diff --git a/build.conf b/build.conf index bcdf419f..9a936098 100644 --- a/build.conf +++ b/build.conf @@ -8,7 +8,7 @@ # # version must always start with "v" like: v0.1.45-rc -VERSION=v0.5.0-rc +VERSION=v0.5.0 # This must match the tags in the github repository @@ -25,7 +25,7 @@ RASPBIAN_ARM_DOWNLOAD_URL="https://downloads.raspberrypi.org/raspios_lite_armhf/ RASPBIAN_ARM64_DOWNLOAD_URL="https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2021-05-28/2021-05-07-raspios-buster-arm64-lite.zip" # Skywire release download for OS running on destination skyminer -SKYWIRE_VERSION=v0.6.0-rc1 +SKYWIRE_VERSION=v0.6.0 SKYWIRE_ARM64_DOWNLOAD_URL="https://github.com/skycoin/skywire/releases/download/$SKYWIRE_VERSION/skywire-$SKYWIRE_VERSION-linux-arm64.tar.gz" SKYWIRE_ARM_DOWNLOAD_URL="https://github.com/skycoin/skywire/releases/download/$SKYWIRE_VERSION/skywire-$SKYWIRE_VERSION-linux-arm.tar.gz" diff --git a/go.mod b/go.mod index 457dd73b..2c46ec30 100644 --- a/go.mod +++ b/go.mod @@ -5,17 +5,16 @@ go 1.16 require ( fyne.io/fyne/v2 v2.1.0 - github.com/fyne-io/fyne-cross v1.1.3 // indirect github.com/google/go-github v17.0.0+incompatible github.com/mholt/archiver v3.1.1+incompatible github.com/rakyll/statik v0.1.7 github.com/sirupsen/logrus v1.8.1 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 - github.com/skycoin/dmsg v0.0.0-20211125122021-388f2fc645c9 + github.com/skycoin/dmsg v0.0.0-20220125112430-1dfce6ea8ef3 github.com/skycoin/skycoin v0.27.1 - github.com/skycoin/skywire v0.5.2-0.20211125164518-be38adb86ad3 - github.com/stretchr/testify v1.6.1 - golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 + github.com/skycoin/skywire v0.6.0-rc2.0.20220211172508-37eabd36ef15 + github.com/stretchr/testify v1.7.0 + golang.org/x/net v0.0.0-20211020060615-d418f374d309 ) // Uncomment it for tests with alternative branches and run `make dep` diff --git a/go.sum b/go.sum index eec2244e..89a9267c 100644 --- a/go.sum +++ b/go.sum @@ -2,65 +2,120 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= fyne.io/fyne/v2 v2.1.0 h1:qzdkaXL/UpmMtG4FlsX9xMZ0Q93CRzLxkoiSXyplP/I= fyne.io/fyne/v2 v2.1.0/go.mod h1:c1vwI38Ebd0dAdxVa6H1Pj6/+cK1xtDy61+I31g+s14= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/ActiveState/termtest/conpty v0.5.0 h1:JLUe6YDs4Jw4xNPCU+8VwTpniYOGeKzQg4SM2YHQNA8= github.com/ActiveState/termtest/conpty v0.5.0/go.mod h1:LO4208FLsxw6DcNZ1UtuGUMW+ga9PFtX4ntv8Ymg9og= github.com/AudriusButkevicius/pfilter v0.0.0-20210515103320-4b4b86609d51 h1:77WF6PJZQiA3OMt8Nl+PH/dbkszumosxunW36ZQj2QQ= github.com/AudriusButkevicius/pfilter v0.0.0-20210515103320-4b4b86609d51/go.mod h1:EEEtt5r8y0gGHlRFF2+cLx0WUy/rKHnjALmom5E0+74= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/metrics v1.12.3/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE= -github.com/VictoriaMetrics/metrics v1.17.2 h1:9zPJ7DPfxdJWshOGLPLpAtPL0ZZ9AeUyQC3fIqG6Lvo= -github.com/VictoriaMetrics/metrics v1.17.2/go.mod h1:Z1tSfPfngDn12bTfZSCqArT3OPY3u88J12hSoOhuiRE= +github.com/VictoriaMetrics/metrics v1.18.0 h1:vov5NxDHRSXFbdiH4dYLYEjKLoAXXSQ7hcnG8TSD9JQ= +github.com/VictoriaMetrics/metrics v1.18.0/go.mod h1:ArjwVz7WpgpegX/JpB0zpNF2h2232kErkEnzH1sxMmA= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029 h1:POmUHfxXdeyM8Aomg4tKDcwATCFuW+cYLkj6pwsw9pc= github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029/go.mod h1:Rpr5n9cGHYdM3S3IK8ROSUUUYjQOu+MSUCZDcJbYWi8= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.15 h1:cKRCLMj3Ddm54bKSpemfQ8AtYFBhAI2MPmdys22fBdc= github.com/creack/pty v1.1.15/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA= @@ -68,9 +123,7 @@ github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUv github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fyne-io/fyne-cross v1.1.3 h1:LT9giTMLaLt/fNmxPEOCkaHxQJNQu/utY0Ugwe1yFjw= -github.com/fyne-io/fyne-cross v1.1.3/go.mod h1:rFwn/M7pkAVZkQTndaD3i5DbZ5oTMJIEWDCF2w7d60Q= -github.com/gen2brain/dlgs v0.0.0-20210609125024-bf6c92aaa984/go.mod h1:/eFcjDXaU2THSOOqLxOPETIbHETnamk8FA/hMjhg/gU= +github.com/gen2brain/dlgs v0.0.0-20210911090025-cbd38e821b98/go.mod h1:/eFcjDXaU2THSOOqLxOPETIbHETnamk8FA/hMjhg/gU= github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY= github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A= github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A= @@ -89,46 +142,62 @@ github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxm github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f h1:s0O46d8fPwk9kU4k1jj76wBquMVETx7uveQD9MCIQoU= github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb h1:T6gaWBvRzJjuOrdCtg8fXXjKai2xSDqWTcKFUPuw8Tw= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210410170116-ea3d685f79fb/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8= github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -137,6 +206,13 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= @@ -144,38 +220,76 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= +github.com/james-barrow/golang-ipc v0.0.0-20210227130457-95e7cc81f5e2 h1:lnIIG509NeyPk/15ZHqP3DwTTQXqp2PoQoxGdYDC2h4= +github.com/james-barrow/golang-ipc v0.0.0-20210227130457-95e7cc81f5e2/go.mod h1:M3eGiVVY7bdtqyWT+gtbIqji7CqHi3PKJHSPl2pP40c= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.0 h1:wJbzvpYMVGG9iTI9VxpnNZfd4DzMPoCWze3GgSqz8yg= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4= @@ -184,7 +298,8 @@ github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54= github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -197,6 +312,7 @@ github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls v0.10.0 h1:ECsuYUKalRL240rRD4Ri33ISb7kAQ3qGDlrrl55b2pc= @@ -204,10 +320,14 @@ github.com/marten-seemann/qtls v0.10.0/go.mod h1:UvMd1oaYDACI99/oZUYLzMCkBXQVT0a github.com/marten-seemann/qtls-go1-15 v0.1.1/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-15 v0.1.4 h1:RehYMOyRW8hPVEja1KBVsFVNSm35Jj9Mvs5yNoZZ28A= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= @@ -216,18 +336,26 @@ github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1w github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/mholt/archiver/v3 v3.3.0/go.mod h1:YnQtqsp+94Rwd0D/rk5cnLrxusUBUXg+08Ebtr1Mqao= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmcloughlin/avo v0.0.0-20200523190732-4439b6b2c061 h1:UCU8+cLbbvyxi0sQ9fSeoEhZgvrrD9HKMtX6Gmc1vk8= github.com/mmcloughlin/avo v0.0.0-20200523190732-4439b6b2c061/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= @@ -237,7 +365,6 @@ github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMB github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -247,7 +374,9 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pires/go-proxyproto v0.3.3/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= @@ -256,26 +385,24 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/progressbar/v2 v2.15.0/go.mod h1:UdPq3prGkfQ7MOzZKlDRpYKcFqEMczbD7YmbPgpzKMI= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil/v3 v3.21.4 h1:XB/+p+kVnyYLuPHCfa99lxz2aJyvVhnyd+FxZqH/k7M= github.com/shirou/gopsutil/v3 v3.21.4/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw= @@ -302,39 +429,39 @@ github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go. github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= -github.com/skycoin/dmsg v0.0.0-20211007145032-962409e5845f h1:0/PJaqsGvkfuf4I/Jg2ayQq0AJg5qhIhK4YzevX72Bg= -github.com/skycoin/dmsg v0.0.0-20211007145032-962409e5845f/go.mod h1:p9RQVoY18Rpi5mrbIfE55z7XcKTscIUiNh8nv1ou1/8= -github.com/skycoin/dmsg v0.0.0-20211125122021-388f2fc645c9 h1:Cy62MJBJkPWc/zoNBnwJC7+ak+Hj20TgwxOMKkhi8mI= -github.com/skycoin/dmsg v0.0.0-20211125122021-388f2fc645c9/go.mod h1:EgRg8fy5RjF67OJlh9w+vhq3+Phyn6AXKSedkzhf1ww= +github.com/skycoin/dmsg v0.0.0-20220125112430-1dfce6ea8ef3 h1:Ja0OyTBk00akywqJbPpPV6wyBX9NtjpyQD64G7oH4RQ= +github.com/skycoin/dmsg v0.0.0-20220125112430-1dfce6ea8ef3/go.mod h1:EgRg8fy5RjF67OJlh9w+vhq3+Phyn6AXKSedkzhf1ww= github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6 h1:1Nc5EBY6pjfw1kwW0duwyG+7WliWz5u9kgk1h5MnLuA= github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:UXghlricA7J3aRD/k7p/zBObQfmBawwCxIVPVjz2Q3o= github.com/skycoin/skycoin v0.26.0/go.mod h1:78nHjQzd8KG0jJJVL/j0xMmrihXi70ti63fh8vXScJw= github.com/skycoin/skycoin v0.27.1 h1:HatxsRwVSPaV4qxH6290xPBmkH/HgiuAoY2qC+e8C9I= github.com/skycoin/skycoin v0.27.1/go.mod h1:78nHjQzd8KG0jJJVL/j0xMmrihXi70ti63fh8vXScJw= -github.com/skycoin/skywire v0.5.2-0.20211124111242-1d90a0492f62 h1:rn4w5R7w+oJPfECHESeTBUBPKcMJYbmea+0nbtJ3gjY= -github.com/skycoin/skywire v0.5.2-0.20211124111242-1d90a0492f62/go.mod h1:H35tSOwurUtc25Pm2lr5vLQIm8tzrfJV92mSUb2dXvY= -github.com/skycoin/skywire v0.5.2-0.20211125164518-be38adb86ad3 h1:Tj1S6wEx3r9czfrWpqcVgonM+mWb62QTKjm89zVL4rs= -github.com/skycoin/skywire v0.5.2-0.20211125164518-be38adb86ad3/go.mod h1:rUwrKlHSt1UQQ5uyip1OXWmBejOyBOrNomXqTM+UEZA= +github.com/skycoin/skywire v0.6.0-rc2.0.20220211172508-37eabd36ef15 h1:enCy1Tob+BuRGAL6erN3Z0UTmRl5YQLd3U8tgDOuf7Y= +github.com/skycoin/skywire v0.6.0-rc2.0.20220211172508-37eabd36ef15/go.mod h1:OoPAzzy1MbpgSDKmUHH5151oulZBGobHqmAd7R3Qo2w= github.com/skycoin/yamux v0.0.0-20200803175205-571ceb89da9f h1:A5dEM1OE9YhN3LciZU9qPjo7fJ46JeHNi3JCroDkK0Y= github.com/skycoin/yamux v0.0.0-20200803175205-571ceb89da9f/go.mod h1:48cleOxgkiLbgv322LOg2Vrxtu180Mb8GG1HbuhmFYM= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM= github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM= @@ -346,108 +473,182 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= -github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM= -github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.0 h1:8nbaiZG+iVdh+fXVw0DZoZZa7a4TGm3Qab+xdrdzj8s= +github.com/tjfoc/gmsm v1.4.0/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tklauser/go-sysconf v0.3.4 h1:HT8SVixZd3IzLdfs/xlpq0jeSfTX57g1v6wB1EuzV7M= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= github.com/tklauser/numcpus v0.2.1 h1:ct88eFm+Q7m2ZfXJdan1xYoXKlmwsfP+k88q05KvlZc= github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI= github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= -github.com/valyala/histogram v1.1.2 h1:vOk5VrGjMBIoPR5k6wA8vBaC8toeJ8XO0yfRjFEc1h8= +github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= +github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/histogram v1.1.2/go.mod h1:CZAr6gK9dbD7hYx2s8WSPh0p5x5wETjC+2b3PJVtEdg= +github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= +github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg= github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.8 h1:Nw158Q8QN+CPgTmVRByhVwapp8Mm1e2blinhmx4wx5E= github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210927181540-4e4d966f7476/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI= +golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -455,69 +656,146 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201231184435-2d18734c6014/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo= +golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210406210042-72f3dc4e9b72/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -526,57 +804,154 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.zx2c4.com/wireguard v0.0.20200320/go.mod h1:lDian4Sw4poJ04SgHh35nzMVwGSYlPumkdnHcucAQoY= +golang.zx2c4.com/wireguard v0.0.0-20211012180210-dfd688b6aa7b/go.mod h1:id8Oh3eCCmpj9uVGWVjsUAl6UPX5ysMLzu6QxJU2UOU= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +nhooyr.io/websocket v1.8.2 h1:LwdzfyyOZKtVFoXay6A39Acu03KmidSZ3YUUvPa13PA= nhooyr.io/websocket v1.8.2/go.mod h1:LiqdCg1Cu7TPWxEvPjPa0TGYxCsy4pHNTN9gGluwBpQ= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/pkg/imager/fyne_pages.go b/pkg/imager/fyne_pages.go index ea071904..722e64f7 100644 --- a/pkg/imager/fyne_pages.go +++ b/pkg/imager/fyne_pages.go @@ -214,10 +214,10 @@ func (fg *FyneUI) Page2() fyne.CanvasObject { genHvImg.SetChecked(fg.hvImg) useDMSGHTTP := widget.NewCheck("Use dmsgHTTP.", func(b bool) { - if b { - fg.dmsghttp = b - } + fg.dmsghttp = b + fg.log.Debugf("Set: fg.useDMSGHTTP = %v", b) }) + genHvImg.SetChecked(fg.dmsghttp) hvPKs := container.NewVBox() hvPKs.Hide() diff --git a/vendor/github.com/ActiveState/termtest/conpty/LICENSE b/vendor/github.com/ActiveState/termtest/conpty/LICENSE new file mode 100644 index 00000000..0ea09c8e --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020, ActiveState Software +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ActiveState/termtest/conpty/README.md b/vendor/github.com/ActiveState/termtest/conpty/README.md new file mode 100644 index 00000000..fb093f85 --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/README.md @@ -0,0 +1,23 @@ +# termtest/conpty + +Support for the [Windows pseudo +console](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/) +in Go. + +Developed as part of the cross-platform terminal automation library +[expect](https://github.com/ActiveState/termtest/expect) for the [ActiveState +state tool](https://www.activestate.com/products/platform/state-tool/). + +## Example + +See ./cmd/example/main.go + +## Client configuration + +On Windows, you may have to adjust the programme that you are running in the +pseudo-console, by configuring the standard output handler to process virtual +terminal codes. See https://docs.microsoft.com/en-us/windows/console/setconsolemode + +This package comes with a convenience function `InitTerminal()` that you can +use in your client to set this option. + diff --git a/vendor/github.com/ActiveState/termtest/conpty/conpty_windows.go b/vendor/github.com/ActiveState/termtest/conpty/conpty_windows.go new file mode 100644 index 00000000..e0a1821f --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/conpty_windows.go @@ -0,0 +1,250 @@ +// Copyright 2020 ActiveState Software. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file + +package conpty + +import ( + "fmt" + "log" + "os" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +// ConPty represents a windows pseudo console. +// Attach a process to it by calling the Spawn() method. +// You can send UTF encoded commands to it with Write() and listen to +// its output stream by accessing the output pipe via OutPipe() +type ConPty struct { + hpCon *windows.Handle + pipeFdIn windows.Handle + pipeFdOut windows.Handle + startupInfo startupInfoEx + consoleSize uintptr + inPipe *os.File + outPipe *os.File + attributeListBuffer []byte +} + +// New returns a new ConPty pseudo terminal device +func New(columns int16, rows int16) (c *ConPty, err error) { + c = &ConPty{ + hpCon: new(windows.Handle), + startupInfo: startupInfoEx{}, + consoleSize: uintptr(columns) + (uintptr(rows) << 16), + } + err = c.createPseudoConsoleAndPipes() + if err != nil { + return nil, err + } + err = c.initializeStartupInfoAttachedToPTY() + if err != nil { + return nil, err + } + return +} + +// Close closes the pseudo-terminal and cleans up all attached resources +func (c *ConPty) Close() (err error) { + err = deleteProcThreadAttributeList(c.startupInfo.lpAttributeList) + if err != nil { + log.Printf("Failed to free delete proc thread attribute list: %v", err) + } + /* + _, err = windows.LocalFree(c.startupInfo.lpAttributeList) + if err != nil { + log.Printf("Failed to free the lpAttributeList") + } + */ + err = closePseudoConsole(*c.hpCon) + if err != nil { + log.Printf("Failed to close pseudo console: %v", err) + } + c.inPipe.Close() + c.outPipe.Close() + return +} + +// OutPipe returns the output pipe of the pseudo terminal +func (c *ConPty) OutPipe() *os.File { + return c.outPipe +} + +// InPipe returns input pipe of the pseudo terminal +// Note: It is safer to use the Write method to prevent partially-written VT sequences +// from corrupting the terminal +func (c *ConPty) InPipe() *os.File { + return c.inPipe +} + +func (c *ConPty) OutFd() uintptr { + return c.outPipe.Fd() +} + +// Write safely writes bytes to the pseudo terminal +func (c *ConPty) Write(buf []byte) (uint32, error) { + var n uint32 + err := windows.WriteFile(c.pipeFdIn, buf, &n, nil) + return n, err +} + +var zeroProcAttr syscall.ProcAttr + +// Spawn spawns a new process attached to the pseudo terminal +func (c *ConPty) Spawn(argv0 string, argv []string, attr *syscall.ProcAttr) (pid int, handle uintptr, err error) { + + if attr == nil { + attr = &zeroProcAttr + } + + if attr.Sys != nil { + log.Printf("Warning: SysProc attributes are not supported by Spawn.") + } + + if len(attr.Files) != 0 { + log.Printf("Warning: Ignoring 'Files' attribute in ProcAttr argument.") + } + + if len(attr.Dir) != 0 { + // StartProcess assumes that argv0 is relative to attr.Dir, + // because it implies Chdir(attr.Dir) before executing argv0. + // Windows CreateProcess assumes the opposite: it looks for + // argv0 relative to the current directory, and, only once the new + // process is started, it does Chdir(attr.Dir). We are adjusting + // for that difference here by making argv0 absolute. + var err error + argv0, err = joinExeDirAndFName(attr.Dir, argv0) + if err != nil { + return 0, 0, err + } + } + argv0p, err := windows.UTF16PtrFromString(argv0) + if err != nil { + return 0, 0, err + } + + // Windows CreateProcess takes the command line as a single string: + // use attr.CmdLine if set, else build the command line by escaping + // and joining each argument with spaces + cmdline := makeCmdLine(argv) + + var argvp *uint16 + if len(cmdline) != 0 { + argvp, err = windows.UTF16PtrFromString(cmdline) + if err != nil { + return 0, 0, err + } + } + + var dirp *uint16 + if len(attr.Dir) != 0 { + dirp, err = windows.UTF16PtrFromString(attr.Dir) + if err != nil { + return 0, 0, err + } + } + + c.startupInfo.startupInfo.Flags = windows.STARTF_USESTDHANDLES + + pi := new(windows.ProcessInformation) + + flags := uint32(windows.CREATE_UNICODE_ENVIRONMENT) | extendedStartupinfoPresent + + var zeroSec windows.SecurityAttributes + pSec := &windows.SecurityAttributes{Length: uint32(unsafe.Sizeof(zeroSec)), InheritHandle: 1} + tSec := &windows.SecurityAttributes{Length: uint32(unsafe.Sizeof(zeroSec)), InheritHandle: 1} + + // c.startupInfo.startupInfo.Cb = uint32(unsafe.Sizeof(c.startupInfo)) + err = windows.CreateProcess( + argv0p, + argvp, + pSec, // process handle not inheritable + tSec, // thread handles not inheritable, + false, + flags, + createEnvBlock(addCriticalEnv(dedupEnvCase(true, attr.Env))), + dirp, // use current directory later: dirp, + &c.startupInfo.startupInfo, + pi) + + if err != nil { + return 0, 0, err + } + defer windows.CloseHandle(windows.Handle(pi.Thread)) + + return int(pi.ProcessId), uintptr(pi.Process), nil +} + +func (c *ConPty) createPseudoConsoleAndPipes() (err error) { + var hPipePTYIn windows.Handle + var hPipePTYOut windows.Handle + + if err := windows.CreatePipe(&hPipePTYIn, &c.pipeFdIn, nil, 0); err != nil { + log.Fatalf("Failed to create PTY input pipe: %v", err) + } + if err := windows.CreatePipe(&c.pipeFdOut, &hPipePTYOut, nil, 0); err != nil { + log.Fatalf("Failed to create PTY output pipe: %v", err) + } + + err = createPseudoConsole(c.consoleSize, hPipePTYIn, hPipePTYOut, c.hpCon) + if err != nil { + return fmt.Errorf("failed to create pseudo console: %d, %v", uintptr(*c.hpCon), err) + } + + // Note: We can close the handles to the PTY-end of the pipes here + // because the handles are dup'ed into the ConHost and will be released + // when the ConPTY is destroyed. + if hPipePTYOut != windows.InvalidHandle { + windows.CloseHandle(hPipePTYOut) + } + if hPipePTYIn != windows.InvalidHandle { + windows.CloseHandle(hPipePTYIn) + } + + c.inPipe = os.NewFile(uintptr(c.pipeFdIn), "|0") + c.outPipe = os.NewFile(uintptr(c.pipeFdOut), "|1") + + return +} + +func (c *ConPty) Resize(cols uint16, rows uint16) error { + return resizePseudoConsole(*c.hpCon, uintptr(cols)+(uintptr(rows)<<16)) +} + +func (c *ConPty) initializeStartupInfoAttachedToPTY() (err error) { + + var attrListSize uint64 + c.startupInfo.startupInfo.Cb = uint32(unsafe.Sizeof(c.startupInfo)) + + err = initializeProcThreadAttributeList(0, 1, &attrListSize) + if err != nil { + return fmt.Errorf("could not retrieve list size: %v", err) + } + + c.attributeListBuffer = make([]byte, attrListSize) + // c.startupInfo.lpAttributeList, err = localAlloc(attrListSize) + // if err != nil { + // return fmt.Errorf("Could not allocate local memory: %v", err) + // } + + c.startupInfo.lpAttributeList = windows.Handle(unsafe.Pointer(&c.attributeListBuffer[0])) + + err = initializeProcThreadAttributeList(uintptr(c.startupInfo.lpAttributeList), 1, &attrListSize) + if err != nil { + return fmt.Errorf("failed to initialize proc thread attributes for conpty: %v", err) + } + + err = updateProcThreadAttributeList( + c.startupInfo.lpAttributeList, + procThreadAttributePseudoconsole, + *c.hpCon, + unsafe.Sizeof(*c.hpCon)) + if err != nil { + return fmt.Errorf("failed to update proc thread attributes attributes for conpty usage: %v", err) + } + + return +} diff --git a/vendor/github.com/ActiveState/termtest/conpty/doc.go b/vendor/github.com/ActiveState/termtest/conpty/doc.go new file mode 100644 index 00000000..b423fb62 --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/doc.go @@ -0,0 +1,11 @@ +// Copyright 2020 ActiveState Software. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file + +// Package conpty provides functions for creating a process attached to a +// ConPTY pseudo-terminal. This allows the process to call console specific +// API functions without an actual terminal being present. +// +// The concept is best explained in this blog post: +// https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/ +package conpty diff --git a/vendor/github.com/ActiveState/termtest/conpty/exec_windows.go b/vendor/github.com/ActiveState/termtest/conpty/exec_windows.go new file mode 100644 index 00000000..6d077705 --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/exec_windows.go @@ -0,0 +1,161 @@ +// Copyright 2009 The Go Authors. All rights reserved. + +// This file has copies of unexported functions form the go source code, +// hence the above copyright message + +package conpty + +import ( + "os" + "strings" + "syscall" + "unicode/utf16" + + "golang.org/x/sys/windows" +) + +// makeCmdLine builds a command line out of args by escaping "special" +// characters and joining the arguments with spaces. +func makeCmdLine(args []string) string { + var s string + for _, v := range args { + if s != "" { + s += " " + } + s += windows.EscapeArg(v) + } + return s +} + +func isSlash(c uint8) bool { + return c == '\\' || c == '/' +} + +func normalizeDir(dir string) (name string, err error) { + ndir, err := syscall.FullPath(dir) + if err != nil { + return "", err + } + if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) { + // dir cannot have \\server\share\path form + return "", syscall.EINVAL + } + return ndir, nil +} + +func volToUpper(ch int) int { + if 'a' <= ch && ch <= 'z' { + ch += 'A' - 'a' + } + return ch +} + +func joinExeDirAndFName(dir, p string) (name string, err error) { + if len(p) == 0 { + return "", syscall.EINVAL + } + if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) { + // \\server\share\path form + return p, nil + } + if len(p) > 1 && p[1] == ':' { + // has drive letter + if len(p) == 2 { + return "", syscall.EINVAL + } + if isSlash(p[2]) { + return p, nil + } else { + d, err := normalizeDir(dir) + if err != nil { + return "", err + } + if volToUpper(int(p[0])) == volToUpper(int(d[0])) { + return syscall.FullPath(d + "\\" + p[2:]) + } else { + return syscall.FullPath(p) + } + } + } else { + // no drive letter + d, err := normalizeDir(dir) + if err != nil { + return "", err + } + if isSlash(p[0]) { + return windows.FullPath(d[:2] + p) + } else { + return windows.FullPath(d + "\\" + p) + } + } +} + +// createEnvBlock converts an array of environment strings into +// the representation required by CreateProcess: a sequence of NUL +// terminated strings followed by a nil. +// Last bytes are two UCS-2 NULs, or four NUL bytes. +func createEnvBlock(envv []string) *uint16 { + if len(envv) == 0 { + return &utf16.Encode([]rune("\x00\x00"))[0] + } + length := 0 + for _, s := range envv { + length += len(s) + 1 + } + length += 1 + + b := make([]byte, length) + i := 0 + for _, s := range envv { + l := len(s) + copy(b[i:i+l], []byte(s)) + copy(b[i+l:i+l+1], []byte{0}) + i = i + l + 1 + } + copy(b[i:i+1], []byte{0}) + + return &utf16.Encode([]rune(string(b)))[0] +} + +// dedupEnvCase is dedupEnv with a case option for testing. +// If caseInsensitive is true, the case of keys is ignored. +func dedupEnvCase(caseInsensitive bool, env []string) []string { + out := make([]string, 0, len(env)) + saw := make(map[string]int, len(env)) // key => index into out + for _, kv := range env { + eq := strings.Index(kv, "=") + if eq < 0 { + out = append(out, kv) + continue + } + k := kv[:eq] + if caseInsensitive { + k = strings.ToLower(k) + } + if dupIdx, isDup := saw[k]; isDup { + out[dupIdx] = kv + continue + } + saw[k] = len(out) + out = append(out, kv) + } + return out +} + +// addCriticalEnv adds any critical environment variables that are required +// (or at least almost always required) on the operating system. +// Currently this is only used for Windows. +func addCriticalEnv(env []string) []string { + for _, kv := range env { + eq := strings.Index(kv, "=") + if eq < 0 { + continue + } + k := kv[:eq] + if strings.EqualFold(k, "SYSTEMROOT") { + // We already have it. + return env + } + } + return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT")) +} diff --git a/vendor/github.com/ActiveState/termtest/conpty/go.mod b/vendor/github.com/ActiveState/termtest/conpty/go.mod new file mode 100644 index 00000000..67bb0a5f --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/go.mod @@ -0,0 +1,8 @@ +module github.com/ActiveState/termtest/conpty + +go 1.12 + +require ( + github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 + golang.org/x/sys v0.0.0-20200428200454-593003d681fa +) diff --git a/vendor/github.com/ActiveState/termtest/conpty/go.sum b/vendor/github.com/ActiveState/termtest/conpty/go.sum new file mode 100644 index 00000000..c1c7bf67 --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/go.sum @@ -0,0 +1,4 @@ +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +golang.org/x/sys v0.0.0-20200428200454-593003d681fa h1:yMbJOvnfYkO1dSAviTu/ZguZWLBTXx4xE3LYrxUCCiA= +golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/ActiveState/termtest/conpty/syscall_windows.go b/vendor/github.com/ActiveState/termtest/conpty/syscall_windows.go new file mode 100644 index 00000000..37504311 --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/syscall_windows.go @@ -0,0 +1,112 @@ +// Copyright 2020 ActiveState Software. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file + +package conpty + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +// load some windows system procedures + +var ( + kernel32 = windows.NewLazySystemDLL("kernel32.dll") + procResizePseudoConsole = kernel32.NewProc("ResizePseudoConsole") + procCreatePseudoConsole = kernel32.NewProc("CreatePseudoConsole") + procClosePseudoConsole = kernel32.NewProc("ClosePseudoConsole") + procInitializeProcThreadAttributeList = kernel32.NewProc("InitializeProcThreadAttributeList") + procUpdateProcThreadAttribute = kernel32.NewProc("UpdateProcThreadAttribute") + procLocalAlloc = kernel32.NewProc("LocalAlloc") + procDeleteProcThreadAttributeList = kernel32.NewProc("DeleteProcThreadAttributeList") + procCreateProcessW = kernel32.NewProc("CreateProcessW") +) + +// an extended version of a process startup info, the attribute list points +// to a pseudo terminal object +type startupInfoEx struct { + startupInfo windows.StartupInfo + lpAttributeList windows.Handle +} + +// constant used in CreateProcessW indicating that extended startup info is present +const extendedStartupinfoPresent uint32 = 0x00080000 + +type procThreadAttribute uintptr + +// windows constant needed during initialization of extended startupinfo +const procThreadAttributePseudoconsole procThreadAttribute = 22 | 0x00020000 // this is the only one we support right now + +func initializeProcThreadAttributeList(attributeList uintptr, attributeCount uint32, listSize *uint64) (err error) { + + if attributeList == 0 { + procInitializeProcThreadAttributeList.Call(0, uintptr(attributeCount), 0, uintptr(unsafe.Pointer(listSize))) + return + } + r1, _, e1 := procInitializeProcThreadAttributeList.Call(attributeList, uintptr(attributeCount), 0, uintptr(unsafe.Pointer(listSize))) + + if r1 == 0 { // boolean FALSE + err = e1 + } + + return +} + +func updateProcThreadAttributeList(attributeList windows.Handle, attribute procThreadAttribute, lpValue windows.Handle, lpSize uintptr) (err error) { + + r1, _, e1 := procUpdateProcThreadAttribute.Call(uintptr(attributeList), 0, uintptr(attribute), uintptr(lpValue), lpSize, 0, 0) + + if r1 == 0 { // boolean FALSE + err = e1 + } + + return +} +func deleteProcThreadAttributeList(handle windows.Handle) (err error) { + r1, _, e1 := procDeleteProcThreadAttributeList.Call(uintptr(handle)) + + if r1 == 0 { // boolean FALSE + err = e1 + } + + return +} + +func localAlloc(size uint64) (ptr windows.Handle, err error) { + r1, _, e1 := procLocalAlloc.Call(uintptr(0x0040), uintptr(size)) + if r1 == 0 { + err = e1 + ptr = windows.InvalidHandle + return + } + ptr = windows.Handle(r1) + return +} + +func createPseudoConsole(consoleSize uintptr, ptyIn windows.Handle, ptyOut windows.Handle, hpCon *windows.Handle) (err error) { + r1, _, e1 := procCreatePseudoConsole.Call(consoleSize, uintptr(ptyIn), uintptr(ptyOut), 0, uintptr(unsafe.Pointer(hpCon))) + + if r1 != 0 { // !S_OK + err = e1 + } + return +} + +func resizePseudoConsole(handle windows.Handle, consoleSize uintptr) (err error) { + r1, _, e1 := procResizePseudoConsole.Call(uintptr(handle), consoleSize) + if r1 != 0 { // !S_OK + err = e1 + } + return +} + +func closePseudoConsole(handle windows.Handle) (err error) { + r1, _, e1 := procClosePseudoConsole.Call(uintptr(handle)) + if r1 == 0 { + err = e1 + } + + return +} diff --git a/vendor/github.com/ActiveState/termtest/conpty/term_other.go b/vendor/github.com/ActiveState/termtest/conpty/term_other.go new file mode 100644 index 00000000..daef1c07 --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/term_other.go @@ -0,0 +1,7 @@ +// +build !windows + +package conpty + +func InitTerminal(_ bool) (func(), error) { + return func() {}, nil +} diff --git a/vendor/github.com/ActiveState/termtest/conpty/term_windows.go b/vendor/github.com/ActiveState/termtest/conpty/term_windows.go new file mode 100644 index 00000000..df091b5b --- /dev/null +++ b/vendor/github.com/ActiveState/termtest/conpty/term_windows.go @@ -0,0 +1,61 @@ +// +build windows + +package conpty + +import ( + "fmt" + "log" + "syscall" + + "github.com/Azure/go-ansiterm/winterm" +) + +func InitTerminal(disableNewlineAutoReturn bool) (func(), error) { + stdoutFd := int(syscall.Stdout) + + // fmt.Printf("file descriptors <%d >%d\n", stdinFd, stdoutFd) + + oldOutMode, err := winterm.GetConsoleMode(uintptr(stdoutFd)) + if err != nil { + return func() {}, fmt.Errorf("failed to retrieve stdout mode: %w", err) + } + + // fmt.Printf("old modes: <%d >%d\n", oldInMode, oldOutMode) + newOutMode := oldOutMode | winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING + if disableNewlineAutoReturn { + newOutMode |= winterm.DISABLE_NEWLINE_AUTO_RETURN + } + + err = winterm.SetConsoleMode(uintptr(stdoutFd), newOutMode) + if err != nil { + return func() {}, fmt.Errorf("failed to set stdout mode: %w", err) + } + + // dump(uintptr(stdoutFd)) + return func() { + err = winterm.SetConsoleMode(uintptr(stdoutFd), oldOutMode) + if err != nil { + log.Fatalf("Failed to reset output terminal mode to %d: %v\n", oldOutMode, err) + } + }, nil +} + +func dump(fd uintptr) { + fmt.Printf("FD=%d\n", fd) + modes, err := winterm.GetConsoleMode(fd) + if err != nil { + panic(err) + } + + fmt.Printf("ENABLE_ECHO_INPUT=%d, ENABLE_PROCESSED_INPUT=%d ENABLE_LINE_INPUT=%d\n", + modes&winterm.ENABLE_ECHO_INPUT, + modes&winterm.ENABLE_PROCESSED_INPUT, + modes&winterm.ENABLE_LINE_INPUT) + fmt.Printf("ENABLE_WINDOW_INPUT=%d, ENABLE_MOUSE_INPUT=%d\n", + modes&winterm.ENABLE_WINDOW_INPUT, + modes&winterm.ENABLE_MOUSE_INPUT) + fmt.Printf("enableVirtualTerminalInput=%d, enableVirtualTerminalProcessing=%d, disableNewlineAutoReturn=%d\n", + modes&winterm.ENABLE_VIRTUAL_TERMINAL_INPUT, + modes&winterm.ENABLE_VIRTUAL_TERMINAL_PROCESSING, + modes&winterm.DISABLE_NEWLINE_AUTO_RETURN) +} diff --git a/vendor/github.com/Azure/go-ansiterm/LICENSE b/vendor/github.com/Azure/go-ansiterm/LICENSE new file mode 100644 index 00000000..e3d9a64d --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/Azure/go-ansiterm/README.md b/vendor/github.com/Azure/go-ansiterm/README.md new file mode 100644 index 00000000..261c041e --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/README.md @@ -0,0 +1,12 @@ +# go-ansiterm + +This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent. + +For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position. + +The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go). + +See parser_test.go for examples exercising the state machine and generating appropriate function calls. + +----- +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/vendor/github.com/Azure/go-ansiterm/constants.go b/vendor/github.com/Azure/go-ansiterm/constants.go new file mode 100644 index 00000000..96504a33 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/constants.go @@ -0,0 +1,188 @@ +package ansiterm + +const LogEnv = "DEBUG_TERMINAL" + +// ANSI constants +// References: +// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm +// -- http://man7.org/linux/man-pages/man4/console_codes.4.html +// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html +// -- http://en.wikipedia.org/wiki/ANSI_escape_code +// -- http://vt100.net/emu/dec_ansi_parser +// -- http://vt100.net/emu/vt500_parser.svg +// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html +// -- http://www.inwap.com/pdp10/ansicode.txt +const ( + // ECMA-48 Set Graphics Rendition + // Note: + // -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved + // -- Fonts could possibly be supported via SetCurrentConsoleFontEx + // -- Windows does not expose the per-window cursor (i.e., caret) blink times + ANSI_SGR_RESET = 0 + ANSI_SGR_BOLD = 1 + ANSI_SGR_DIM = 2 + _ANSI_SGR_ITALIC = 3 + ANSI_SGR_UNDERLINE = 4 + _ANSI_SGR_BLINKSLOW = 5 + _ANSI_SGR_BLINKFAST = 6 + ANSI_SGR_REVERSE = 7 + _ANSI_SGR_INVISIBLE = 8 + _ANSI_SGR_LINETHROUGH = 9 + _ANSI_SGR_FONT_00 = 10 + _ANSI_SGR_FONT_01 = 11 + _ANSI_SGR_FONT_02 = 12 + _ANSI_SGR_FONT_03 = 13 + _ANSI_SGR_FONT_04 = 14 + _ANSI_SGR_FONT_05 = 15 + _ANSI_SGR_FONT_06 = 16 + _ANSI_SGR_FONT_07 = 17 + _ANSI_SGR_FONT_08 = 18 + _ANSI_SGR_FONT_09 = 19 + _ANSI_SGR_FONT_10 = 20 + _ANSI_SGR_DOUBLEUNDERLINE = 21 + ANSI_SGR_BOLD_DIM_OFF = 22 + _ANSI_SGR_ITALIC_OFF = 23 + ANSI_SGR_UNDERLINE_OFF = 24 + _ANSI_SGR_BLINK_OFF = 25 + _ANSI_SGR_RESERVED_00 = 26 + ANSI_SGR_REVERSE_OFF = 27 + _ANSI_SGR_INVISIBLE_OFF = 28 + _ANSI_SGR_LINETHROUGH_OFF = 29 + ANSI_SGR_FOREGROUND_BLACK = 30 + ANSI_SGR_FOREGROUND_RED = 31 + ANSI_SGR_FOREGROUND_GREEN = 32 + ANSI_SGR_FOREGROUND_YELLOW = 33 + ANSI_SGR_FOREGROUND_BLUE = 34 + ANSI_SGR_FOREGROUND_MAGENTA = 35 + ANSI_SGR_FOREGROUND_CYAN = 36 + ANSI_SGR_FOREGROUND_WHITE = 37 + _ANSI_SGR_RESERVED_01 = 38 + ANSI_SGR_FOREGROUND_DEFAULT = 39 + ANSI_SGR_BACKGROUND_BLACK = 40 + ANSI_SGR_BACKGROUND_RED = 41 + ANSI_SGR_BACKGROUND_GREEN = 42 + ANSI_SGR_BACKGROUND_YELLOW = 43 + ANSI_SGR_BACKGROUND_BLUE = 44 + ANSI_SGR_BACKGROUND_MAGENTA = 45 + ANSI_SGR_BACKGROUND_CYAN = 46 + ANSI_SGR_BACKGROUND_WHITE = 47 + _ANSI_SGR_RESERVED_02 = 48 + ANSI_SGR_BACKGROUND_DEFAULT = 49 + // 50 - 65: Unsupported + + ANSI_MAX_CMD_LENGTH = 4096 + + MAX_INPUT_EVENTS = 128 + DEFAULT_WIDTH = 80 + DEFAULT_HEIGHT = 24 + + ANSI_BEL = 0x07 + ANSI_BACKSPACE = 0x08 + ANSI_TAB = 0x09 + ANSI_LINE_FEED = 0x0A + ANSI_VERTICAL_TAB = 0x0B + ANSI_FORM_FEED = 0x0C + ANSI_CARRIAGE_RETURN = 0x0D + ANSI_ESCAPE_PRIMARY = 0x1B + ANSI_ESCAPE_SECONDARY = 0x5B + ANSI_OSC_STRING_ENTRY = 0x5D + ANSI_COMMAND_FIRST = 0x40 + ANSI_COMMAND_LAST = 0x7E + DCS_ENTRY = 0x90 + CSI_ENTRY = 0x9B + OSC_STRING = 0x9D + ANSI_PARAMETER_SEP = ";" + ANSI_CMD_G0 = '(' + ANSI_CMD_G1 = ')' + ANSI_CMD_G2 = '*' + ANSI_CMD_G3 = '+' + ANSI_CMD_DECPNM = '>' + ANSI_CMD_DECPAM = '=' + ANSI_CMD_OSC = ']' + ANSI_CMD_STR_TERM = '\\' + + KEY_CONTROL_PARAM_2 = ";2" + KEY_CONTROL_PARAM_3 = ";3" + KEY_CONTROL_PARAM_4 = ";4" + KEY_CONTROL_PARAM_5 = ";5" + KEY_CONTROL_PARAM_6 = ";6" + KEY_CONTROL_PARAM_7 = ";7" + KEY_CONTROL_PARAM_8 = ";8" + KEY_ESC_CSI = "\x1B[" + KEY_ESC_N = "\x1BN" + KEY_ESC_O = "\x1BO" + + FILL_CHARACTER = ' ' +) + +func getByteRange(start byte, end byte) []byte { + bytes := make([]byte, 0, 32) + for i := start; i <= end; i++ { + bytes = append(bytes, byte(i)) + } + + return bytes +} + +var toGroundBytes = getToGroundBytes() +var executors = getExecuteBytes() + +// SPACE 20+A0 hex Always and everywhere a blank space +// Intermediate 20-2F hex !"#$%&'()*+,-./ +var intermeds = getByteRange(0x20, 0x2F) + +// Parameters 30-3F hex 0123456789:;<=>? +// CSI Parameters 30-39, 3B hex 0123456789; +var csiParams = getByteRange(0x30, 0x3F) + +var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...) + +// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ +var upperCase = getByteRange(0x40, 0x5F) + +// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~ +var lowerCase = getByteRange(0x60, 0x7E) + +// Alphabetics 40-7E hex (all of upper and lower case) +var alphabetics = append(upperCase, lowerCase...) + +var printables = getByteRange(0x20, 0x7F) + +var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E) +var escapeToGroundBytes = getEscapeToGroundBytes() + +// See http://www.vt100.net/emu/vt500_parser.png for description of the complex +// byte ranges below + +func getEscapeToGroundBytes() []byte { + escapeToGroundBytes := getByteRange(0x30, 0x4F) + escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...) + escapeToGroundBytes = append(escapeToGroundBytes, 0x59) + escapeToGroundBytes = append(escapeToGroundBytes, 0x5A) + escapeToGroundBytes = append(escapeToGroundBytes, 0x5C) + escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...) + return escapeToGroundBytes +} + +func getExecuteBytes() []byte { + executeBytes := getByteRange(0x00, 0x17) + executeBytes = append(executeBytes, 0x19) + executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...) + return executeBytes +} + +func getToGroundBytes() []byte { + groundBytes := []byte{0x18} + groundBytes = append(groundBytes, 0x1A) + groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...) + groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...) + groundBytes = append(groundBytes, 0x99) + groundBytes = append(groundBytes, 0x9A) + groundBytes = append(groundBytes, 0x9C) + return groundBytes +} + +// Delete 7F hex Always and everywhere ignored +// C1 Control 80-9F hex 32 additional control characters +// G1 Displayable A1-FE hex 94 additional displayable characters +// Special A0+FF hex Same as SPACE and DELETE diff --git a/vendor/github.com/Azure/go-ansiterm/context.go b/vendor/github.com/Azure/go-ansiterm/context.go new file mode 100644 index 00000000..8d66e777 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/context.go @@ -0,0 +1,7 @@ +package ansiterm + +type ansiContext struct { + currentChar byte + paramBuffer []byte + interBuffer []byte +} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go new file mode 100644 index 00000000..bcbe00d0 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go @@ -0,0 +1,49 @@ +package ansiterm + +type csiEntryState struct { + baseState +} + +func (csiState csiEntryState) Handle(b byte) (s state, e error) { + csiState.parser.logf("CsiEntry::Handle %#x", b) + + nextState, err := csiState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(alphabetics, b): + return csiState.parser.ground, nil + case sliceContains(csiCollectables, b): + return csiState.parser.csiParam, nil + case sliceContains(executors, b): + return csiState, csiState.parser.execute() + } + + return csiState, nil +} + +func (csiState csiEntryState) Transition(s state) error { + csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) + csiState.baseState.Transition(s) + + switch s { + case csiState.parser.ground: + return csiState.parser.csiDispatch() + case csiState.parser.csiParam: + switch { + case sliceContains(csiParams, csiState.parser.context.currentChar): + csiState.parser.collectParam() + case sliceContains(intermeds, csiState.parser.context.currentChar): + csiState.parser.collectInter() + } + } + + return nil +} + +func (csiState csiEntryState) Enter() error { + csiState.parser.clear() + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go new file mode 100644 index 00000000..7ed5e01c --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go @@ -0,0 +1,38 @@ +package ansiterm + +type csiParamState struct { + baseState +} + +func (csiState csiParamState) Handle(b byte) (s state, e error) { + csiState.parser.logf("CsiParam::Handle %#x", b) + + nextState, err := csiState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(alphabetics, b): + return csiState.parser.ground, nil + case sliceContains(csiCollectables, b): + csiState.parser.collectParam() + return csiState, nil + case sliceContains(executors, b): + return csiState, csiState.parser.execute() + } + + return csiState, nil +} + +func (csiState csiParamState) Transition(s state) error { + csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) + csiState.baseState.Transition(s) + + switch s { + case csiState.parser.ground: + return csiState.parser.csiDispatch() + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go new file mode 100644 index 00000000..1c719db9 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go @@ -0,0 +1,36 @@ +package ansiterm + +type escapeIntermediateState struct { + baseState +} + +func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { + escState.parser.logf("escapeIntermediateState::Handle %#x", b) + nextState, err := escState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(intermeds, b): + return escState, escState.parser.collectInter() + case sliceContains(executors, b): + return escState, escState.parser.execute() + case sliceContains(escapeIntermediateToGroundBytes, b): + return escState.parser.ground, nil + } + + return escState, nil +} + +func (escState escapeIntermediateState) Transition(s state) error { + escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) + escState.baseState.Transition(s) + + switch s { + case escState.parser.ground: + return escState.parser.escDispatch() + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_state.go b/vendor/github.com/Azure/go-ansiterm/escape_state.go new file mode 100644 index 00000000..6390abd2 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/escape_state.go @@ -0,0 +1,47 @@ +package ansiterm + +type escapeState struct { + baseState +} + +func (escState escapeState) Handle(b byte) (s state, e error) { + escState.parser.logf("escapeState::Handle %#x", b) + nextState, err := escState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case b == ANSI_ESCAPE_SECONDARY: + return escState.parser.csiEntry, nil + case b == ANSI_OSC_STRING_ENTRY: + return escState.parser.oscString, nil + case sliceContains(executors, b): + return escState, escState.parser.execute() + case sliceContains(escapeToGroundBytes, b): + return escState.parser.ground, nil + case sliceContains(intermeds, b): + return escState.parser.escapeIntermediate, nil + } + + return escState, nil +} + +func (escState escapeState) Transition(s state) error { + escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name()) + escState.baseState.Transition(s) + + switch s { + case escState.parser.ground: + return escState.parser.escDispatch() + case escState.parser.escapeIntermediate: + return escState.parser.collectInter() + } + + return nil +} + +func (escState escapeState) Enter() error { + escState.parser.clear() + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/event_handler.go b/vendor/github.com/Azure/go-ansiterm/event_handler.go new file mode 100644 index 00000000..98087b38 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/event_handler.go @@ -0,0 +1,90 @@ +package ansiterm + +type AnsiEventHandler interface { + // Print + Print(b byte) error + + // Execute C0 commands + Execute(b byte) error + + // CUrsor Up + CUU(int) error + + // CUrsor Down + CUD(int) error + + // CUrsor Forward + CUF(int) error + + // CUrsor Backward + CUB(int) error + + // Cursor to Next Line + CNL(int) error + + // Cursor to Previous Line + CPL(int) error + + // Cursor Horizontal position Absolute + CHA(int) error + + // Vertical line Position Absolute + VPA(int) error + + // CUrsor Position + CUP(int, int) error + + // Horizontal and Vertical Position (depends on PUM) + HVP(int, int) error + + // Text Cursor Enable Mode + DECTCEM(bool) error + + // Origin Mode + DECOM(bool) error + + // 132 Column Mode + DECCOLM(bool) error + + // Erase in Display + ED(int) error + + // Erase in Line + EL(int) error + + // Insert Line + IL(int) error + + // Delete Line + DL(int) error + + // Insert Character + ICH(int) error + + // Delete Character + DCH(int) error + + // Set Graphics Rendition + SGR([]int) error + + // Pan Down + SU(int) error + + // Pan Up + SD(int) error + + // Device Attributes + DA([]string) error + + // Set Top and Bottom Margins + DECSTBM(int, int) error + + // Index + IND() error + + // Reverse Index + RI() error + + // Flush updates from previous commands + Flush() error +} diff --git a/vendor/github.com/Azure/go-ansiterm/ground_state.go b/vendor/github.com/Azure/go-ansiterm/ground_state.go new file mode 100644 index 00000000..52451e94 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/ground_state.go @@ -0,0 +1,24 @@ +package ansiterm + +type groundState struct { + baseState +} + +func (gs groundState) Handle(b byte) (s state, e error) { + gs.parser.context.currentChar = b + + nextState, err := gs.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(printables, b): + return gs, gs.parser.print() + + case sliceContains(executors, b): + return gs, gs.parser.execute() + } + + return gs, nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go new file mode 100644 index 00000000..593b10ab --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go @@ -0,0 +1,31 @@ +package ansiterm + +type oscStringState struct { + baseState +} + +func (oscState oscStringState) Handle(b byte) (s state, e error) { + oscState.parser.logf("OscString::Handle %#x", b) + nextState, err := oscState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case isOscStringTerminator(b): + return oscState.parser.ground, nil + } + + return oscState, nil +} + +// See below for OSC string terminators for linux +// http://man7.org/linux/man-pages/man4/console_codes.4.html +func isOscStringTerminator(b byte) bool { + + if b == ANSI_BEL || b == 0x5C { + return true + } + + return false +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser.go b/vendor/github.com/Azure/go-ansiterm/parser.go new file mode 100644 index 00000000..03cec7ad --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser.go @@ -0,0 +1,151 @@ +package ansiterm + +import ( + "errors" + "log" + "os" +) + +type AnsiParser struct { + currState state + eventHandler AnsiEventHandler + context *ansiContext + csiEntry state + csiParam state + dcsEntry state + escape state + escapeIntermediate state + error state + ground state + oscString state + stateMap []state + + logf func(string, ...interface{}) +} + +type Option func(*AnsiParser) + +func WithLogf(f func(string, ...interface{})) Option { + return func(ap *AnsiParser) { + ap.logf = f + } +} + +func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser { + ap := &AnsiParser{ + eventHandler: evtHandler, + context: &ansiContext{}, + } + for _, o := range opts { + o(ap) + } + + if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" { + logFile, _ := os.Create("ansiParser.log") + logger := log.New(logFile, "", log.LstdFlags) + if ap.logf != nil { + l := ap.logf + ap.logf = func(s string, v ...interface{}) { + l(s, v...) + logger.Printf(s, v...) + } + } else { + ap.logf = logger.Printf + } + } + + if ap.logf == nil { + ap.logf = func(string, ...interface{}) {} + } + + ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}} + ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}} + ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}} + ap.escape = escapeState{baseState{name: "Escape", parser: ap}} + ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}} + ap.error = errorState{baseState{name: "Error", parser: ap}} + ap.ground = groundState{baseState{name: "Ground", parser: ap}} + ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}} + + ap.stateMap = []state{ + ap.csiEntry, + ap.csiParam, + ap.dcsEntry, + ap.escape, + ap.escapeIntermediate, + ap.error, + ap.ground, + ap.oscString, + } + + ap.currState = getState(initialState, ap.stateMap) + + ap.logf("CreateParser: parser %p", ap) + return ap +} + +func getState(name string, states []state) state { + for _, el := range states { + if el.Name() == name { + return el + } + } + + return nil +} + +func (ap *AnsiParser) Parse(bytes []byte) (int, error) { + for i, b := range bytes { + if err := ap.handle(b); err != nil { + return i, err + } + } + + return len(bytes), ap.eventHandler.Flush() +} + +func (ap *AnsiParser) handle(b byte) error { + ap.context.currentChar = b + newState, err := ap.currState.Handle(b) + if err != nil { + return err + } + + if newState == nil { + ap.logf("WARNING: newState is nil") + return errors.New("New state of 'nil' is invalid.") + } + + if newState != ap.currState { + if err := ap.changeState(newState); err != nil { + return err + } + } + + return nil +} + +func (ap *AnsiParser) changeState(newState state) error { + ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name()) + + // Exit old state + if err := ap.currState.Exit(); err != nil { + ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err) + return err + } + + // Perform transition action + if err := ap.currState.Transition(newState); err != nil { + ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) + return err + } + + // Enter new state + if err := newState.Enter(); err != nil { + ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err) + return err + } + + ap.currState = newState + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go new file mode 100644 index 00000000..de0a1f9c --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go @@ -0,0 +1,99 @@ +package ansiterm + +import ( + "strconv" +) + +func parseParams(bytes []byte) ([]string, error) { + paramBuff := make([]byte, 0, 0) + params := []string{} + + for _, v := range bytes { + if v == ';' { + if len(paramBuff) > 0 { + // Completed parameter, append it to the list + s := string(paramBuff) + params = append(params, s) + paramBuff = make([]byte, 0, 0) + } + } else { + paramBuff = append(paramBuff, v) + } + } + + // Last parameter may not be terminated with ';' + if len(paramBuff) > 0 { + s := string(paramBuff) + params = append(params, s) + } + + return params, nil +} + +func parseCmd(context ansiContext) (string, error) { + return string(context.currentChar), nil +} + +func getInt(params []string, dflt int) int { + i := getInts(params, 1, dflt)[0] + return i +} + +func getInts(params []string, minCount int, dflt int) []int { + ints := []int{} + + for _, v := range params { + i, _ := strconv.Atoi(v) + // Zero is mapped to the default value in VT100. + if i == 0 { + i = dflt + } + ints = append(ints, i) + } + + if len(ints) < minCount { + remaining := minCount - len(ints) + for i := 0; i < remaining; i++ { + ints = append(ints, dflt) + } + } + + return ints +} + +func (ap *AnsiParser) modeDispatch(param string, set bool) error { + switch param { + case "?3": + return ap.eventHandler.DECCOLM(set) + case "?6": + return ap.eventHandler.DECOM(set) + case "?25": + return ap.eventHandler.DECTCEM(set) + } + return nil +} + +func (ap *AnsiParser) hDispatch(params []string) error { + if len(params) == 1 { + return ap.modeDispatch(params[0], true) + } + + return nil +} + +func (ap *AnsiParser) lDispatch(params []string) error { + if len(params) == 1 { + return ap.modeDispatch(params[0], false) + } + + return nil +} + +func getEraseParam(params []string) int { + param := getInt(params, 0) + if param < 0 || 3 < param { + param = 0 + } + + return param +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_actions.go b/vendor/github.com/Azure/go-ansiterm/parser_actions.go new file mode 100644 index 00000000..0bb5e51e --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_actions.go @@ -0,0 +1,119 @@ +package ansiterm + +func (ap *AnsiParser) collectParam() error { + currChar := ap.context.currentChar + ap.logf("collectParam %#x", currChar) + ap.context.paramBuffer = append(ap.context.paramBuffer, currChar) + return nil +} + +func (ap *AnsiParser) collectInter() error { + currChar := ap.context.currentChar + ap.logf("collectInter %#x", currChar) + ap.context.paramBuffer = append(ap.context.interBuffer, currChar) + return nil +} + +func (ap *AnsiParser) escDispatch() error { + cmd, _ := parseCmd(*ap.context) + intermeds := ap.context.interBuffer + ap.logf("escDispatch currentChar: %#x", ap.context.currentChar) + ap.logf("escDispatch: %v(%v)", cmd, intermeds) + + switch cmd { + case "D": // IND + return ap.eventHandler.IND() + case "E": // NEL, equivalent to CRLF + err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN) + if err == nil { + err = ap.eventHandler.Execute(ANSI_LINE_FEED) + } + return err + case "M": // RI + return ap.eventHandler.RI() + } + + return nil +} + +func (ap *AnsiParser) csiDispatch() error { + cmd, _ := parseCmd(*ap.context) + params, _ := parseParams(ap.context.paramBuffer) + ap.logf("Parsed params: %v with length: %d", params, len(params)) + + ap.logf("csiDispatch: %v(%v)", cmd, params) + + switch cmd { + case "@": + return ap.eventHandler.ICH(getInt(params, 1)) + case "A": + return ap.eventHandler.CUU(getInt(params, 1)) + case "B": + return ap.eventHandler.CUD(getInt(params, 1)) + case "C": + return ap.eventHandler.CUF(getInt(params, 1)) + case "D": + return ap.eventHandler.CUB(getInt(params, 1)) + case "E": + return ap.eventHandler.CNL(getInt(params, 1)) + case "F": + return ap.eventHandler.CPL(getInt(params, 1)) + case "G": + return ap.eventHandler.CHA(getInt(params, 1)) + case "H": + ints := getInts(params, 2, 1) + x, y := ints[0], ints[1] + return ap.eventHandler.CUP(x, y) + case "J": + param := getEraseParam(params) + return ap.eventHandler.ED(param) + case "K": + param := getEraseParam(params) + return ap.eventHandler.EL(param) + case "L": + return ap.eventHandler.IL(getInt(params, 1)) + case "M": + return ap.eventHandler.DL(getInt(params, 1)) + case "P": + return ap.eventHandler.DCH(getInt(params, 1)) + case "S": + return ap.eventHandler.SU(getInt(params, 1)) + case "T": + return ap.eventHandler.SD(getInt(params, 1)) + case "c": + return ap.eventHandler.DA(params) + case "d": + return ap.eventHandler.VPA(getInt(params, 1)) + case "f": + ints := getInts(params, 2, 1) + x, y := ints[0], ints[1] + return ap.eventHandler.HVP(x, y) + case "h": + return ap.hDispatch(params) + case "l": + return ap.lDispatch(params) + case "m": + return ap.eventHandler.SGR(getInts(params, 1, 0)) + case "r": + ints := getInts(params, 2, 1) + top, bottom := ints[0], ints[1] + return ap.eventHandler.DECSTBM(top, bottom) + default: + ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context) + return nil + } + +} + +func (ap *AnsiParser) print() error { + return ap.eventHandler.Print(ap.context.currentChar) +} + +func (ap *AnsiParser) clear() error { + ap.context = &ansiContext{} + return nil +} + +func (ap *AnsiParser) execute() error { + return ap.eventHandler.Execute(ap.context.currentChar) +} diff --git a/vendor/github.com/Azure/go-ansiterm/states.go b/vendor/github.com/Azure/go-ansiterm/states.go new file mode 100644 index 00000000..f2ea1fcd --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/states.go @@ -0,0 +1,71 @@ +package ansiterm + +type stateID int + +type state interface { + Enter() error + Exit() error + Handle(byte) (state, error) + Name() string + Transition(state) error +} + +type baseState struct { + name string + parser *AnsiParser +} + +func (base baseState) Enter() error { + return nil +} + +func (base baseState) Exit() error { + return nil +} + +func (base baseState) Handle(b byte) (s state, e error) { + + switch { + case b == CSI_ENTRY: + return base.parser.csiEntry, nil + case b == DCS_ENTRY: + return base.parser.dcsEntry, nil + case b == ANSI_ESCAPE_PRIMARY: + return base.parser.escape, nil + case b == OSC_STRING: + return base.parser.oscString, nil + case sliceContains(toGroundBytes, b): + return base.parser.ground, nil + } + + return nil, nil +} + +func (base baseState) Name() string { + return base.name +} + +func (base baseState) Transition(s state) error { + if s == base.parser.ground { + execBytes := []byte{0x18} + execBytes = append(execBytes, 0x1A) + execBytes = append(execBytes, getByteRange(0x80, 0x8F)...) + execBytes = append(execBytes, getByteRange(0x91, 0x97)...) + execBytes = append(execBytes, 0x99) + execBytes = append(execBytes, 0x9A) + + if sliceContains(execBytes, base.parser.context.currentChar) { + return base.parser.execute() + } + } + + return nil +} + +type dcsEntryState struct { + baseState +} + +type errorState struct { + baseState +} diff --git a/vendor/github.com/Azure/go-ansiterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/utilities.go new file mode 100644 index 00000000..39211449 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/utilities.go @@ -0,0 +1,21 @@ +package ansiterm + +import ( + "strconv" +) + +func sliceContains(bytes []byte, b byte) bool { + for _, v := range bytes { + if v == b { + return true + } + } + + return false +} + +func convertBytesToInteger(bytes []byte) int { + s := string(bytes) + i, _ := strconv.Atoi(s) + return i +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go new file mode 100644 index 00000000..a6732797 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go @@ -0,0 +1,182 @@ +// +build windows + +package winterm + +import ( + "fmt" + "os" + "strconv" + "strings" + "syscall" + + "github.com/Azure/go-ansiterm" +) + +// Windows keyboard constants +// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx. +const ( + VK_PRIOR = 0x21 // PAGE UP key + VK_NEXT = 0x22 // PAGE DOWN key + VK_END = 0x23 // END key + VK_HOME = 0x24 // HOME key + VK_LEFT = 0x25 // LEFT ARROW key + VK_UP = 0x26 // UP ARROW key + VK_RIGHT = 0x27 // RIGHT ARROW key + VK_DOWN = 0x28 // DOWN ARROW key + VK_SELECT = 0x29 // SELECT key + VK_PRINT = 0x2A // PRINT key + VK_EXECUTE = 0x2B // EXECUTE key + VK_SNAPSHOT = 0x2C // PRINT SCREEN key + VK_INSERT = 0x2D // INS key + VK_DELETE = 0x2E // DEL key + VK_HELP = 0x2F // HELP key + VK_F1 = 0x70 // F1 key + VK_F2 = 0x71 // F2 key + VK_F3 = 0x72 // F3 key + VK_F4 = 0x73 // F4 key + VK_F5 = 0x74 // F5 key + VK_F6 = 0x75 // F6 key + VK_F7 = 0x76 // F7 key + VK_F8 = 0x77 // F8 key + VK_F9 = 0x78 // F9 key + VK_F10 = 0x79 // F10 key + VK_F11 = 0x7A // F11 key + VK_F12 = 0x7B // F12 key + + RIGHT_ALT_PRESSED = 0x0001 + LEFT_ALT_PRESSED = 0x0002 + RIGHT_CTRL_PRESSED = 0x0004 + LEFT_CTRL_PRESSED = 0x0008 + SHIFT_PRESSED = 0x0010 + NUMLOCK_ON = 0x0020 + SCROLLLOCK_ON = 0x0040 + CAPSLOCK_ON = 0x0080 + ENHANCED_KEY = 0x0100 +) + +type ansiCommand struct { + CommandBytes []byte + Command string + Parameters []string + IsSpecial bool +} + +func newAnsiCommand(command []byte) *ansiCommand { + + if isCharacterSelectionCmdChar(command[1]) { + // Is Character Set Selection commands + return &ansiCommand{ + CommandBytes: command, + Command: string(command), + IsSpecial: true, + } + } + + // last char is command character + lastCharIndex := len(command) - 1 + + ac := &ansiCommand{ + CommandBytes: command, + Command: string(command[lastCharIndex]), + IsSpecial: false, + } + + // more than a single escape + if lastCharIndex != 0 { + start := 1 + // skip if double char escape sequence + if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY { + start++ + } + // convert this to GetNextParam method + ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP) + } + + return ac +} + +func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 { + if index < 0 || index >= len(ac.Parameters) { + return defaultValue + } + + param, err := strconv.ParseInt(ac.Parameters[index], 10, 16) + if err != nil { + return defaultValue + } + + return int16(param) +} + +func (ac *ansiCommand) String() string { + return fmt.Sprintf("0x%v \"%v\" (\"%v\")", + bytesToHex(ac.CommandBytes), + ac.Command, + strings.Join(ac.Parameters, "\",\"")) +} + +// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands. +// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html. +func isAnsiCommandChar(b byte) bool { + switch { + case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY: + return true + case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM: + // non-CSI escape sequence terminator + return true + case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL: + // String escape sequence terminator + return true + } + return false +} + +func isXtermOscSequence(command []byte, current byte) bool { + return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL) +} + +func isCharacterSelectionCmdChar(b byte) bool { + return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3) +} + +// bytesToHex converts a slice of bytes to a human-readable string. +func bytesToHex(b []byte) string { + hex := make([]string, len(b)) + for i, ch := range b { + hex[i] = fmt.Sprintf("%X", ch) + } + return strings.Join(hex, "") +} + +// ensureInRange adjusts the passed value, if necessary, to ensure it is within +// the passed min / max range. +func ensureInRange(n int16, min int16, max int16) int16 { + if n < min { + return min + } else if n > max { + return max + } else { + return n + } +} + +func GetStdFile(nFile int) (*os.File, uintptr) { + var file *os.File + switch nFile { + case syscall.STD_INPUT_HANDLE: + file = os.Stdin + case syscall.STD_OUTPUT_HANDLE: + file = os.Stdout + case syscall.STD_ERROR_HANDLE: + file = os.Stderr + default: + panic(fmt.Errorf("Invalid standard handle identifier: %v", nFile)) + } + + fd, err := syscall.GetStdHandle(nFile) + if err != nil { + panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err)) + } + + return file, uintptr(fd) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/api.go b/vendor/github.com/Azure/go-ansiterm/winterm/api.go new file mode 100644 index 00000000..6055e33b --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/api.go @@ -0,0 +1,327 @@ +// +build windows + +package winterm + +import ( + "fmt" + "syscall" + "unsafe" +) + +//=========================================================================================================== +// IMPORTANT NOTE: +// +// The methods below make extensive use of the "unsafe" package to obtain the required pointers. +// Beginning in Go 1.3, the garbage collector may release local variables (e.g., incoming arguments, stack +// variables) the pointers reference *before* the API completes. +// +// As a result, in those cases, the code must hint that the variables remain in active by invoking the +// dummy method "use" (see below). Newer versions of Go are planned to change the mechanism to no longer +// require unsafe pointers. +// +// If you add or modify methods, ENSURE protection of local variables through the "use" builtin to inform +// the garbage collector the variables remain in use if: +// +// -- The value is not a pointer (e.g., int32, struct) +// -- The value is not referenced by the method after passing the pointer to Windows +// +// See http://golang.org/doc/go1.3. +//=========================================================================================================== + +var ( + kernel32DLL = syscall.NewLazyDLL("kernel32.dll") + + getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo") + setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo") + setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition") + setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode") + getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo") + setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize") + scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA") + setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute") + setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo") + writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW") + readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW") + waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject") +) + +// Windows Console constants +const ( + // Console modes + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. + ENABLE_PROCESSED_INPUT = 0x0001 + ENABLE_LINE_INPUT = 0x0002 + ENABLE_ECHO_INPUT = 0x0004 + ENABLE_WINDOW_INPUT = 0x0008 + ENABLE_MOUSE_INPUT = 0x0010 + ENABLE_INSERT_MODE = 0x0020 + ENABLE_QUICK_EDIT_MODE = 0x0040 + ENABLE_EXTENDED_FLAGS = 0x0080 + ENABLE_AUTO_POSITION = 0x0100 + ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 + + ENABLE_PROCESSED_OUTPUT = 0x0001 + ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + DISABLE_NEWLINE_AUTO_RETURN = 0x0008 + ENABLE_LVB_GRID_WORLDWIDE = 0x0010 + + // Character attributes + // Note: + // -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan). + // Clearing all foreground or background colors results in black; setting all creates white. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes. + FOREGROUND_BLUE uint16 = 0x0001 + FOREGROUND_GREEN uint16 = 0x0002 + FOREGROUND_RED uint16 = 0x0004 + FOREGROUND_INTENSITY uint16 = 0x0008 + FOREGROUND_MASK uint16 = 0x000F + + BACKGROUND_BLUE uint16 = 0x0010 + BACKGROUND_GREEN uint16 = 0x0020 + BACKGROUND_RED uint16 = 0x0040 + BACKGROUND_INTENSITY uint16 = 0x0080 + BACKGROUND_MASK uint16 = 0x00F0 + + COMMON_LVB_MASK uint16 = 0xFF00 + COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000 + COMMON_LVB_UNDERSCORE uint16 = 0x8000 + + // Input event types + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. + KEY_EVENT = 0x0001 + MOUSE_EVENT = 0x0002 + WINDOW_BUFFER_SIZE_EVENT = 0x0004 + MENU_EVENT = 0x0008 + FOCUS_EVENT = 0x0010 + + // WaitForSingleObject return codes + WAIT_ABANDONED = 0x00000080 + WAIT_FAILED = 0xFFFFFFFF + WAIT_SIGNALED = 0x0000000 + WAIT_TIMEOUT = 0x00000102 + + // WaitForSingleObject wait duration + WAIT_INFINITE = 0xFFFFFFFF + WAIT_ONE_SECOND = 1000 + WAIT_HALF_SECOND = 500 + WAIT_QUARTER_SECOND = 250 +) + +// Windows API Console types +// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682101(v=vs.85).aspx for Console specific types (e.g., COORD) +// -- See https://msdn.microsoft.com/en-us/library/aa296569(v=vs.60).aspx for comments on alignment +type ( + CHAR_INFO struct { + UnicodeChar uint16 + Attributes uint16 + } + + CONSOLE_CURSOR_INFO struct { + Size uint32 + Visible int32 + } + + CONSOLE_SCREEN_BUFFER_INFO struct { + Size COORD + CursorPosition COORD + Attributes uint16 + Window SMALL_RECT + MaximumWindowSize COORD + } + + COORD struct { + X int16 + Y int16 + } + + SMALL_RECT struct { + Left int16 + Top int16 + Right int16 + Bottom int16 + } + + // INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. + INPUT_RECORD struct { + EventType uint16 + KeyEvent KEY_EVENT_RECORD + } + + KEY_EVENT_RECORD struct { + KeyDown int32 + RepeatCount uint16 + VirtualKeyCode uint16 + VirtualScanCode uint16 + UnicodeChar uint16 + ControlKeyState uint32 + } + + WINDOW_BUFFER_SIZE struct { + Size COORD + } +) + +// boolToBOOL converts a Go bool into a Windows int32. +func boolToBOOL(f bool) int32 { + if f { + return int32(1) + } else { + return int32(0) + } +} + +// GetConsoleCursorInfo retrieves information about the size and visiblity of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683163(v=vs.85).aspx. +func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { + r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) + return checkError(r1, r2, err) +} + +// SetConsoleCursorInfo sets the size and visiblity of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx. +func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { + r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) + return checkError(r1, r2, err) +} + +// SetConsoleCursorPosition location of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx. +func SetConsoleCursorPosition(handle uintptr, coord COORD) error { + r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord)) + use(coord) + return checkError(r1, r2, err) +} + +// GetConsoleMode gets the console mode for given file descriptor +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx. +func GetConsoleMode(handle uintptr) (mode uint32, err error) { + err = syscall.GetConsoleMode(syscall.Handle(handle), &mode) + return mode, err +} + +// SetConsoleMode sets the console mode for given file descriptor +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. +func SetConsoleMode(handle uintptr, mode uint32) error { + r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0) + use(mode) + return checkError(r1, r2, err) +} + +// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer. +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx. +func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) { + info := CONSOLE_SCREEN_BUFFER_INFO{} + err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)) + if err != nil { + return nil, err + } + return &info, nil +} + +func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error { + r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char))) + use(scrollRect) + use(clipRect) + use(destOrigin) + use(char) + return checkError(r1, r2, err) +} + +// SetConsoleScreenBufferSize sets the size of the console screen buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx. +func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error { + r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord)) + use(coord) + return checkError(r1, r2, err) +} + +// SetConsoleTextAttribute sets the attributes of characters written to the +// console screen buffer by the WriteFile or WriteConsole function. +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx. +func SetConsoleTextAttribute(handle uintptr, attribute uint16) error { + r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0) + use(attribute) + return checkError(r1, r2, err) +} + +// SetConsoleWindowInfo sets the size and position of the console screen buffer's window. +// Note that the size and location must be within and no larger than the backing console screen buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx. +func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error { + r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect))) + use(isAbsolute) + use(rect) + return checkError(r1, r2, err) +} + +// WriteConsoleOutput writes the CHAR_INFOs from the provided buffer to the active console buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx. +func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error { + r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion))) + use(buffer) + use(bufferSize) + use(bufferCoord) + return checkError(r1, r2, err) +} + +// ReadConsoleInput reads (and removes) data from the console input buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx. +func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error { + r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count))) + use(buffer) + return checkError(r1, r2, err) +} + +// WaitForSingleObject waits for the passed handle to be signaled. +// It returns true if the handle was signaled; false otherwise. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx. +func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) { + r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait))) + switch r1 { + case WAIT_ABANDONED, WAIT_TIMEOUT: + return false, nil + case WAIT_SIGNALED: + return true, nil + } + use(msWait) + return false, err +} + +// String helpers +func (info CONSOLE_SCREEN_BUFFER_INFO) String() string { + return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize) +} + +func (coord COORD) String() string { + return fmt.Sprintf("%v,%v", coord.X, coord.Y) +} + +func (rect SMALL_RECT) String() string { + return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom) +} + +// checkError evaluates the results of a Windows API call and returns the error if it failed. +func checkError(r1, r2 uintptr, err error) error { + // Windows APIs return non-zero to indicate success + if r1 != 0 { + return nil + } + + // Return the error if provided, otherwise default to EINVAL + if err != nil { + return err + } + return syscall.EINVAL +} + +// coordToPointer converts a COORD into a uintptr (by fooling the type system). +func coordToPointer(c COORD) uintptr { + // Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass. + return uintptr(*((*uint32)(unsafe.Pointer(&c)))) +} + +// use is a no-op, but the compiler cannot see that it is. +// Calling use(p) ensures that p is kept live until that point. +func use(p interface{}) {} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go new file mode 100644 index 00000000..cbec8f72 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go @@ -0,0 +1,100 @@ +// +build windows + +package winterm + +import "github.com/Azure/go-ansiterm" + +const ( + FOREGROUND_COLOR_MASK = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + BACKGROUND_COLOR_MASK = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE +) + +// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the +// request represented by the passed ANSI mode. +func collectAnsiIntoWindowsAttributes(windowsMode uint16, inverted bool, baseMode uint16, ansiMode int16) (uint16, bool) { + switch ansiMode { + + // Mode styles + case ansiterm.ANSI_SGR_BOLD: + windowsMode = windowsMode | FOREGROUND_INTENSITY + + case ansiterm.ANSI_SGR_DIM, ansiterm.ANSI_SGR_BOLD_DIM_OFF: + windowsMode &^= FOREGROUND_INTENSITY + + case ansiterm.ANSI_SGR_UNDERLINE: + windowsMode = windowsMode | COMMON_LVB_UNDERSCORE + + case ansiterm.ANSI_SGR_REVERSE: + inverted = true + + case ansiterm.ANSI_SGR_REVERSE_OFF: + inverted = false + + case ansiterm.ANSI_SGR_UNDERLINE_OFF: + windowsMode &^= COMMON_LVB_UNDERSCORE + + // Foreground colors + case ansiterm.ANSI_SGR_FOREGROUND_DEFAULT: + windowsMode = (windowsMode &^ FOREGROUND_MASK) | (baseMode & FOREGROUND_MASK) + + case ansiterm.ANSI_SGR_FOREGROUND_BLACK: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) + + case ansiterm.ANSI_SGR_FOREGROUND_RED: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED + + case ansiterm.ANSI_SGR_FOREGROUND_GREEN: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN + + case ansiterm.ANSI_SGR_FOREGROUND_YELLOW: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN + + case ansiterm.ANSI_SGR_FOREGROUND_BLUE: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_MAGENTA: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_CYAN: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_WHITE: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + + // Background colors + case ansiterm.ANSI_SGR_BACKGROUND_DEFAULT: + // Black with no intensity + windowsMode = (windowsMode &^ BACKGROUND_MASK) | (baseMode & BACKGROUND_MASK) + + case ansiterm.ANSI_SGR_BACKGROUND_BLACK: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) + + case ansiterm.ANSI_SGR_BACKGROUND_RED: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED + + case ansiterm.ANSI_SGR_BACKGROUND_GREEN: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN + + case ansiterm.ANSI_SGR_BACKGROUND_YELLOW: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN + + case ansiterm.ANSI_SGR_BACKGROUND_BLUE: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_MAGENTA: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_CYAN: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_WHITE: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE + } + + return windowsMode, inverted +} + +// invertAttributes inverts the foreground and background colors of a Windows attributes value +func invertAttributes(windowsMode uint16) uint16 { + return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go new file mode 100644 index 00000000..3ee06ea7 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go @@ -0,0 +1,101 @@ +// +build windows + +package winterm + +const ( + horizontal = iota + vertical +) + +func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT { + if h.originMode { + sr := h.effectiveSr(info.Window) + return SMALL_RECT{ + Top: sr.top, + Bottom: sr.bottom, + Left: 0, + Right: info.Size.X - 1, + } + } else { + return SMALL_RECT{ + Top: info.Window.Top, + Bottom: info.Window.Bottom, + Left: 0, + Right: info.Size.X - 1, + } + } +} + +// setCursorPosition sets the cursor to the specified position, bounded to the screen size +func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error { + position.X = ensureInRange(position.X, window.Left, window.Right) + position.Y = ensureInRange(position.Y, window.Top, window.Bottom) + err := SetConsoleCursorPosition(h.fd, position) + if err != nil { + return err + } + h.logf("Cursor position set: (%d, %d)", position.X, position.Y) + return err +} + +func (h *windowsAnsiEventHandler) moveCursorVertical(param int) error { + return h.moveCursor(vertical, param) +} + +func (h *windowsAnsiEventHandler) moveCursorHorizontal(param int) error { + return h.moveCursor(horizontal, param) +} + +func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + switch moveMode { + case horizontal: + position.X += int16(param) + case vertical: + position.Y += int16(param) + } + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) moveCursorLine(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + position.X = 0 + position.Y += int16(param) + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + position.X = int16(param) - 1 + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go new file mode 100644 index 00000000..244b5fa2 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go @@ -0,0 +1,84 @@ +// +build windows + +package winterm + +import "github.com/Azure/go-ansiterm" + +func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD, toCoord COORD) error { + // Ignore an invalid (negative area) request + if toCoord.Y < fromCoord.Y { + return nil + } + + var err error + + var coordStart = COORD{} + var coordEnd = COORD{} + + xCurrent, yCurrent := fromCoord.X, fromCoord.Y + xEnd, yEnd := toCoord.X, toCoord.Y + + // Clear any partial initial line + if xCurrent > 0 { + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yCurrent + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + xCurrent = 0 + yCurrent += 1 + } + + // Clear intervening rectangular section + if yCurrent < yEnd { + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yEnd-1 + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + xCurrent = 0 + yCurrent = yEnd + } + + // Clear remaining partial ending line + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yEnd + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error { + region := SMALL_RECT{Top: fromCoord.Y, Left: fromCoord.X, Bottom: toCoord.Y, Right: toCoord.X} + width := toCoord.X - fromCoord.X + 1 + height := toCoord.Y - fromCoord.Y + 1 + size := uint32(width) * uint32(height) + + if size <= 0 { + return nil + } + + buffer := make([]CHAR_INFO, size) + + char := CHAR_INFO{ansiterm.FILL_CHARACTER, attributes} + for i := 0; i < int(size); i++ { + buffer[i] = char + } + + err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, ®ion) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go new file mode 100644 index 00000000..2d27fa1d --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go @@ -0,0 +1,118 @@ +// +build windows + +package winterm + +// effectiveSr gets the current effective scroll region in buffer coordinates +func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion { + top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom) + bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom) + if top >= bottom { + top = window.Top + bottom = window.Bottom + } + return scrollRegion{top: top, bottom: bottom} +} + +func (h *windowsAnsiEventHandler) scrollUp(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + sr := h.effectiveSr(info.Window) + return h.scroll(param, sr, info) +} + +func (h *windowsAnsiEventHandler) scrollDown(param int) error { + return h.scrollUp(-param) +} + +func (h *windowsAnsiEventHandler) deleteLines(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + start := info.CursorPosition.Y + sr := h.effectiveSr(info.Window) + // Lines cannot be inserted or deleted outside the scrolling region. + if start >= sr.top && start <= sr.bottom { + sr.top = start + return h.scroll(param, sr, info) + } else { + return nil + } +} + +func (h *windowsAnsiEventHandler) insertLines(param int) error { + return h.deleteLines(-param) +} + +// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. +func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { + h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) + h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) + + // Copy from and clip to the scroll region (full buffer width) + scrollRect := SMALL_RECT{ + Top: sr.top, + Bottom: sr.bottom, + Left: 0, + Right: info.Size.X - 1, + } + + // Origin to which area should be copied + destOrigin := COORD{ + X: 0, + Y: sr.top - int16(param), + } + + char := CHAR_INFO{ + UnicodeChar: ' ', + Attributes: h.attributes, + } + + if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { + return err + } + return nil +} + +func (h *windowsAnsiEventHandler) deleteCharacters(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + return h.scrollLine(param, info.CursorPosition, info) +} + +func (h *windowsAnsiEventHandler) insertCharacters(param int) error { + return h.deleteCharacters(-param) +} + +// scrollLine scrolls a line horizontally starting at the provided position by a number of columns. +func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error { + // Copy from and clip to the scroll region (full buffer width) + scrollRect := SMALL_RECT{ + Top: position.Y, + Bottom: position.Y, + Left: position.X, + Right: info.Size.X - 1, + } + + // Origin to which area should be copied + destOrigin := COORD{ + X: position.X - int16(columns), + Y: position.Y, + } + + char := CHAR_INFO{ + UnicodeChar: ' ', + Attributes: h.attributes, + } + + if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go new file mode 100644 index 00000000..afa7635d --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go @@ -0,0 +1,9 @@ +// +build windows + +package winterm + +// AddInRange increments a value by the passed quantity while ensuring the values +// always remain within the supplied min / max range. +func addInRange(n int16, increment int16, min int16, max int16) int16 { + return ensureInRange(n+increment, min, max) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go new file mode 100644 index 00000000..2d40fb75 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go @@ -0,0 +1,743 @@ +// +build windows + +package winterm + +import ( + "bytes" + "log" + "os" + "strconv" + + "github.com/Azure/go-ansiterm" +) + +type windowsAnsiEventHandler struct { + fd uintptr + file *os.File + infoReset *CONSOLE_SCREEN_BUFFER_INFO + sr scrollRegion + buffer bytes.Buffer + attributes uint16 + inverted bool + wrapNext bool + drewMarginByte bool + originMode bool + marginByte byte + curInfo *CONSOLE_SCREEN_BUFFER_INFO + curPos COORD + logf func(string, ...interface{}) +} + +type Option func(*windowsAnsiEventHandler) + +func WithLogf(f func(string, ...interface{})) Option { + return func(w *windowsAnsiEventHandler) { + w.logf = f + } +} + +func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler { + infoReset, err := GetConsoleScreenBufferInfo(fd) + if err != nil { + return nil + } + + h := &windowsAnsiEventHandler{ + fd: fd, + file: file, + infoReset: infoReset, + attributes: infoReset.Attributes, + } + for _, o := range opts { + o(h) + } + + if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { + logFile, _ := os.Create("winEventHandler.log") + logger := log.New(logFile, "", log.LstdFlags) + if h.logf != nil { + l := h.logf + h.logf = func(s string, v ...interface{}) { + l(s, v...) + logger.Printf(s, v...) + } + } else { + h.logf = logger.Printf + } + } + + if h.logf == nil { + h.logf = func(string, ...interface{}) {} + } + + return h +} + +type scrollRegion struct { + top int16 + bottom int16 +} + +// simulateLF simulates a LF or CR+LF by scrolling if necessary to handle the +// current cursor position and scroll region settings, in which case it returns +// true. If no special handling is necessary, then it does nothing and returns +// false. +// +// In the false case, the caller should ensure that a carriage return +// and line feed are inserted or that the text is otherwise wrapped. +func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) { + if h.wrapNext { + if err := h.Flush(); err != nil { + return false, err + } + h.clearWrap() + } + pos, info, err := h.getCurrentInfo() + if err != nil { + return false, err + } + sr := h.effectiveSr(info.Window) + if pos.Y == sr.bottom { + // Scrolling is necessary. Let Windows automatically scroll if the scrolling region + // is the full window. + if sr.top == info.Window.Top && sr.bottom == info.Window.Bottom { + if includeCR { + pos.X = 0 + h.updatePos(pos) + } + return false, nil + } + + // A custom scroll region is active. Scroll the window manually to simulate + // the LF. + if err := h.Flush(); err != nil { + return false, err + } + h.logf("Simulating LF inside scroll region") + if err := h.scrollUp(1); err != nil { + return false, err + } + if includeCR { + pos.X = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return false, err + } + } + return true, nil + + } else if pos.Y < info.Window.Bottom { + // Let Windows handle the LF. + pos.Y++ + if includeCR { + pos.X = 0 + } + h.updatePos(pos) + return false, nil + } else { + // The cursor is at the bottom of the screen but outside the scroll + // region. Skip the LF. + h.logf("Simulating LF outside scroll region") + if includeCR { + if err := h.Flush(); err != nil { + return false, err + } + pos.X = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return false, err + } + } + return true, nil + } +} + +// executeLF executes a LF without a CR. +func (h *windowsAnsiEventHandler) executeLF() error { + handled, err := h.simulateLF(false) + if err != nil { + return err + } + if !handled { + // Windows LF will reset the cursor column position. Write the LF + // and restore the cursor position. + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) + if pos.X != 0 { + if err := h.Flush(); err != nil { + return err + } + h.logf("Resetting cursor position for LF without CR") + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + } + } + return nil +} + +func (h *windowsAnsiEventHandler) Print(b byte) error { + if h.wrapNext { + h.buffer.WriteByte(h.marginByte) + h.clearWrap() + if _, err := h.simulateLF(true); err != nil { + return err + } + } + pos, info, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X == info.Size.X-1 { + h.wrapNext = true + h.marginByte = b + } else { + pos.X++ + h.updatePos(pos) + h.buffer.WriteByte(b) + } + return nil +} + +func (h *windowsAnsiEventHandler) Execute(b byte) error { + switch b { + case ansiterm.ANSI_TAB: + h.logf("Execute(TAB)") + // Move to the next tab stop, but preserve auto-wrap if already set. + if !h.wrapNext { + pos, info, err := h.getCurrentInfo() + if err != nil { + return err + } + pos.X = (pos.X + 8) - pos.X%8 + if pos.X >= info.Size.X { + pos.X = info.Size.X - 1 + } + if err := h.Flush(); err != nil { + return err + } + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + } + return nil + + case ansiterm.ANSI_BEL: + h.buffer.WriteByte(ansiterm.ANSI_BEL) + return nil + + case ansiterm.ANSI_BACKSPACE: + if h.wrapNext { + if err := h.Flush(); err != nil { + return err + } + h.clearWrap() + } + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X > 0 { + pos.X-- + h.updatePos(pos) + h.buffer.WriteByte(ansiterm.ANSI_BACKSPACE) + } + return nil + + case ansiterm.ANSI_VERTICAL_TAB, ansiterm.ANSI_FORM_FEED: + // Treat as true LF. + return h.executeLF() + + case ansiterm.ANSI_LINE_FEED: + // Simulate a CR and LF for now since there is no way in go-ansiterm + // to tell if the LF should include CR (and more things break when it's + // missing than when it's incorrectly added). + handled, err := h.simulateLF(true) + if handled || err != nil { + return err + } + return h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) + + case ansiterm.ANSI_CARRIAGE_RETURN: + if h.wrapNext { + if err := h.Flush(); err != nil { + return err + } + h.clearWrap() + } + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X != 0 { + pos.X = 0 + h.updatePos(pos) + h.buffer.WriteByte(ansiterm.ANSI_CARRIAGE_RETURN) + } + return nil + + default: + return nil + } +} + +func (h *windowsAnsiEventHandler) CUU(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUU: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorVertical(-param) +} + +func (h *windowsAnsiEventHandler) CUD(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUD: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorVertical(param) +} + +func (h *windowsAnsiEventHandler) CUF(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUF: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorHorizontal(param) +} + +func (h *windowsAnsiEventHandler) CUB(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUB: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorHorizontal(-param) +} + +func (h *windowsAnsiEventHandler) CNL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CNL: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorLine(param) +} + +func (h *windowsAnsiEventHandler) CPL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CPL: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorLine(-param) +} + +func (h *windowsAnsiEventHandler) CHA(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CHA: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorColumn(param) +} + +func (h *windowsAnsiEventHandler) VPA(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("VPA: [[%d]]", param) + h.clearWrap() + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + window := h.getCursorWindow(info) + position := info.CursorPosition + position.Y = window.Top + int16(param) - 1 + return h.setCursorPosition(position, window) +} + +func (h *windowsAnsiEventHandler) CUP(row int, col int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUP: [[%d %d]]", row, col) + h.clearWrap() + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + window := h.getCursorWindow(info) + position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1} + return h.setCursorPosition(position, window) +} + +func (h *windowsAnsiEventHandler) HVP(row int, col int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("HVP: [[%d %d]]", row, col) + h.clearWrap() + return h.CUP(row, col) +} + +func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)}) + h.clearWrap() + return nil +} + +func (h *windowsAnsiEventHandler) DECOM(enable bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)}) + h.clearWrap() + h.originMode = enable + return h.CUP(1, 1) +} + +func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)}) + h.clearWrap() + if err := h.ED(2); err != nil { + return err + } + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + targetWidth := int16(80) + if use132 { + targetWidth = 132 + } + if info.Size.X < targetWidth { + if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { + h.logf("set buffer failed: %v", err) + return err + } + } + window := info.Window + window.Left = 0 + window.Right = targetWidth - 1 + if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { + h.logf("set window failed: %v", err) + return err + } + if info.Size.X > targetWidth { + if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { + h.logf("set buffer failed: %v", err) + return err + } + } + return SetConsoleCursorPosition(h.fd, COORD{0, 0}) +} + +func (h *windowsAnsiEventHandler) ED(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("ED: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + + // [J -- Erases from the cursor to the end of the screen, including the cursor position. + // [1J -- Erases from the beginning of the screen to the cursor, including the cursor position. + // [2J -- Erases the complete display. The cursor does not move. + // Notes: + // -- Clearing the entire buffer, versus just the Window, works best for Windows Consoles + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + var start COORD + var end COORD + + switch param { + case 0: + start = info.CursorPosition + end = COORD{info.Size.X - 1, info.Size.Y - 1} + + case 1: + start = COORD{0, 0} + end = info.CursorPosition + + case 2: + start = COORD{0, 0} + end = COORD{info.Size.X - 1, info.Size.Y - 1} + } + + err = h.clearRange(h.attributes, start, end) + if err != nil { + return err + } + + // If the whole buffer was cleared, move the window to the top while preserving + // the window-relative cursor position. + if param == 2 { + pos := info.CursorPosition + window := info.Window + pos.Y -= window.Top + window.Bottom -= window.Top + window.Top = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { + return err + } + } + + return nil +} + +func (h *windowsAnsiEventHandler) EL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("EL: [%v]", strconv.Itoa(param)) + h.clearWrap() + + // [K -- Erases from the cursor to the end of the line, including the cursor position. + // [1K -- Erases from the beginning of the line to the cursor, including the cursor position. + // [2K -- Erases the complete line. + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + var start COORD + var end COORD + + switch param { + case 0: + start = info.CursorPosition + end = COORD{info.Size.X, info.CursorPosition.Y} + + case 1: + start = COORD{0, info.CursorPosition.Y} + end = info.CursorPosition + + case 2: + start = COORD{0, info.CursorPosition.Y} + end = COORD{info.Size.X, info.CursorPosition.Y} + } + + err = h.clearRange(h.attributes, start, end) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) IL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("IL: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.insertLines(param) +} + +func (h *windowsAnsiEventHandler) DL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DL: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.deleteLines(param) +} + +func (h *windowsAnsiEventHandler) ICH(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("ICH: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.insertCharacters(param) +} + +func (h *windowsAnsiEventHandler) DCH(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DCH: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.deleteCharacters(param) +} + +func (h *windowsAnsiEventHandler) SGR(params []int) error { + if err := h.Flush(); err != nil { + return err + } + strings := []string{} + for _, v := range params { + strings = append(strings, strconv.Itoa(v)) + } + + h.logf("SGR: [%v]", strings) + + if len(params) <= 0 { + h.attributes = h.infoReset.Attributes + h.inverted = false + } else { + for _, attr := range params { + + if attr == ansiterm.ANSI_SGR_RESET { + h.attributes = h.infoReset.Attributes + h.inverted = false + continue + } + + h.attributes, h.inverted = collectAnsiIntoWindowsAttributes(h.attributes, h.inverted, h.infoReset.Attributes, int16(attr)) + } + } + + attributes := h.attributes + if h.inverted { + attributes = invertAttributes(attributes) + } + err := SetConsoleTextAttribute(h.fd, attributes) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) SU(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("SU: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.scrollUp(param) +} + +func (h *windowsAnsiEventHandler) SD(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("SD: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.scrollDown(param) +} + +func (h *windowsAnsiEventHandler) DA(params []string) error { + h.logf("DA: [%v]", params) + // DA cannot be implemented because it must send data on the VT100 input stream, + // which is not available to go-ansiterm. + return nil +} + +func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECSTBM: [%d, %d]", top, bottom) + + // Windows is 0 indexed, Linux is 1 indexed + h.sr.top = int16(top - 1) + h.sr.bottom = int16(bottom - 1) + + // This command also moves the cursor to the origin. + h.clearWrap() + return h.CUP(1, 1) +} + +func (h *windowsAnsiEventHandler) RI() error { + if err := h.Flush(); err != nil { + return err + } + h.logf("RI: []") + h.clearWrap() + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + sr := h.effectiveSr(info.Window) + if info.CursorPosition.Y == sr.top { + return h.scrollDown(1) + } + + return h.moveCursorVertical(-1) +} + +func (h *windowsAnsiEventHandler) IND() error { + h.logf("IND: []") + return h.executeLF() +} + +func (h *windowsAnsiEventHandler) Flush() error { + h.curInfo = nil + if h.buffer.Len() > 0 { + h.logf("Flush: [%s]", h.buffer.Bytes()) + if _, err := h.buffer.WriteTo(h.file); err != nil { + return err + } + } + + if h.wrapNext && !h.drewMarginByte { + h.logf("Flush: drawing margin byte '%c'", h.marginByte) + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}} + size := COORD{1, 1} + position := COORD{0, 0} + region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y} + if err := WriteConsoleOutput(h.fd, charInfo, size, position, ®ion); err != nil { + return err + } + h.drewMarginByte = true + } + return nil +} + +// cacheConsoleInfo ensures that the current console screen information has been queried +// since the last call to Flush(). It must be called before accessing h.curInfo or h.curPos. +func (h *windowsAnsiEventHandler) getCurrentInfo() (COORD, *CONSOLE_SCREEN_BUFFER_INFO, error) { + if h.curInfo == nil { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return COORD{}, nil, err + } + h.curInfo = info + h.curPos = info.CursorPosition + } + return h.curPos, h.curInfo, nil +} + +func (h *windowsAnsiEventHandler) updatePos(pos COORD) { + if h.curInfo == nil { + panic("failed to call getCurrentInfo before calling updatePos") + } + h.curPos = pos +} + +// clearWrap clears the state where the cursor is in the margin +// waiting for the next character before wrapping the line. This must +// be done before most operations that act on the cursor. +func (h *windowsAnsiEventHandler) clearWrap() { + h.wrapNext = false + h.drewMarginByte = false +} diff --git a/vendor/github.com/Microsoft/go-winio/.gitignore b/vendor/github.com/Microsoft/go-winio/.gitignore new file mode 100644 index 00000000..b883f1fd --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/.gitignore @@ -0,0 +1 @@ +*.exe diff --git a/vendor/github.com/Microsoft/go-winio/LICENSE b/vendor/github.com/Microsoft/go-winio/LICENSE new file mode 100644 index 00000000..b8b569d7 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/Microsoft/go-winio/README.md b/vendor/github.com/Microsoft/go-winio/README.md new file mode 100644 index 00000000..56800105 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/README.md @@ -0,0 +1,22 @@ +# go-winio + +This repository contains utilities for efficiently performing Win32 IO operations in +Go. Currently, this is focused on accessing named pipes and other file handles, and +for using named pipes as a net transport. + +This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go +to reuse the thread to schedule another goroutine. This limits support to Windows Vista and +newer operating systems. This is similar to the implementation of network sockets in Go's net +package. + +Please see the LICENSE file for licensing information. + +This project has adopted the [Microsoft Open Source Code of +Conduct](https://opensource.microsoft.com/codeofconduct/). For more information +see the [Code of Conduct +FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact +[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional +questions or comments. + +Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe +for another named pipe implementation. diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go new file mode 100644 index 00000000..2be34af4 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -0,0 +1,280 @@ +// +build windows + +package winio + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "runtime" + "syscall" + "unicode/utf16" +) + +//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead +//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite + +const ( + BackupData = uint32(iota + 1) + BackupEaData + BackupSecurity + BackupAlternateData + BackupLink + BackupPropertyData + BackupObjectId + BackupReparseData + BackupSparseBlock + BackupTxfsData +) + +const ( + StreamSparseAttributes = uint32(8) +) + +const ( + WRITE_DAC = 0x40000 + WRITE_OWNER = 0x80000 + ACCESS_SYSTEM_SECURITY = 0x1000000 +) + +// BackupHeader represents a backup stream of a file. +type BackupHeader struct { + Id uint32 // The backup stream ID + Attributes uint32 // Stream attributes + Size int64 // The size of the stream in bytes + Name string // The name of the stream (for BackupAlternateData only). + Offset int64 // The offset of the stream in the file (for BackupSparseBlock only). +} + +type win32StreamId struct { + StreamId uint32 + Attributes uint32 + Size uint64 + NameSize uint32 +} + +// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series +// of BackupHeader values. +type BackupStreamReader struct { + r io.Reader + bytesLeft int64 +} + +// NewBackupStreamReader produces a BackupStreamReader from any io.Reader. +func NewBackupStreamReader(r io.Reader) *BackupStreamReader { + return &BackupStreamReader{r, 0} +} + +// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if +// it was not completely read. +func (r *BackupStreamReader) Next() (*BackupHeader, error) { + if r.bytesLeft > 0 { + if s, ok := r.r.(io.Seeker); ok { + // Make sure Seek on io.SeekCurrent sometimes succeeds + // before trying the actual seek. + if _, err := s.Seek(0, io.SeekCurrent); err == nil { + if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil { + return nil, err + } + r.bytesLeft = 0 + } + } + if _, err := io.Copy(ioutil.Discard, r); err != nil { + return nil, err + } + } + var wsi win32StreamId + if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil { + return nil, err + } + hdr := &BackupHeader{ + Id: wsi.StreamId, + Attributes: wsi.Attributes, + Size: int64(wsi.Size), + } + if wsi.NameSize != 0 { + name := make([]uint16, int(wsi.NameSize/2)) + if err := binary.Read(r.r, binary.LittleEndian, name); err != nil { + return nil, err + } + hdr.Name = syscall.UTF16ToString(name) + } + if wsi.StreamId == BackupSparseBlock { + if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { + return nil, err + } + hdr.Size -= 8 + } + r.bytesLeft = hdr.Size + return hdr, nil +} + +// Read reads from the current backup stream. +func (r *BackupStreamReader) Read(b []byte) (int, error) { + if r.bytesLeft == 0 { + return 0, io.EOF + } + if int64(len(b)) > r.bytesLeft { + b = b[:r.bytesLeft] + } + n, err := r.r.Read(b) + r.bytesLeft -= int64(n) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } else if r.bytesLeft == 0 && err == nil { + err = io.EOF + } + return n, err +} + +// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API. +type BackupStreamWriter struct { + w io.Writer + bytesLeft int64 +} + +// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer. +func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter { + return &BackupStreamWriter{w, 0} +} + +// WriteHeader writes the next backup stream header and prepares for calls to Write(). +func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error { + if w.bytesLeft != 0 { + return fmt.Errorf("missing %d bytes", w.bytesLeft) + } + name := utf16.Encode([]rune(hdr.Name)) + wsi := win32StreamId{ + StreamId: hdr.Id, + Attributes: hdr.Attributes, + Size: uint64(hdr.Size), + NameSize: uint32(len(name) * 2), + } + if hdr.Id == BackupSparseBlock { + // Include space for the int64 block offset + wsi.Size += 8 + } + if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil { + return err + } + if len(name) != 0 { + if err := binary.Write(w.w, binary.LittleEndian, name); err != nil { + return err + } + } + if hdr.Id == BackupSparseBlock { + if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil { + return err + } + } + w.bytesLeft = hdr.Size + return nil +} + +// Write writes to the current backup stream. +func (w *BackupStreamWriter) Write(b []byte) (int, error) { + if w.bytesLeft < int64(len(b)) { + return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft) + } + n, err := w.w.Write(b) + w.bytesLeft -= int64(n) + return n, err +} + +// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API. +type BackupFileReader struct { + f *os.File + includeSecurity bool + ctx uintptr +} + +// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true, +// Read will attempt to read the security descriptor of the file. +func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader { + r := &BackupFileReader{f, includeSecurity, 0} + return r +} + +// Read reads a backup stream from the file by calling the Win32 API BackupRead(). +func (r *BackupFileReader) Read(b []byte) (int, error) { + var bytesRead uint32 + err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) + if err != nil { + return 0, &os.PathError{"BackupRead", r.f.Name(), err} + } + runtime.KeepAlive(r.f) + if bytesRead == 0 { + return 0, io.EOF + } + return int(bytesRead), nil +} + +// Close frees Win32 resources associated with the BackupFileReader. It does not close +// the underlying file. +func (r *BackupFileReader) Close() error { + if r.ctx != 0 { + backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) + runtime.KeepAlive(r.f) + r.ctx = 0 + } + return nil +} + +// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API. +type BackupFileWriter struct { + f *os.File + includeSecurity bool + ctx uintptr +} + +// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true, +// Write() will attempt to restore the security descriptor from the stream. +func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter { + w := &BackupFileWriter{f, includeSecurity, 0} + return w +} + +// Write restores a portion of the file using the provided backup stream. +func (w *BackupFileWriter) Write(b []byte) (int, error) { + var bytesWritten uint32 + err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) + if err != nil { + return 0, &os.PathError{"BackupWrite", w.f.Name(), err} + } + runtime.KeepAlive(w.f) + if int(bytesWritten) != len(b) { + return int(bytesWritten), errors.New("not all bytes could be written") + } + return len(b), nil +} + +// Close frees Win32 resources associated with the BackupFileWriter. It does not +// close the underlying file. +func (w *BackupFileWriter) Close() error { + if w.ctx != 0 { + backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) + runtime.KeepAlive(w.f) + w.ctx = 0 + } + return nil +} + +// OpenForBackup opens a file or directory, potentially skipping access checks if the backup +// or restore privileges have been acquired. +// +// If the file opened was a directory, it cannot be used with Readdir(). +func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) { + winPath, err := syscall.UTF16FromString(path) + if err != nil { + return nil, err + } + h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0) + if err != nil { + err = &os.PathError{Op: "open", Path: path, Err: err} + return nil, err + } + return os.NewFile(uintptr(h), path), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go new file mode 100644 index 00000000..4051c1b3 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/ea.go @@ -0,0 +1,137 @@ +package winio + +import ( + "bytes" + "encoding/binary" + "errors" +) + +type fileFullEaInformation struct { + NextEntryOffset uint32 + Flags uint8 + NameLength uint8 + ValueLength uint16 +} + +var ( + fileFullEaInformationSize = binary.Size(&fileFullEaInformation{}) + + errInvalidEaBuffer = errors.New("invalid extended attribute buffer") + errEaNameTooLarge = errors.New("extended attribute name too large") + errEaValueTooLarge = errors.New("extended attribute value too large") +) + +// ExtendedAttribute represents a single Windows EA. +type ExtendedAttribute struct { + Name string + Value []byte + Flags uint8 +} + +func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { + var info fileFullEaInformation + err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) + if err != nil { + err = errInvalidEaBuffer + return + } + + nameOffset := fileFullEaInformationSize + nameLen := int(info.NameLength) + valueOffset := nameOffset + int(info.NameLength) + 1 + valueLen := int(info.ValueLength) + nextOffset := int(info.NextEntryOffset) + if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) { + err = errInvalidEaBuffer + return + } + + ea.Name = string(b[nameOffset : nameOffset+nameLen]) + ea.Value = b[valueOffset : valueOffset+valueLen] + ea.Flags = info.Flags + if info.NextEntryOffset != 0 { + nb = b[info.NextEntryOffset:] + } + return +} + +// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION +// buffer retrieved from BackupRead, ZwQueryEaFile, etc. +func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { + for len(b) != 0 { + ea, nb, err := parseEa(b) + if err != nil { + return nil, err + } + + eas = append(eas, ea) + b = nb + } + return +} + +func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { + if int(uint8(len(ea.Name))) != len(ea.Name) { + return errEaNameTooLarge + } + if int(uint16(len(ea.Value))) != len(ea.Value) { + return errEaValueTooLarge + } + entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value)) + withPadding := (entrySize + 3) &^ 3 + nextOffset := uint32(0) + if !last { + nextOffset = withPadding + } + info := fileFullEaInformation{ + NextEntryOffset: nextOffset, + Flags: ea.Flags, + NameLength: uint8(len(ea.Name)), + ValueLength: uint16(len(ea.Value)), + } + + err := binary.Write(buf, binary.LittleEndian, &info) + if err != nil { + return err + } + + _, err = buf.Write([]byte(ea.Name)) + if err != nil { + return err + } + + err = buf.WriteByte(0) + if err != nil { + return err + } + + _, err = buf.Write(ea.Value) + if err != nil { + return err + } + + _, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize]) + if err != nil { + return err + } + + return nil +} + +// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION +// buffer for use with BackupWrite, ZwSetEaFile, etc. +func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) { + var buf bytes.Buffer + for i := range eas { + last := false + if i == len(eas)-1 { + last = true + } + + err := writeEa(&buf, &eas[i], last) + if err != nil { + return nil, err + } + } + return buf.Bytes(), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go new file mode 100644 index 00000000..0385e410 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -0,0 +1,323 @@ +// +build windows + +package winio + +import ( + "errors" + "io" + "runtime" + "sync" + "sync/atomic" + "syscall" + "time" +) + +//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx +//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort +//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus +//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes +//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult + +type atomicBool int32 + +func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } +func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) } +func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) } +func (b *atomicBool) swap(new bool) bool { + var newInt int32 + if new { + newInt = 1 + } + return atomic.SwapInt32((*int32)(b), newInt) == 1 +} + +const ( + cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 + cFILE_SKIP_SET_EVENT_ON_HANDLE = 2 +) + +var ( + ErrFileClosed = errors.New("file has already been closed") + ErrTimeout = &timeoutError{} +) + +type timeoutError struct{} + +func (e *timeoutError) Error() string { return "i/o timeout" } +func (e *timeoutError) Timeout() bool { return true } +func (e *timeoutError) Temporary() bool { return true } + +type timeoutChan chan struct{} + +var ioInitOnce sync.Once +var ioCompletionPort syscall.Handle + +// ioResult contains the result of an asynchronous IO operation +type ioResult struct { + bytes uint32 + err error +} + +// ioOperation represents an outstanding asynchronous Win32 IO +type ioOperation struct { + o syscall.Overlapped + ch chan ioResult +} + +func initIo() { + h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) + if err != nil { + panic(err) + } + ioCompletionPort = h + go ioCompletionProcessor(h) +} + +// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall. +// It takes ownership of this handle and will close it if it is garbage collected. +type win32File struct { + handle syscall.Handle + wg sync.WaitGroup + wgLock sync.RWMutex + closing atomicBool + socket bool + readDeadline deadlineHandler + writeDeadline deadlineHandler +} + +type deadlineHandler struct { + setLock sync.Mutex + channel timeoutChan + channelLock sync.RWMutex + timer *time.Timer + timedout atomicBool +} + +// makeWin32File makes a new win32File from an existing file handle +func makeWin32File(h syscall.Handle) (*win32File, error) { + f := &win32File{handle: h} + ioInitOnce.Do(initIo) + _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) + if err != nil { + return nil, err + } + err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) + if err != nil { + return nil, err + } + f.readDeadline.channel = make(timeoutChan) + f.writeDeadline.channel = make(timeoutChan) + return f, nil +} + +func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { + // If we return the result of makeWin32File directly, it can result in an + // interface-wrapped nil, rather than a nil interface value. + f, err := makeWin32File(h) + if err != nil { + return nil, err + } + return f, nil +} + +// closeHandle closes the resources associated with a Win32 handle +func (f *win32File) closeHandle() { + f.wgLock.Lock() + // Atomically set that we are closing, releasing the resources only once. + if !f.closing.swap(true) { + f.wgLock.Unlock() + // cancel all IO and wait for it to complete + cancelIoEx(f.handle, nil) + f.wg.Wait() + // at this point, no new IO can start + syscall.Close(f.handle) + f.handle = 0 + } else { + f.wgLock.Unlock() + } +} + +// Close closes a win32File. +func (f *win32File) Close() error { + f.closeHandle() + return nil +} + +// prepareIo prepares for a new IO operation. +// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. +func (f *win32File) prepareIo() (*ioOperation, error) { + f.wgLock.RLock() + if f.closing.isSet() { + f.wgLock.RUnlock() + return nil, ErrFileClosed + } + f.wg.Add(1) + f.wgLock.RUnlock() + c := &ioOperation{} + c.ch = make(chan ioResult) + return c, nil +} + +// ioCompletionProcessor processes completed async IOs forever +func ioCompletionProcessor(h syscall.Handle) { + for { + var bytes uint32 + var key uintptr + var op *ioOperation + err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE) + if op == nil { + panic(err) + } + op.ch <- ioResult{bytes, err} + } +} + +// asyncIo processes the return value from ReadFile or WriteFile, blocking until +// the operation has actually completed. +func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { + if err != syscall.ERROR_IO_PENDING { + return int(bytes), err + } + + if f.closing.isSet() { + cancelIoEx(f.handle, &c.o) + } + + var timeout timeoutChan + if d != nil { + d.channelLock.Lock() + timeout = d.channel + d.channelLock.Unlock() + } + + var r ioResult + select { + case r = <-c.ch: + err = r.err + if err == syscall.ERROR_OPERATION_ABORTED { + if f.closing.isSet() { + err = ErrFileClosed + } + } else if err != nil && f.socket { + // err is from Win32. Query the overlapped structure to get the winsock error. + var bytes, flags uint32 + err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) + } + case <-timeout: + cancelIoEx(f.handle, &c.o) + r = <-c.ch + err = r.err + if err == syscall.ERROR_OPERATION_ABORTED { + err = ErrTimeout + } + } + + // runtime.KeepAlive is needed, as c is passed via native + // code to ioCompletionProcessor, c must remain alive + // until the channel read is complete. + runtime.KeepAlive(c) + return int(r.bytes), err +} + +// Read reads from a file handle. +func (f *win32File) Read(b []byte) (int, error) { + c, err := f.prepareIo() + if err != nil { + return 0, err + } + defer f.wg.Done() + + if f.readDeadline.timedout.isSet() { + return 0, ErrTimeout + } + + var bytes uint32 + err = syscall.ReadFile(f.handle, b, &bytes, &c.o) + n, err := f.asyncIo(c, &f.readDeadline, bytes, err) + runtime.KeepAlive(b) + + // Handle EOF conditions. + if err == nil && n == 0 && len(b) != 0 { + return 0, io.EOF + } else if err == syscall.ERROR_BROKEN_PIPE { + return 0, io.EOF + } else { + return n, err + } +} + +// Write writes to a file handle. +func (f *win32File) Write(b []byte) (int, error) { + c, err := f.prepareIo() + if err != nil { + return 0, err + } + defer f.wg.Done() + + if f.writeDeadline.timedout.isSet() { + return 0, ErrTimeout + } + + var bytes uint32 + err = syscall.WriteFile(f.handle, b, &bytes, &c.o) + n, err := f.asyncIo(c, &f.writeDeadline, bytes, err) + runtime.KeepAlive(b) + return n, err +} + +func (f *win32File) SetReadDeadline(deadline time.Time) error { + return f.readDeadline.set(deadline) +} + +func (f *win32File) SetWriteDeadline(deadline time.Time) error { + return f.writeDeadline.set(deadline) +} + +func (f *win32File) Flush() error { + return syscall.FlushFileBuffers(f.handle) +} + +func (f *win32File) Fd() uintptr { + return uintptr(f.handle) +} + +func (d *deadlineHandler) set(deadline time.Time) error { + d.setLock.Lock() + defer d.setLock.Unlock() + + if d.timer != nil { + if !d.timer.Stop() { + <-d.channel + } + d.timer = nil + } + d.timedout.setFalse() + + select { + case <-d.channel: + d.channelLock.Lock() + d.channel = make(chan struct{}) + d.channelLock.Unlock() + default: + } + + if deadline.IsZero() { + return nil + } + + timeoutIO := func() { + d.timedout.setTrue() + close(d.channel) + } + + now := time.Now() + duration := deadline.Sub(now) + if deadline.After(now) { + // Deadline is in the future, set a timer to wait + d.timer = time.AfterFunc(duration, timeoutIO) + } else { + // Deadline is in the past. Cancel all pending IO now. + timeoutIO() + } + return nil +} diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go new file mode 100644 index 00000000..ada2fbab --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -0,0 +1,61 @@ +// +build windows + +package winio + +import ( + "os" + "runtime" + "syscall" + "unsafe" +) + +//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx +//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle + +const ( + fileBasicInfo = 0 + fileIDInfo = 0x12 +) + +// FileBasicInfo contains file access time and file attributes information. +type FileBasicInfo struct { + CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime + FileAttributes uint32 + pad uint32 // padding +} + +// GetFileBasicInfo retrieves times and attributes for a file. +func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { + bi := &FileBasicInfo{} + if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return bi, nil +} + +// SetFileBasicInfo sets times and attributes for a file. +func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { + if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return nil +} + +// FileIDInfo contains the volume serial number and file ID for a file. This pair should be +// unique on a system. +type FileIDInfo struct { + VolumeSerialNumber uint64 + FileID [16]byte +} + +// GetFileID retrieves the unique (volume, file ID) pair for a file. +func GetFileID(f *os.File) (*FileIDInfo, error) { + fileID := &FileIDInfo{} + if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { + return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} + } + runtime.KeepAlive(f) + return fileID, nil +} diff --git a/vendor/github.com/Microsoft/go-winio/go.mod b/vendor/github.com/Microsoft/go-winio/go.mod new file mode 100644 index 00000000..a2eb6496 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/go.mod @@ -0,0 +1,9 @@ +module github.com/Microsoft/go-winio + +go 1.12 + +require ( + github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.4.1 + golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 +) diff --git a/vendor/github.com/Microsoft/go-winio/go.sum b/vendor/github.com/Microsoft/go-winio/go.sum new file mode 100644 index 00000000..6da76a49 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/go.sum @@ -0,0 +1,16 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go new file mode 100644 index 00000000..dbfe790e --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -0,0 +1,305 @@ +package winio + +import ( + "fmt" + "io" + "net" + "os" + "syscall" + "time" + "unsafe" + + "github.com/Microsoft/go-winio/pkg/guid" +) + +//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind + +const ( + afHvSock = 34 // AF_HYPERV + + socketError = ^uintptr(0) +) + +// An HvsockAddr is an address for a AF_HYPERV socket. +type HvsockAddr struct { + VMID guid.GUID + ServiceID guid.GUID +} + +type rawHvsockAddr struct { + Family uint16 + _ uint16 + VMID guid.GUID + ServiceID guid.GUID +} + +// Network returns the address's network name, "hvsock". +func (addr *HvsockAddr) Network() string { + return "hvsock" +} + +func (addr *HvsockAddr) String() string { + return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID) +} + +// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port. +func VsockServiceID(port uint32) guid.GUID { + g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3") + g.Data1 = port + return g +} + +func (addr *HvsockAddr) raw() rawHvsockAddr { + return rawHvsockAddr{ + Family: afHvSock, + VMID: addr.VMID, + ServiceID: addr.ServiceID, + } +} + +func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) { + addr.VMID = raw.VMID + addr.ServiceID = raw.ServiceID +} + +// HvsockListener is a socket listener for the AF_HYPERV address family. +type HvsockListener struct { + sock *win32File + addr HvsockAddr +} + +// HvsockConn is a connected socket of the AF_HYPERV address family. +type HvsockConn struct { + sock *win32File + local, remote HvsockAddr +} + +func newHvSocket() (*win32File, error) { + fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1) + if err != nil { + return nil, os.NewSyscallError("socket", err) + } + f, err := makeWin32File(fd) + if err != nil { + syscall.Close(fd) + return nil, err + } + f.socket = true + return f, nil +} + +// ListenHvsock listens for connections on the specified hvsock address. +func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { + l := &HvsockListener{addr: *addr} + sock, err := newHvSocket() + if err != nil { + return nil, l.opErr("listen", err) + } + sa := addr.raw() + err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa))) + if err != nil { + return nil, l.opErr("listen", os.NewSyscallError("socket", err)) + } + err = syscall.Listen(sock.handle, 16) + if err != nil { + return nil, l.opErr("listen", os.NewSyscallError("listen", err)) + } + return &HvsockListener{sock: sock, addr: *addr}, nil +} + +func (l *HvsockListener) opErr(op string, err error) error { + return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err} +} + +// Addr returns the listener's network address. +func (l *HvsockListener) Addr() net.Addr { + return &l.addr +} + +// Accept waits for the next connection and returns it. +func (l *HvsockListener) Accept() (_ net.Conn, err error) { + sock, err := newHvSocket() + if err != nil { + return nil, l.opErr("accept", err) + } + defer func() { + if sock != nil { + sock.Close() + } + }() + c, err := l.sock.prepareIo() + if err != nil { + return nil, l.opErr("accept", err) + } + defer l.sock.wg.Done() + + // AcceptEx, per documentation, requires an extra 16 bytes per address. + const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{})) + var addrbuf [addrlen * 2]byte + + var bytes uint32 + err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) + _, err = l.sock.asyncIo(c, nil, bytes, err) + if err != nil { + return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) + } + conn := &HvsockConn{ + sock: sock, + } + conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0]))) + conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) + sock = nil + return conn, nil +} + +// Close closes the listener, causing any pending Accept calls to fail. +func (l *HvsockListener) Close() error { + return l.sock.Close() +} + +/* Need to finish ConnectEx handling +func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) { + sock, err := newHvSocket() + if err != nil { + return nil, err + } + defer func() { + if sock != nil { + sock.Close() + } + }() + c, err := sock.prepareIo() + if err != nil { + return nil, err + } + defer sock.wg.Done() + var bytes uint32 + err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o) + _, err = sock.asyncIo(ctx, c, nil, bytes, err) + if err != nil { + return nil, err + } + conn := &HvsockConn{ + sock: sock, + remote: *addr, + } + sock = nil + return conn, nil +} +*/ + +func (conn *HvsockConn) opErr(op string, err error) error { + return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err} +} + +func (conn *HvsockConn) Read(b []byte) (int, error) { + c, err := conn.sock.prepareIo() + if err != nil { + return 0, conn.opErr("read", err) + } + defer conn.sock.wg.Done() + buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + var flags, bytes uint32 + err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) + n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err) + if err != nil { + if _, ok := err.(syscall.Errno); ok { + err = os.NewSyscallError("wsarecv", err) + } + return 0, conn.opErr("read", err) + } else if n == 0 { + err = io.EOF + } + return n, err +} + +func (conn *HvsockConn) Write(b []byte) (int, error) { + t := 0 + for len(b) != 0 { + n, err := conn.write(b) + if err != nil { + return t + n, err + } + t += n + b = b[n:] + } + return t, nil +} + +func (conn *HvsockConn) write(b []byte) (int, error) { + c, err := conn.sock.prepareIo() + if err != nil { + return 0, conn.opErr("write", err) + } + defer conn.sock.wg.Done() + buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} + var bytes uint32 + err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) + n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err) + if err != nil { + if _, ok := err.(syscall.Errno); ok { + err = os.NewSyscallError("wsasend", err) + } + return 0, conn.opErr("write", err) + } + return n, err +} + +// Close closes the socket connection, failing any pending read or write calls. +func (conn *HvsockConn) Close() error { + return conn.sock.Close() +} + +func (conn *HvsockConn) shutdown(how int) error { + err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) + if err != nil { + return os.NewSyscallError("shutdown", err) + } + return nil +} + +// CloseRead shuts down the read end of the socket. +func (conn *HvsockConn) CloseRead() error { + err := conn.shutdown(syscall.SHUT_RD) + if err != nil { + return conn.opErr("close", err) + } + return nil +} + +// CloseWrite shuts down the write end of the socket, notifying the other endpoint that +// no more data will be written. +func (conn *HvsockConn) CloseWrite() error { + err := conn.shutdown(syscall.SHUT_WR) + if err != nil { + return conn.opErr("close", err) + } + return nil +} + +// LocalAddr returns the local address of the connection. +func (conn *HvsockConn) LocalAddr() net.Addr { + return &conn.local +} + +// RemoteAddr returns the remote address of the connection. +func (conn *HvsockConn) RemoteAddr() net.Addr { + return &conn.remote +} + +// SetDeadline implements the net.Conn SetDeadline method. +func (conn *HvsockConn) SetDeadline(t time.Time) error { + conn.SetReadDeadline(t) + conn.SetWriteDeadline(t) + return nil +} + +// SetReadDeadline implements the net.Conn SetReadDeadline method. +func (conn *HvsockConn) SetReadDeadline(t time.Time) error { + return conn.sock.SetReadDeadline(t) +} + +// SetWriteDeadline implements the net.Conn SetWriteDeadline method. +func (conn *HvsockConn) SetWriteDeadline(t time.Time) error { + return conn.sock.SetWriteDeadline(t) +} diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go new file mode 100644 index 00000000..96700a73 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -0,0 +1,517 @@ +// +build windows + +package winio + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "os" + "runtime" + "syscall" + "time" + "unsafe" +) + +//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe +//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW +//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW +//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo +//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW +//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc +//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile +//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb +//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U +//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl + +type ioStatusBlock struct { + Status, Information uintptr +} + +type objectAttributes struct { + Length uintptr + RootDirectory uintptr + ObjectName *unicodeString + Attributes uintptr + SecurityDescriptor *securityDescriptor + SecurityQoS uintptr +} + +type unicodeString struct { + Length uint16 + MaximumLength uint16 + Buffer uintptr +} + +type securityDescriptor struct { + Revision byte + Sbz1 byte + Control uint16 + Owner uintptr + Group uintptr + Sacl uintptr + Dacl uintptr +} + +type ntstatus int32 + +func (status ntstatus) Err() error { + if status >= 0 { + return nil + } + return rtlNtStatusToDosError(status) +} + +const ( + cERROR_PIPE_BUSY = syscall.Errno(231) + cERROR_NO_DATA = syscall.Errno(232) + cERROR_PIPE_CONNECTED = syscall.Errno(535) + cERROR_SEM_TIMEOUT = syscall.Errno(121) + + cSECURITY_SQOS_PRESENT = 0x100000 + cSECURITY_ANONYMOUS = 0 + + cPIPE_TYPE_MESSAGE = 4 + + cPIPE_READMODE_MESSAGE = 2 + + cFILE_OPEN = 1 + cFILE_CREATE = 2 + + cFILE_PIPE_MESSAGE_TYPE = 1 + cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2 + + cSE_DACL_PRESENT = 4 +) + +var ( + // ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed. + // This error should match net.errClosing since docker takes a dependency on its text. + ErrPipeListenerClosed = errors.New("use of closed network connection") + + errPipeWriteClosed = errors.New("pipe has been closed for write") +) + +type win32Pipe struct { + *win32File + path string +} + +type win32MessageBytePipe struct { + win32Pipe + writeClosed bool + readEOF bool +} + +type pipeAddress string + +func (f *win32Pipe) LocalAddr() net.Addr { + return pipeAddress(f.path) +} + +func (f *win32Pipe) RemoteAddr() net.Addr { + return pipeAddress(f.path) +} + +func (f *win32Pipe) SetDeadline(t time.Time) error { + f.SetReadDeadline(t) + f.SetWriteDeadline(t) + return nil +} + +// CloseWrite closes the write side of a message pipe in byte mode. +func (f *win32MessageBytePipe) CloseWrite() error { + if f.writeClosed { + return errPipeWriteClosed + } + err := f.win32File.Flush() + if err != nil { + return err + } + _, err = f.win32File.Write(nil) + if err != nil { + return err + } + f.writeClosed = true + return nil +} + +// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since +// they are used to implement CloseWrite(). +func (f *win32MessageBytePipe) Write(b []byte) (int, error) { + if f.writeClosed { + return 0, errPipeWriteClosed + } + if len(b) == 0 { + return 0, nil + } + return f.win32File.Write(b) +} + +// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message +// mode pipe will return io.EOF, as will all subsequent reads. +func (f *win32MessageBytePipe) Read(b []byte) (int, error) { + if f.readEOF { + return 0, io.EOF + } + n, err := f.win32File.Read(b) + if err == io.EOF { + // If this was the result of a zero-byte read, then + // it is possible that the read was due to a zero-size + // message. Since we are simulating CloseWrite with a + // zero-byte message, ensure that all future Read() calls + // also return EOF. + f.readEOF = true + } else if err == syscall.ERROR_MORE_DATA { + // ERROR_MORE_DATA indicates that the pipe's read mode is message mode + // and the message still has more bytes. Treat this as a success, since + // this package presents all named pipes as byte streams. + err = nil + } + return n, err +} + +func (s pipeAddress) Network() string { + return "pipe" +} + +func (s pipeAddress) String() string { + return string(s) +} + +// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. +func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) { + for { + + select { + case <-ctx.Done(): + return syscall.Handle(0), ctx.Err() + default: + h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) + if err == nil { + return h, nil + } + if err != cERROR_PIPE_BUSY { + return h, &os.PathError{Err: err, Op: "open", Path: *path} + } + // Wait 10 msec and try again. This is a rather simplistic + // view, as we always try each 10 milliseconds. + time.Sleep(10 * time.Millisecond) + } + } +} + +// DialPipe connects to a named pipe by path, timing out if the connection +// takes longer than the specified duration. If timeout is nil, then we use +// a default timeout of 2 seconds. (We do not use WaitNamedPipe.) +func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { + var absTimeout time.Time + if timeout != nil { + absTimeout = time.Now().Add(*timeout) + } else { + absTimeout = time.Now().Add(2 * time.Second) + } + ctx, _ := context.WithDeadline(context.Background(), absTimeout) + conn, err := DialPipeContext(ctx, path) + if err == context.DeadlineExceeded { + return nil, ErrTimeout + } + return conn, err +} + +// DialPipeContext attempts to connect to a named pipe by `path` until `ctx` +// cancellation or timeout. +func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { + return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE) +} + +// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx` +// cancellation or timeout. +func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) { + var err error + var h syscall.Handle + h, err = tryDialPipe(ctx, &path, access) + if err != nil { + return nil, err + } + + var flags uint32 + err = getNamedPipeInfo(h, &flags, nil, nil, nil) + if err != nil { + return nil, err + } + + f, err := makeWin32File(h) + if err != nil { + syscall.Close(h) + return nil, err + } + + // If the pipe is in message mode, return a message byte pipe, which + // supports CloseWrite(). + if flags&cPIPE_TYPE_MESSAGE != 0 { + return &win32MessageBytePipe{ + win32Pipe: win32Pipe{win32File: f, path: path}, + }, nil + } + return &win32Pipe{win32File: f, path: path}, nil +} + +type acceptResponse struct { + f *win32File + err error +} + +type win32PipeListener struct { + firstHandle syscall.Handle + path string + config PipeConfig + acceptCh chan (chan acceptResponse) + closeCh chan int + doneCh chan int +} + +func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) { + path16, err := syscall.UTF16FromString(path) + if err != nil { + return 0, &os.PathError{Op: "open", Path: path, Err: err} + } + + var oa objectAttributes + oa.Length = unsafe.Sizeof(oa) + + var ntPath unicodeString + if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil { + return 0, &os.PathError{Op: "open", Path: path, Err: err} + } + defer localFree(ntPath.Buffer) + oa.ObjectName = &ntPath + + // The security descriptor is only needed for the first pipe. + if first { + if sd != nil { + len := uint32(len(sd)) + sdb := localAlloc(0, len) + defer localFree(sdb) + copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) + oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) + } else { + // Construct the default named pipe security descriptor. + var dacl uintptr + if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { + return 0, fmt.Errorf("getting default named pipe ACL: %s", err) + } + defer localFree(dacl) + + sdb := &securityDescriptor{ + Revision: 1, + Control: cSE_DACL_PRESENT, + Dacl: dacl, + } + oa.SecurityDescriptor = sdb + } + } + + typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS) + if c.MessageMode { + typ |= cFILE_PIPE_MESSAGE_TYPE + } + + disposition := uint32(cFILE_OPEN) + access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) + if first { + disposition = cFILE_CREATE + // By not asking for read or write access, the named pipe file system + // will put this pipe into an initially disconnected state, blocking + // client connections until the next call with first == false. + access = syscall.SYNCHRONIZE + } + + timeout := int64(-50 * 10000) // 50ms + + var ( + h syscall.Handle + iosb ioStatusBlock + ) + err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() + if err != nil { + return 0, &os.PathError{Op: "open", Path: path, Err: err} + } + + runtime.KeepAlive(ntPath) + return h, nil +} + +func (l *win32PipeListener) makeServerPipe() (*win32File, error) { + h, err := makeServerPipeHandle(l.path, nil, &l.config, false) + if err != nil { + return nil, err + } + f, err := makeWin32File(h) + if err != nil { + syscall.Close(h) + return nil, err + } + return f, nil +} + +func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) { + p, err := l.makeServerPipe() + if err != nil { + return nil, err + } + + // Wait for the client to connect. + ch := make(chan error) + go func(p *win32File) { + ch <- connectPipe(p) + }(p) + + select { + case err = <-ch: + if err != nil { + p.Close() + p = nil + } + case <-l.closeCh: + // Abort the connect request by closing the handle. + p.Close() + p = nil + err = <-ch + if err == nil || err == ErrFileClosed { + err = ErrPipeListenerClosed + } + } + return p, err +} + +func (l *win32PipeListener) listenerRoutine() { + closed := false + for !closed { + select { + case <-l.closeCh: + closed = true + case responseCh := <-l.acceptCh: + var ( + p *win32File + err error + ) + for { + p, err = l.makeConnectedServerPipe() + // If the connection was immediately closed by the client, try + // again. + if err != cERROR_NO_DATA { + break + } + } + responseCh <- acceptResponse{p, err} + closed = err == ErrPipeListenerClosed + } + } + syscall.Close(l.firstHandle) + l.firstHandle = 0 + // Notify Close() and Accept() callers that the handle has been closed. + close(l.doneCh) +} + +// PipeConfig contain configuration for the pipe listener. +type PipeConfig struct { + // SecurityDescriptor contains a Windows security descriptor in SDDL format. + SecurityDescriptor string + + // MessageMode determines whether the pipe is in byte or message mode. In either + // case the pipe is read in byte mode by default. The only practical difference in + // this implementation is that CloseWrite() is only supported for message mode pipes; + // CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only + // transferred to the reader (and returned as io.EOF in this implementation) + // when the pipe is in message mode. + MessageMode bool + + // InputBufferSize specifies the size of the input buffer, in bytes. + InputBufferSize int32 + + // OutputBufferSize specifies the size of the output buffer, in bytes. + OutputBufferSize int32 +} + +// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe. +// The pipe must not already exist. +func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { + var ( + sd []byte + err error + ) + if c == nil { + c = &PipeConfig{} + } + if c.SecurityDescriptor != "" { + sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor) + if err != nil { + return nil, err + } + } + h, err := makeServerPipeHandle(path, sd, c, true) + if err != nil { + return nil, err + } + l := &win32PipeListener{ + firstHandle: h, + path: path, + config: *c, + acceptCh: make(chan (chan acceptResponse)), + closeCh: make(chan int), + doneCh: make(chan int), + } + go l.listenerRoutine() + return l, nil +} + +func connectPipe(p *win32File) error { + c, err := p.prepareIo() + if err != nil { + return err + } + defer p.wg.Done() + + err = connectNamedPipe(p.handle, &c.o) + _, err = p.asyncIo(c, nil, 0, err) + if err != nil && err != cERROR_PIPE_CONNECTED { + return err + } + return nil +} + +func (l *win32PipeListener) Accept() (net.Conn, error) { + ch := make(chan acceptResponse) + select { + case l.acceptCh <- ch: + response := <-ch + err := response.err + if err != nil { + return nil, err + } + if l.config.MessageMode { + return &win32MessageBytePipe{ + win32Pipe: win32Pipe{win32File: response.f, path: l.path}, + }, nil + } + return &win32Pipe{win32File: response.f, path: l.path}, nil + case <-l.doneCh: + return nil, ErrPipeListenerClosed + } +} + +func (l *win32PipeListener) Close() error { + select { + case l.closeCh <- 1: + <-l.doneCh + case <-l.doneCh: + } + return nil +} + +func (l *win32PipeListener) Addr() net.Addr { + return pipeAddress(l.path) +} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go new file mode 100644 index 00000000..58640657 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go @@ -0,0 +1,235 @@ +// Package guid provides a GUID type. The backing structure for a GUID is +// identical to that used by the golang.org/x/sys/windows GUID type. +// There are two main binary encodings used for a GUID, the big-endian encoding, +// and the Windows (mixed-endian) encoding. See here for details: +// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding +package guid + +import ( + "crypto/rand" + "crypto/sha1" + "encoding" + "encoding/binary" + "fmt" + "strconv" + + "golang.org/x/sys/windows" +) + +// Variant specifies which GUID variant (or "type") of the GUID. It determines +// how the entirety of the rest of the GUID is interpreted. +type Variant uint8 + +// The variants specified by RFC 4122. +const ( + // VariantUnknown specifies a GUID variant which does not conform to one of + // the variant encodings specified in RFC 4122. + VariantUnknown Variant = iota + VariantNCS + VariantRFC4122 + VariantMicrosoft + VariantFuture +) + +// Version specifies how the bits in the GUID were generated. For instance, a +// version 4 GUID is randomly generated, and a version 5 is generated from the +// hash of an input string. +type Version uint8 + +var _ = (encoding.TextMarshaler)(GUID{}) +var _ = (encoding.TextUnmarshaler)(&GUID{}) + +// GUID represents a GUID/UUID. It has the same structure as +// golang.org/x/sys/windows.GUID so that it can be used with functions expecting +// that type. It is defined as its own type so that stringification and +// marshaling can be supported. The representation matches that used by native +// Windows code. +type GUID windows.GUID + +// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122. +func NewV4() (GUID, error) { + var b [16]byte + if _, err := rand.Read(b[:]); err != nil { + return GUID{}, err + } + + g := FromArray(b) + g.setVersion(4) // Version 4 means randomly generated. + g.setVariant(VariantRFC4122) + + return g, nil +} + +// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing) +// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name, +// and the sample code treats it as a series of bytes, so we do the same here. +// +// Some implementations, such as those found on Windows, treat the name as a +// big-endian UTF16 stream of bytes. If that is desired, the string can be +// encoded as such before being passed to this function. +func NewV5(namespace GUID, name []byte) (GUID, error) { + b := sha1.New() + namespaceBytes := namespace.ToArray() + b.Write(namespaceBytes[:]) + b.Write(name) + + a := [16]byte{} + copy(a[:], b.Sum(nil)) + + g := FromArray(a) + g.setVersion(5) // Version 5 means generated from a string. + g.setVariant(VariantRFC4122) + + return g, nil +} + +func fromArray(b [16]byte, order binary.ByteOrder) GUID { + var g GUID + g.Data1 = order.Uint32(b[0:4]) + g.Data2 = order.Uint16(b[4:6]) + g.Data3 = order.Uint16(b[6:8]) + copy(g.Data4[:], b[8:16]) + return g +} + +func (g GUID) toArray(order binary.ByteOrder) [16]byte { + b := [16]byte{} + order.PutUint32(b[0:4], g.Data1) + order.PutUint16(b[4:6], g.Data2) + order.PutUint16(b[6:8], g.Data3) + copy(b[8:16], g.Data4[:]) + return b +} + +// FromArray constructs a GUID from a big-endian encoding array of 16 bytes. +func FromArray(b [16]byte) GUID { + return fromArray(b, binary.BigEndian) +} + +// ToArray returns an array of 16 bytes representing the GUID in big-endian +// encoding. +func (g GUID) ToArray() [16]byte { + return g.toArray(binary.BigEndian) +} + +// FromWindowsArray constructs a GUID from a Windows encoding array of bytes. +func FromWindowsArray(b [16]byte) GUID { + return fromArray(b, binary.LittleEndian) +} + +// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows +// encoding. +func (g GUID) ToWindowsArray() [16]byte { + return g.toArray(binary.LittleEndian) +} + +func (g GUID) String() string { + return fmt.Sprintf( + "%08x-%04x-%04x-%04x-%012x", + g.Data1, + g.Data2, + g.Data3, + g.Data4[:2], + g.Data4[2:]) +} + +// FromString parses a string containing a GUID and returns the GUID. The only +// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` +// format. +func FromString(s string) (GUID, error) { + if len(s) != 36 { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + + var g GUID + + data1, err := strconv.ParseUint(s[0:8], 16, 32) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data1 = uint32(data1) + + data2, err := strconv.ParseUint(s[9:13], 16, 16) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data2 = uint16(data2) + + data3, err := strconv.ParseUint(s[14:18], 16, 16) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data3 = uint16(data3) + + for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} { + v, err := strconv.ParseUint(s[x:x+2], 16, 8) + if err != nil { + return GUID{}, fmt.Errorf("invalid GUID %q", s) + } + g.Data4[i] = uint8(v) + } + + return g, nil +} + +func (g *GUID) setVariant(v Variant) { + d := g.Data4[0] + switch v { + case VariantNCS: + d = (d & 0x7f) + case VariantRFC4122: + d = (d & 0x3f) | 0x80 + case VariantMicrosoft: + d = (d & 0x1f) | 0xc0 + case VariantFuture: + d = (d & 0x0f) | 0xe0 + case VariantUnknown: + fallthrough + default: + panic(fmt.Sprintf("invalid variant: %d", v)) + } + g.Data4[0] = d +} + +// Variant returns the GUID variant, as defined in RFC 4122. +func (g GUID) Variant() Variant { + b := g.Data4[0] + if b&0x80 == 0 { + return VariantNCS + } else if b&0xc0 == 0x80 { + return VariantRFC4122 + } else if b&0xe0 == 0xc0 { + return VariantMicrosoft + } else if b&0xe0 == 0xe0 { + return VariantFuture + } + return VariantUnknown +} + +func (g *GUID) setVersion(v Version) { + g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12) +} + +// Version returns the GUID version, as defined in RFC 4122. +func (g GUID) Version() Version { + return Version((g.Data3 & 0xF000) >> 12) +} + +// MarshalText returns the textual representation of the GUID. +func (g GUID) MarshalText() ([]byte, error) { + return []byte(g.String()), nil +} + +// UnmarshalText takes the textual representation of a GUID, and unmarhals it +// into this GUID. +func (g *GUID) UnmarshalText(text []byte) error { + g2, err := FromString(string(text)) + if err != nil { + return err + } + *g = g2 + return nil +} diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go new file mode 100644 index 00000000..9c83d36f --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/privilege.go @@ -0,0 +1,202 @@ +// +build windows + +package winio + +import ( + "bytes" + "encoding/binary" + "fmt" + "runtime" + "sync" + "syscall" + "unicode/utf16" + + "golang.org/x/sys/windows" +) + +//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges +//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf +//sys revertToSelf() (err error) = advapi32.RevertToSelf +//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken +//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread +//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW +//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW +//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW + +const ( + SE_PRIVILEGE_ENABLED = 2 + + ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 + + SeBackupPrivilege = "SeBackupPrivilege" + SeRestorePrivilege = "SeRestorePrivilege" +) + +const ( + securityAnonymous = iota + securityIdentification + securityImpersonation + securityDelegation +) + +var ( + privNames = make(map[string]uint64) + privNameMutex sync.Mutex +) + +// PrivilegeError represents an error enabling privileges. +type PrivilegeError struct { + privileges []uint64 +} + +func (e *PrivilegeError) Error() string { + s := "" + if len(e.privileges) > 1 { + s = "Could not enable privileges " + } else { + s = "Could not enable privilege " + } + for i, p := range e.privileges { + if i != 0 { + s += ", " + } + s += `"` + s += getPrivilegeName(p) + s += `"` + } + return s +} + +// RunWithPrivilege enables a single privilege for a function call. +func RunWithPrivilege(name string, fn func() error) error { + return RunWithPrivileges([]string{name}, fn) +} + +// RunWithPrivileges enables privileges for a function call. +func RunWithPrivileges(names []string, fn func() error) error { + privileges, err := mapPrivileges(names) + if err != nil { + return err + } + runtime.LockOSThread() + defer runtime.UnlockOSThread() + token, err := newThreadToken() + if err != nil { + return err + } + defer releaseThreadToken(token) + err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED) + if err != nil { + return err + } + return fn() +} + +func mapPrivileges(names []string) ([]uint64, error) { + var privileges []uint64 + privNameMutex.Lock() + defer privNameMutex.Unlock() + for _, name := range names { + p, ok := privNames[name] + if !ok { + err := lookupPrivilegeValue("", name, &p) + if err != nil { + return nil, err + } + privNames[name] = p + } + privileges = append(privileges, p) + } + return privileges, nil +} + +// EnableProcessPrivileges enables privileges globally for the process. +func EnableProcessPrivileges(names []string) error { + return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED) +} + +// DisableProcessPrivileges disables privileges globally for the process. +func DisableProcessPrivileges(names []string) error { + return enableDisableProcessPrivilege(names, 0) +} + +func enableDisableProcessPrivilege(names []string, action uint32) error { + privileges, err := mapPrivileges(names) + if err != nil { + return err + } + + p, _ := windows.GetCurrentProcess() + var token windows.Token + err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token) + if err != nil { + return err + } + + defer token.Close() + return adjustPrivileges(token, privileges, action) +} + +func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error { + var b bytes.Buffer + binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) + for _, p := range privileges { + binary.Write(&b, binary.LittleEndian, p) + binary.Write(&b, binary.LittleEndian, action) + } + prevState := make([]byte, b.Len()) + reqSize := uint32(0) + success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize) + if !success { + return err + } + if err == ERROR_NOT_ALL_ASSIGNED { + return &PrivilegeError{privileges} + } + return nil +} + +func getPrivilegeName(luid uint64) string { + var nameBuffer [256]uint16 + bufSize := uint32(len(nameBuffer)) + err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize) + if err != nil { + return fmt.Sprintf("", luid) + } + + var displayNameBuffer [256]uint16 + displayBufSize := uint32(len(displayNameBuffer)) + var langID uint32 + err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID) + if err != nil { + return fmt.Sprintf("", string(utf16.Decode(nameBuffer[:bufSize]))) + } + + return string(utf16.Decode(displayNameBuffer[:displayBufSize])) +} + +func newThreadToken() (windows.Token, error) { + err := impersonateSelf(securityImpersonation) + if err != nil { + return 0, err + } + + var token windows.Token + err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token) + if err != nil { + rerr := revertToSelf() + if rerr != nil { + panic(rerr) + } + return 0, err + } + return token, nil +} + +func releaseThreadToken(h windows.Token) { + err := revertToSelf() + if err != nil { + panic(err) + } + h.Close() +} diff --git a/vendor/github.com/Microsoft/go-winio/reparse.go b/vendor/github.com/Microsoft/go-winio/reparse.go new file mode 100644 index 00000000..fc1ee4d3 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/reparse.go @@ -0,0 +1,128 @@ +package winio + +import ( + "bytes" + "encoding/binary" + "fmt" + "strings" + "unicode/utf16" + "unsafe" +) + +const ( + reparseTagMountPoint = 0xA0000003 + reparseTagSymlink = 0xA000000C +) + +type reparseDataBuffer struct { + ReparseTag uint32 + ReparseDataLength uint16 + Reserved uint16 + SubstituteNameOffset uint16 + SubstituteNameLength uint16 + PrintNameOffset uint16 + PrintNameLength uint16 +} + +// ReparsePoint describes a Win32 symlink or mount point. +type ReparsePoint struct { + Target string + IsMountPoint bool +} + +// UnsupportedReparsePointError is returned when trying to decode a non-symlink or +// mount point reparse point. +type UnsupportedReparsePointError struct { + Tag uint32 +} + +func (e *UnsupportedReparsePointError) Error() string { + return fmt.Sprintf("unsupported reparse point %x", e.Tag) +} + +// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink +// or a mount point. +func DecodeReparsePoint(b []byte) (*ReparsePoint, error) { + tag := binary.LittleEndian.Uint32(b[0:4]) + return DecodeReparsePointData(tag, b[8:]) +} + +func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) { + isMountPoint := false + switch tag { + case reparseTagMountPoint: + isMountPoint = true + case reparseTagSymlink: + default: + return nil, &UnsupportedReparsePointError{tag} + } + nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6]) + if !isMountPoint { + nameOffset += 4 + } + nameLength := binary.LittleEndian.Uint16(b[6:8]) + name := make([]uint16, nameLength/2) + err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name) + if err != nil { + return nil, err + } + return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil +} + +func isDriveLetter(c byte) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') +} + +// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or +// mount point. +func EncodeReparsePoint(rp *ReparsePoint) []byte { + // Generate an NT path and determine if this is a relative path. + var ntTarget string + relative := false + if strings.HasPrefix(rp.Target, `\\?\`) { + ntTarget = `\??\` + rp.Target[4:] + } else if strings.HasPrefix(rp.Target, `\\`) { + ntTarget = `\??\UNC\` + rp.Target[2:] + } else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' { + ntTarget = `\??\` + rp.Target + } else { + ntTarget = rp.Target + relative = true + } + + // The paths must be NUL-terminated even though they are counted strings. + target16 := utf16.Encode([]rune(rp.Target + "\x00")) + ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00")) + + size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8 + size += len(ntTarget16)*2 + len(target16)*2 + + tag := uint32(reparseTagMountPoint) + if !rp.IsMountPoint { + tag = reparseTagSymlink + size += 4 // Add room for symlink flags + } + + data := reparseDataBuffer{ + ReparseTag: tag, + ReparseDataLength: uint16(size), + SubstituteNameOffset: 0, + SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2), + PrintNameOffset: uint16(len(ntTarget16) * 2), + PrintNameLength: uint16((len(target16) - 1) * 2), + } + + var b bytes.Buffer + binary.Write(&b, binary.LittleEndian, &data) + if !rp.IsMountPoint { + flags := uint32(0) + if relative { + flags |= 1 + } + binary.Write(&b, binary.LittleEndian, flags) + } + + binary.Write(&b, binary.LittleEndian, ntTarget16) + binary.Write(&b, binary.LittleEndian, target16) + return b.Bytes() +} diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go new file mode 100644 index 00000000..db1b370a --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/sd.go @@ -0,0 +1,98 @@ +// +build windows + +package winio + +import ( + "syscall" + "unsafe" +) + +//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW +//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW +//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW +//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW +//sys localFree(mem uintptr) = LocalFree +//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength + +const ( + cERROR_NONE_MAPPED = syscall.Errno(1332) +) + +type AccountLookupError struct { + Name string + Err error +} + +func (e *AccountLookupError) Error() string { + if e.Name == "" { + return "lookup account: empty account name specified" + } + var s string + switch e.Err { + case cERROR_NONE_MAPPED: + s = "not found" + default: + s = e.Err.Error() + } + return "lookup account " + e.Name + ": " + s +} + +type SddlConversionError struct { + Sddl string + Err error +} + +func (e *SddlConversionError) Error() string { + return "convert " + e.Sddl + ": " + e.Err.Error() +} + +// LookupSidByName looks up the SID of an account by name +func LookupSidByName(name string) (sid string, err error) { + if name == "" { + return "", &AccountLookupError{name, cERROR_NONE_MAPPED} + } + + var sidSize, sidNameUse, refDomainSize uint32 + err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) + if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { + return "", &AccountLookupError{name, err} + } + sidBuffer := make([]byte, sidSize) + refDomainBuffer := make([]uint16, refDomainSize) + err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) + if err != nil { + return "", &AccountLookupError{name, err} + } + var strBuffer *uint16 + err = convertSidToStringSid(&sidBuffer[0], &strBuffer) + if err != nil { + return "", &AccountLookupError{name, err} + } + sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:]) + localFree(uintptr(unsafe.Pointer(strBuffer))) + return sid, nil +} + +func SddlToSecurityDescriptor(sddl string) ([]byte, error) { + var sdBuffer uintptr + err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) + if err != nil { + return nil, &SddlConversionError{sddl, err} + } + defer localFree(sdBuffer) + sd := make([]byte, getSecurityDescriptorLength(sdBuffer)) + copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)]) + return sd, nil +} + +func SecurityDescriptorToSddl(sd []byte) (string, error) { + var sddl *uint16 + // The returned string length seems to including an aribtrary number of terminating NULs. + // Don't use it. + err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil) + if err != nil { + return "", err + } + defer localFree(uintptr(unsafe.Pointer(sddl))) + return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil +} diff --git a/vendor/github.com/Microsoft/go-winio/syscall.go b/vendor/github.com/Microsoft/go-winio/syscall.go new file mode 100644 index 00000000..5cb52bc7 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/syscall.go @@ -0,0 +1,3 @@ +package winio + +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go new file mode 100644 index 00000000..e26b01fa --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -0,0 +1,562 @@ +// Code generated by 'go generate'; DO NOT EDIT. + +package winio + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") + + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") + procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") + procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") + procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") + procLocalAlloc = modkernel32.NewProc("LocalAlloc") + procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") + procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") + procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") + procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") + procLocalFree = modkernel32.NewProc("LocalFree") + procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") + procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") + procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") + procBackupRead = modkernel32.NewProc("BackupRead") + procBackupWrite = modkernel32.NewProc("BackupWrite") + procbind = modws2_32.NewProc("bind") +) + +func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) + newport = syscall.Handle(r0) + if newport == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa) +} + +func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) +} + +func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func localAlloc(uFlags uint32, length uint32) (ptr uintptr) { + r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0) + ptr = uintptr(r0) + return +} + +func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { + r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) + status = ntstatus(r0) + return +} + +func rtlNtStatusToDosError(status ntstatus) (winerr error) { + r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) + if r0 != 0 { + winerr = syscall.Errno(r0) + } + return +} + +func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { + r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) + status = ntstatus(r0) + return +} + +func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { + r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) + status = ntstatus(r0) + return +} + +func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(accountName) + if err != nil { + return + } + return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse) +} + +func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertSidToStringSid(sid *byte, str **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(str) + if err != nil { + return + } + return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) +} + +func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func localFree(mem uintptr) { + syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0) + return +} + +func getSecurityDescriptorLength(sd uintptr) (len uint32) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) + len = uint32(r0) + return +} + +func getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(h), uintptr(class), uintptr(unsafe.Pointer(buffer)), uintptr(size), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { + var _p0 uint32 + if releaseAll { + _p0 = 1 + } else { + _p0 = 0 + } + r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize))) + success = r0 != 0 + if true { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func impersonateSelf(level uint32) (err error) { + r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func revertToSelf() (err error) { + r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) { + var _p0 uint32 + if openAsSelf { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getCurrentThread() (h syscall.Handle) { + r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) + h = syscall.Handle(r0) + return +} + +func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + var _p1 *uint16 + _p1, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _lookupPrivilegeValue(_p0, _p1, luid) +} + +func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) { + r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + return _lookupPrivilegeName(_p0, luid, buffer, size) +} + +func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(systemName) + if err != nil { + return + } + return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId) +} + +func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { + var _p0 *byte + if len(b) > 0 { + _p0 = &b[0] + } + var _p1 uint32 + if abort { + _p1 = 1 + } else { + _p1 = 0 + } + var _p2 uint32 + if processSecurity { + _p2 = 1 + } else { + _p2 = 0 + } + r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) { + var _p0 *byte + if len(b) > 0 { + _p0 = &b[0] + } + var _p1 uint32 + if abort { + _p1 = 1 + } else { + _p1 = 0 + } + var _p2 uint32 + if processSecurity { + _p2 = 1 + } else { + _p2 = 0 + } + r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socketError { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} diff --git a/vendor/github.com/VictoriaMetrics/metrics/go.mod b/vendor/github.com/VictoriaMetrics/metrics/go.mod index a66c19bd..1202ec8d 100644 --- a/vendor/github.com/VictoriaMetrics/metrics/go.mod +++ b/vendor/github.com/VictoriaMetrics/metrics/go.mod @@ -1,5 +1,5 @@ module github.com/VictoriaMetrics/metrics -require github.com/valyala/histogram v1.1.2 +require github.com/valyala/histogram v1.2.0 go 1.12 diff --git a/vendor/github.com/VictoriaMetrics/metrics/go.sum b/vendor/github.com/VictoriaMetrics/metrics/go.sum index b1219448..b94ade69 100644 --- a/vendor/github.com/VictoriaMetrics/metrics/go.sum +++ b/vendor/github.com/VictoriaMetrics/metrics/go.sum @@ -1,4 +1,4 @@ -github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI= -github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= -github.com/valyala/histogram v1.1.2 h1:vOk5VrGjMBIoPR5k6wA8vBaC8toeJ8XO0yfRjFEc1h8= -github.com/valyala/histogram v1.1.2/go.mod h1:CZAr6gK9dbD7hYx2s8WSPh0p5x5wETjC+2b3PJVtEdg= +github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= +github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= +github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= +github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= diff --git a/vendor/github.com/VictoriaMetrics/metrics/validator.go b/vendor/github.com/VictoriaMetrics/metrics/validator.go index 27e88ca3..9960189a 100644 --- a/vendor/github.com/VictoriaMetrics/metrics/validator.go +++ b/vendor/github.com/VictoriaMetrics/metrics/validator.go @@ -81,4 +81,4 @@ func validateIdent(s string) error { return nil } -var identRegexp = regexp.MustCompile("^[a-zA-Z_:][a-zA-Z0-9_:]*$") +var identRegexp = regexp.MustCompile("^[a-zA-Z_:.][a-zA-Z0-9_:.]*$") diff --git a/vendor/github.com/creack/pty/.gitignore b/vendor/github.com/creack/pty/.gitignore new file mode 100644 index 00000000..1f0a99f2 --- /dev/null +++ b/vendor/github.com/creack/pty/.gitignore @@ -0,0 +1,4 @@ +[568].out +_go* +_test* +_obj diff --git a/vendor/github.com/creack/pty/Dockerfile.golang b/vendor/github.com/creack/pty/Dockerfile.golang new file mode 100644 index 00000000..2ee82a3a --- /dev/null +++ b/vendor/github.com/creack/pty/Dockerfile.golang @@ -0,0 +1,17 @@ +ARG GOVERSION=1.14 +FROM golang:${GOVERSION} + +# Set base env. +ARG GOOS=linux +ARG GOARCH=amd64 +ENV GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w' + +# Pre compile the stdlib for 386/arm (32bits). +RUN go build -a std + +# Add the code to the image. +WORKDIR pty +ADD . . + +# Build the lib. +RUN go build diff --git a/vendor/github.com/creack/pty/Dockerfile.riscv b/vendor/github.com/creack/pty/Dockerfile.riscv new file mode 100644 index 00000000..7a30c94d --- /dev/null +++ b/vendor/github.com/creack/pty/Dockerfile.riscv @@ -0,0 +1,23 @@ +# NOTE: Using 1.13 as a base to build the RISCV compiler, the resulting version is based on go1.6. +FROM golang:1.13 + +# Clone and complie a riscv compatible version of the go compiler. +RUN git clone https://review.gerrithub.io/riscv/riscv-go /riscv-go +# riscvdev branch HEAD as of 2019-06-29. +RUN cd /riscv-go && git checkout 04885fddd096d09d4450726064d06dd107e374bf +ENV PATH=/riscv-go/misc/riscv:/riscv-go/bin:$PATH +RUN cd /riscv-go/src && GOROOT_BOOTSTRAP=$(go env GOROOT) ./make.bash +ENV GOROOT=/riscv-go + +# Set the base env. +ENV GOOS=linux GOARCH=riscv CGO_ENABLED=0 GOFLAGS='-v -ldflags=-s -ldflags=-w' + +# Pre compile the stdlib. +RUN go build -a std + +# Add the code to the image. +WORKDIR pty +ADD . . + +# Build the lib. +RUN go build diff --git a/vendor/github.com/creack/pty/LICENSE b/vendor/github.com/creack/pty/LICENSE new file mode 100644 index 00000000..6b7558b6 --- /dev/null +++ b/vendor/github.com/creack/pty/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2011 Keith Rarick + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall +be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/creack/pty/README.md b/vendor/github.com/creack/pty/README.md new file mode 100644 index 00000000..a4fe7670 --- /dev/null +++ b/vendor/github.com/creack/pty/README.md @@ -0,0 +1,107 @@ +# pty + +Pty is a Go package for using unix pseudo-terminals. + +## Install + +```sh +go get github.com/creack/pty +``` + +## Examples + +Note that those examples are for demonstration purpose only, to showcase how to use the library. They are not meant to be used in any kind of production environment. + +### Command + +```go +package main + +import ( + "io" + "os" + "os/exec" + + "github.com/creack/pty" +) + +func main() { + c := exec.Command("grep", "--color=auto", "bar") + f, err := pty.Start(c) + if err != nil { + panic(err) + } + + go func() { + f.Write([]byte("foo\n")) + f.Write([]byte("bar\n")) + f.Write([]byte("baz\n")) + f.Write([]byte{4}) // EOT + }() + io.Copy(os.Stdout, f) +} +``` + +### Shell + +```go +package main + +import ( + "io" + "log" + "os" + "os/exec" + "os/signal" + "syscall" + + "github.com/creack/pty" + "golang.org/x/term" +) + +func test() error { + // Create arbitrary command. + c := exec.Command("bash") + + // Start the command with a pty. + ptmx, err := pty.Start(c) + if err != nil { + return err + } + // Make sure to close the pty at the end. + defer func() { _ = ptmx.Close() }() // Best effort. + + // Handle pty size. + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGWINCH) + go func() { + for range ch { + if err := pty.InheritSize(os.Stdin, ptmx); err != nil { + log.Printf("error resizing pty: %s", err) + } + } + }() + ch <- syscall.SIGWINCH // Initial resize. + defer func() { signal.Stop(ch); close(ch) }() // Cleanup signals when done. + + // Set stdin in raw mode. + oldState, err := term.MakeRaw(int(os.Stdin.Fd())) + if err != nil { + panic(err) + } + defer func() { _ = term.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort. + + // Copy stdin to the pty and the pty to stdout. + // NOTE: The goroutine will keep reading until the next keystroke before returning. + go func() { _, _ = io.Copy(ptmx, os.Stdin) }() + _, _ = io.Copy(os.Stdout, ptmx) + + return nil +} + +func main() { + if err := test(); err != nil { + log.Fatal(err) + } +} +``` diff --git a/vendor/github.com/creack/pty/asm_solaris_amd64.s b/vendor/github.com/creack/pty/asm_solaris_amd64.s new file mode 100644 index 00000000..7fbef8ee --- /dev/null +++ b/vendor/github.com/creack/pty/asm_solaris_amd64.s @@ -0,0 +1,18 @@ +// 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. + +//go:build gc +//+build gc + +#include "textflag.h" + +// +// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go +// + +TEXT ·sysvicall6(SB),NOSPLIT,$0-88 + JMP syscall·sysvicall6(SB) + +TEXT ·rawSysvicall6(SB),NOSPLIT,$0-88 + JMP syscall·rawSysvicall6(SB) diff --git a/vendor/github.com/creack/pty/doc.go b/vendor/github.com/creack/pty/doc.go new file mode 100644 index 00000000..3c8b3244 --- /dev/null +++ b/vendor/github.com/creack/pty/doc.go @@ -0,0 +1,16 @@ +// Package pty provides functions for working with Unix terminals. +package pty + +import ( + "errors" + "os" +) + +// ErrUnsupported is returned if a function is not +// available on the current platform. +var ErrUnsupported = errors.New("unsupported") + +// Open a pty and its corresponding tty. +func Open() (pty, tty *os.File, err error) { + return open() +} diff --git a/vendor/github.com/creack/pty/go.mod b/vendor/github.com/creack/pty/go.mod new file mode 100644 index 00000000..7731235b --- /dev/null +++ b/vendor/github.com/creack/pty/go.mod @@ -0,0 +1,3 @@ +module github.com/creack/pty + +go 1.13 diff --git a/vendor/github.com/creack/pty/ioctl.go b/vendor/github.com/creack/pty/ioctl.go new file mode 100644 index 00000000..06764379 --- /dev/null +++ b/vendor/github.com/creack/pty/ioctl.go @@ -0,0 +1,19 @@ +//go:build !windows && !solaris +//+build !windows,!solaris + +package pty + +import "syscall" + +const ( + TIOCGWINSZ = syscall.TIOCGWINSZ + TIOCSWINSZ = syscall.TIOCSWINSZ +) + +func ioctl(fd, cmd, ptr uintptr) error { + _, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, cmd, ptr) + if e != 0 { + return e + } + return nil +} diff --git a/vendor/github.com/creack/pty/ioctl_bsd.go b/vendor/github.com/creack/pty/ioctl_bsd.go new file mode 100644 index 00000000..ab53e2db --- /dev/null +++ b/vendor/github.com/creack/pty/ioctl_bsd.go @@ -0,0 +1,40 @@ +//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) +//+build darwin dragonfly freebsd netbsd openbsd + +package pty + +// from +const ( + _IOC_VOID uintptr = 0x20000000 + _IOC_OUT uintptr = 0x40000000 + _IOC_IN uintptr = 0x80000000 + _IOC_IN_OUT uintptr = _IOC_OUT | _IOC_IN + _IOC_DIRMASK = _IOC_VOID | _IOC_OUT | _IOC_IN + + _IOC_PARAM_SHIFT = 13 + _IOC_PARAM_MASK = (1 << _IOC_PARAM_SHIFT) - 1 +) + +func _IOC_PARM_LEN(ioctl uintptr) uintptr { + return (ioctl >> 16) & _IOC_PARAM_MASK +} + +func _IOC(inout uintptr, group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return inout | (param_len&_IOC_PARAM_MASK)<<16 | uintptr(group)<<8 | ioctl_num +} + +func _IO(group byte, ioctl_num uintptr) uintptr { + return _IOC(_IOC_VOID, group, ioctl_num, 0) +} + +func _IOR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_OUT, group, ioctl_num, param_len) +} + +func _IOW(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_IN, group, ioctl_num, param_len) +} + +func _IOWR(group byte, ioctl_num uintptr, param_len uintptr) uintptr { + return _IOC(_IOC_IN_OUT, group, ioctl_num, param_len) +} diff --git a/vendor/github.com/creack/pty/ioctl_solaris.go b/vendor/github.com/creack/pty/ioctl_solaris.go new file mode 100644 index 00000000..8b6cc0ec --- /dev/null +++ b/vendor/github.com/creack/pty/ioctl_solaris.go @@ -0,0 +1,48 @@ +//go:build solaris +//+build solaris + +package pty + +import ( + "syscall" + "unsafe" +) + +//go:cgo_import_dynamic libc_ioctl ioctl "libc.so" +//go:linkname procioctl libc_ioctl +var procioctl uintptr + +const ( + // see /usr/include/sys/stropts.h + I_PUSH = uintptr((int32('S')<<8 | 002)) + I_STR = uintptr((int32('S')<<8 | 010)) + I_FIND = uintptr((int32('S')<<8 | 013)) + + // see /usr/include/sys/ptms.h + ISPTM = (int32('P') << 8) | 1 + UNLKPT = (int32('P') << 8) | 2 + PTSSTTY = (int32('P') << 8) | 3 + ZONEPT = (int32('P') << 8) | 4 + OWNERPT = (int32('P') << 8) | 5 + + // see /usr/include/sys/termios.h + TIOCSWINSZ = (uint32('T') << 8) | 103 + TIOCGWINSZ = (uint32('T') << 8) | 104 +) + +type strioctl struct { + icCmd int32 + icTimeout int32 + icLen int32 + icDP unsafe.Pointer +} + +// Defined in asm_solaris_amd64.s. +func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) + +func ioctl(fd, cmd, ptr uintptr) error { + if _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, fd, cmd, ptr, 0, 0, 0); errno != 0 { + return errno + } + return nil +} diff --git a/vendor/github.com/creack/pty/mktypes.bash b/vendor/github.com/creack/pty/mktypes.bash new file mode 100644 index 00000000..7f71bda6 --- /dev/null +++ b/vendor/github.com/creack/pty/mktypes.bash @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +GOOSARCH="${GOOS}_${GOARCH}" +case "$GOOSARCH" in +_* | *_ | _) + echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 + exit 1 + ;; +esac + +GODEFS="go tool cgo -godefs" + +$GODEFS types.go |gofmt > ztypes_$GOARCH.go + +case $GOOS in +freebsd|dragonfly|netbsd|openbsd) + $GODEFS types_$GOOS.go |gofmt > ztypes_$GOOSARCH.go + ;; +esac diff --git a/vendor/github.com/creack/pty/pty_darwin.go b/vendor/github.com/creack/pty/pty_darwin.go new file mode 100644 index 00000000..cca0971f --- /dev/null +++ b/vendor/github.com/creack/pty/pty_darwin.go @@ -0,0 +1,68 @@ +//go:build darwin +//+build darwin + +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + pFD, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC, 0) + if err != nil { + return nil, nil, err + } + p := os.NewFile(uintptr(pFD), "/dev/ptmx") + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := grantpt(p); err != nil { + return nil, nil, err + } + + if err := unlockpt(p); err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + n := make([]byte, _IOC_PARM_LEN(syscall.TIOCPTYGNAME)) + + err := ioctl(f.Fd(), syscall.TIOCPTYGNAME, uintptr(unsafe.Pointer(&n[0]))) + if err != nil { + return "", err + } + + for i, c := range n { + if c == 0 { + return string(n[:i]), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} + +func grantpt(f *os.File) error { + return ioctl(f.Fd(), syscall.TIOCPTYGRANT, 0) +} + +func unlockpt(f *os.File) error { + return ioctl(f.Fd(), syscall.TIOCPTYUNLK, 0) +} diff --git a/vendor/github.com/creack/pty/pty_dragonfly.go b/vendor/github.com/creack/pty/pty_dragonfly.go new file mode 100644 index 00000000..7a1fec3a --- /dev/null +++ b/vendor/github.com/creack/pty/pty_dragonfly.go @@ -0,0 +1,83 @@ +//go:build dragonfly +//+build dragonfly + +package pty + +import ( + "errors" + "os" + "strings" + "syscall" + "unsafe" +) + +// same code as pty_darwin.go +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := grantpt(p); err != nil { + return nil, nil, err + } + + if err := unlockpt(p); err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func grantpt(f *os.File) error { + _, err := isptmaster(f.Fd()) + return err +} + +func unlockpt(f *os.File) error { + _, err := isptmaster(f.Fd()) + return err +} + +func isptmaster(fd uintptr) (bool, error) { + err := ioctl(fd, syscall.TIOCISPTMASTER, 0) + return err == nil, err +} + +var ( + emptyFiodgnameArg fiodgnameArg + ioctl_FIODNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) +) + +func ptsname(f *os.File) (string, error) { + name := make([]byte, _C_SPECNAMELEN) + fa := fiodgnameArg{Name: (*byte)(unsafe.Pointer(&name[0])), Len: _C_SPECNAMELEN, Pad_cgo_0: [4]byte{0, 0, 0, 0}} + + err := ioctl(f.Fd(), ioctl_FIODNAME, uintptr(unsafe.Pointer(&fa))) + if err != nil { + return "", err + } + + for i, c := range name { + if c == 0 { + s := "/dev/" + string(name[:i]) + return strings.Replace(s, "ptm", "pts", -1), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} diff --git a/vendor/github.com/creack/pty/pty_freebsd.go b/vendor/github.com/creack/pty/pty_freebsd.go new file mode 100644 index 00000000..a4cfd925 --- /dev/null +++ b/vendor/github.com/creack/pty/pty_freebsd.go @@ -0,0 +1,81 @@ +//go:build freebsd +//+build freebsd + +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func posixOpenpt(oflag int) (fd int, err error) { + r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) + fd = int(r0) + if e1 != 0 { + err = e1 + } + return fd, err +} + +func open() (pty, tty *os.File, err error) { + fd, err := posixOpenpt(syscall.O_RDWR | syscall.O_CLOEXEC) + if err != nil { + return nil, nil, err + } + p := os.NewFile(uintptr(fd), "/dev/pts") + // In case of error after this point, make sure we close the pts fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + t, err := os.OpenFile("/dev/"+sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func isptmaster(fd uintptr) (bool, error) { + err := ioctl(fd, syscall.TIOCPTMASTER, 0) + return err == nil, err +} + +var ( + emptyFiodgnameArg fiodgnameArg + ioctlFIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) +) + +func ptsname(f *os.File) (string, error) { + master, err := isptmaster(f.Fd()) + if err != nil { + return "", err + } + if !master { + return "", syscall.EINVAL + } + + const n = _C_SPECNAMELEN + 1 + var ( + buf = make([]byte, n) + arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))} + ) + if err := ioctl(f.Fd(), ioctlFIODGNAME, uintptr(unsafe.Pointer(&arg))); err != nil { + return "", err + } + + for i, c := range buf { + if c == 0 { + return string(buf[:i]), nil + } + } + return "", errors.New("FIODGNAME string not NUL-terminated") +} diff --git a/vendor/github.com/creack/pty/pty_linux.go b/vendor/github.com/creack/pty/pty_linux.go new file mode 100644 index 00000000..22ccbe12 --- /dev/null +++ b/vendor/github.com/creack/pty/pty_linux.go @@ -0,0 +1,54 @@ +//go:build linux +//+build linux + +package pty + +import ( + "os" + "strconv" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := unlockpt(p); err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) //nolint:gosec // Expected Open from a variable. + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + var n _C_uint + err := ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) //nolint:gosec // Expected unsafe pointer for Syscall call. + if err != nil { + return "", err + } + return "/dev/pts/" + strconv.Itoa(int(n)), nil +} + +func unlockpt(f *os.File) error { + var u _C_int + // use TIOCSPTLCK with a pointer to zero to clear the lock + return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) //nolint:gosec // Expected unsafe pointer for Syscall call. +} diff --git a/vendor/github.com/creack/pty/pty_netbsd.go b/vendor/github.com/creack/pty/pty_netbsd.go new file mode 100644 index 00000000..98c089c8 --- /dev/null +++ b/vendor/github.com/creack/pty/pty_netbsd.go @@ -0,0 +1,69 @@ +//go:build netbsd +//+build netbsd + +package pty + +import ( + "errors" + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := grantpt(p); err != nil { + return nil, nil, err + } + + // In NetBSD unlockpt() does nothing, so it isn't called here. + + t, err := os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + /* + * from ptsname(3): The ptsname() function is equivalent to: + * struct ptmget pm; + * ioctl(fd, TIOCPTSNAME, &pm) == -1 ? NULL : pm.sn; + */ + var ptm ptmget + if err := ioctl(f.Fd(), uintptr(ioctl_TIOCPTSNAME), uintptr(unsafe.Pointer(&ptm))); err != nil { + return "", err + } + name := make([]byte, len(ptm.Sn)) + for i, c := range ptm.Sn { + name[i] = byte(c) + if c == 0 { + return string(name[:i]), nil + } + } + return "", errors.New("TIOCPTSNAME string not NUL-terminated") +} + +func grantpt(f *os.File) error { + /* + * from grantpt(3): Calling grantpt() is equivalent to: + * ioctl(fd, TIOCGRANTPT, 0); + */ + return ioctl(f.Fd(), uintptr(ioctl_TIOCGRANTPT), 0) +} diff --git a/vendor/github.com/creack/pty/pty_openbsd.go b/vendor/github.com/creack/pty/pty_openbsd.go new file mode 100644 index 00000000..d72b9d8d --- /dev/null +++ b/vendor/github.com/creack/pty/pty_openbsd.go @@ -0,0 +1,36 @@ +//go:build openbsd +//+build openbsd + +package pty + +import ( + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + /* + * from ptm(4): + * The PTMGET command allocates a free pseudo terminal, changes its + * ownership to the caller, revokes the access privileges for all previous + * users, opens the file descriptors for the pty and tty devices and + * returns them to the caller in struct ptmget. + */ + + p, err := os.OpenFile("/dev/ptm", os.O_RDWR|syscall.O_CLOEXEC, 0) + if err != nil { + return nil, nil, err + } + defer p.Close() + + var ptm ptmget + if err := ioctl(p.Fd(), uintptr(ioctl_PTMGET), uintptr(unsafe.Pointer(&ptm))); err != nil { + return nil, nil, err + } + + pty = os.NewFile(uintptr(ptm.Cfd), "/dev/ptm") + tty = os.NewFile(uintptr(ptm.Sfd), "/dev/ptm") + + return pty, tty, nil +} diff --git a/vendor/github.com/creack/pty/pty_solaris.go b/vendor/github.com/creack/pty/pty_solaris.go new file mode 100644 index 00000000..17e47461 --- /dev/null +++ b/vendor/github.com/creack/pty/pty_solaris.go @@ -0,0 +1,152 @@ +//go:build solaris +//+build solaris + +package pty + +/* based on: +http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/pt.c +*/ + +import ( + "errors" + "os" + "strconv" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + ptmxfd, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx") + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := grantpt(p); err != nil { + return nil, nil, err + } + + if err := unlockpt(p); err != nil { + return nil, nil, err + } + + ptsfd, err := syscall.Open(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + t := os.NewFile(uintptr(ptsfd), sname) + + // In case of error after this point, make sure we close the pts fd. + defer func() { + if err != nil { + _ = t.Close() // Best effort. + } + }() + + // pushing terminal driver STREAMS modules as per pts(7) + for _, mod := range []string{"ptem", "ldterm", "ttcompat"} { + if err := streamsPush(t, mod); err != nil { + return nil, nil, err + } + } + + return p, t, nil +} + +func ptsname(f *os.File) (string, error) { + dev, err := ptsdev(f.Fd()) + if err != nil { + return "", err + } + fn := "/dev/pts/" + strconv.FormatInt(int64(dev), 10) + + if err := syscall.Access(fn, 0); err != nil { + return "", err + } + return fn, nil +} + +func unlockpt(f *os.File) error { + istr := strioctl{ + icCmd: UNLKPT, + icTimeout: 0, + icLen: 0, + icDP: nil, + } + return ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))) +} + +func minor(x uint64) uint64 { return x & 0377 } + +func ptsdev(fd uintptr) (uint64, error) { + istr := strioctl{ + icCmd: ISPTM, + icTimeout: 0, + icLen: 0, + icDP: nil, + } + + if err := ioctl(fd, I_STR, uintptr(unsafe.Pointer(&istr))); err != nil { + return 0, err + } + var status syscall.Stat_t + if err := syscall.Fstat(int(fd), &status); err != nil { + return 0, err + } + return uint64(minor(status.Rdev)), nil +} + +type ptOwn struct { + rUID int32 + rGID int32 +} + +func grantpt(f *os.File) error { + if _, err := ptsdev(f.Fd()); err != nil { + return err + } + pto := ptOwn{ + rUID: int32(os.Getuid()), + // XXX should first attempt to get gid of DEFAULT_TTY_GROUP="tty" + rGID: int32(os.Getgid()), + } + istr := strioctl{ + icCmd: OWNERPT, + icTimeout: 0, + icLen: int32(unsafe.Sizeof(strioctl{})), + icDP: unsafe.Pointer(&pto), + } + if err := ioctl(f.Fd(), I_STR, uintptr(unsafe.Pointer(&istr))); err != nil { + return errors.New("access denied") + } + return nil +} + +// streamsPush pushes STREAMS modules if not already done so. +func streamsPush(f *os.File, mod string) error { + buf := []byte(mod) + + // XXX I_FIND is not returning an error when the module + // is already pushed even though truss reports a return + // value of 1. A bug in the Go Solaris syscall interface? + // XXX without this we are at risk of the issue + // https://www.illumos.org/issues/9042 + // but since we are not using libc or XPG4.2, we should not be + // double-pushing modules + + if err := ioctl(f.Fd(), I_FIND, uintptr(unsafe.Pointer(&buf[0]))); err != nil { + return nil + } + return ioctl(f.Fd(), I_PUSH, uintptr(unsafe.Pointer(&buf[0]))) +} diff --git a/vendor/github.com/creack/pty/pty_unsupported.go b/vendor/github.com/creack/pty/pty_unsupported.go new file mode 100644 index 00000000..765523ab --- /dev/null +++ b/vendor/github.com/creack/pty/pty_unsupported.go @@ -0,0 +1,12 @@ +//go:build !linux && !darwin && !freebsd && !dragonfly && !netbsd && !openbsd && !solaris +//+build !linux,!darwin,!freebsd,!dragonfly,!netbsd,!openbsd,!solaris + +package pty + +import ( + "os" +) + +func open() (pty, tty *os.File, err error) { + return nil, nil, ErrUnsupported +} diff --git a/vendor/github.com/creack/pty/run.go b/vendor/github.com/creack/pty/run.go new file mode 100644 index 00000000..160001f9 --- /dev/null +++ b/vendor/github.com/creack/pty/run.go @@ -0,0 +1,75 @@ +//go:build !windows +//+build !windows + +package pty + +import ( + "os" + "os/exec" + "syscall" +) + +// Start assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, +// and c.Stderr, calls c.Start, and returns the File of the tty's +// corresponding pty. +// +// Starts the process in a new session and sets the controlling terminal. +func Start(cmd *exec.Cmd) (*os.File, error) { + return StartWithSize(cmd, nil) +} + +// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, +// and c.Stderr, calls c.Start, and returns the File of the tty's +// corresponding pty. +// +// This will resize the pty to the specified size before starting the command. +// Starts the process in a new session and sets the controlling terminal. +func StartWithSize(cmd *exec.Cmd, ws *Winsize) (*os.File, error) { + if cmd.SysProcAttr == nil { + cmd.SysProcAttr = &syscall.SysProcAttr{} + } + cmd.SysProcAttr.Setsid = true + cmd.SysProcAttr.Setctty = true + return StartWithAttrs(cmd, ws, cmd.SysProcAttr) +} + +// StartWithAttrs assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, +// and c.Stderr, calls c.Start, and returns the File of the tty's +// corresponding pty. +// +// This will resize the pty to the specified size before starting the command if a size is provided. +// The `attrs` parameter overrides the one set in c.SysProcAttr. +// +// This should generally not be needed. Used in some edge cases where it is needed to create a pty +// without a controlling terminal. +func StartWithAttrs(c *exec.Cmd, sz *Winsize, attrs *syscall.SysProcAttr) (*os.File, error) { + pty, tty, err := Open() + if err != nil { + return nil, err + } + defer func() { _ = tty.Close() }() // Best effort. + + if sz != nil { + if err := Setsize(pty, sz); err != nil { + _ = pty.Close() // Best effort. + return nil, err + } + } + if c.Stdout == nil { + c.Stdout = tty + } + if c.Stderr == nil { + c.Stderr = tty + } + if c.Stdin == nil { + c.Stdin = tty + } + + c.SysProcAttr = attrs + + if err := c.Start(); err != nil { + _ = pty.Close() // Best effort. + return nil, err + } + return pty, err +} diff --git a/vendor/github.com/creack/pty/test_crosscompile.sh b/vendor/github.com/creack/pty/test_crosscompile.sh new file mode 100644 index 00000000..c736c8b0 --- /dev/null +++ b/vendor/github.com/creack/pty/test_crosscompile.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env sh + +# Test script checking that all expected os/arch compile properly. +# Does not actually test the logic, just the compilation so we make sure we don't break code depending on the lib. + +echo2() { + echo $@ >&2 +} + +trap end 0 +end() { + [ "$?" = 0 ] && echo2 "Pass." || (echo2 "Fail."; exit 1) +} + +cross() { + os=$1 + shift + echo2 "Build for $os." + for arch in $@; do + echo2 " - $os/$arch" + GOOS=$os GOARCH=$arch go build + done + echo2 +} + +set -e + +cross linux amd64 386 arm arm64 ppc64 ppc64le s390x mips mipsle mips64 mips64le +cross darwin amd64 arm64 +cross freebsd amd64 386 arm arm64 +cross netbsd amd64 386 arm arm64 +cross openbsd amd64 386 arm arm64 +cross dragonfly amd64 +cross solaris amd64 + +# Not expected to work but should still compile. +cross windows amd64 386 arm + +# TODO: Fix compilation error on openbsd/arm. +# TODO: Merge the solaris PR. + +# Some os/arch require a different compiler. Run in docker. +if ! hash docker; then + # If docker is not present, stop here. + return +fi + +echo2 "Build for linux." +echo2 " - linux/riscv" +docker build -t creack-pty-test -f Dockerfile.riscv . + +# Golang dropped support for darwin 32bits since go1.15. Make sure the lib still compile with go1.14 on those archs. +echo2 "Build for darwin (32bits)." +echo2 " - darwin/386" +docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=386 . +echo2 " - darwin/arm" +docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.14 --build-arg=GOOS=darwin --build-arg=GOARCH=arm . + +# Run a single test for an old go version. Would be best with go1.0, but not available on Dockerhub. +# Using 1.6 as it is the base version for the RISCV compiler. +# Would also be better to run all the tests, not just one, need to refactor this file to allow for specifc archs per version. +echo2 "Build for linux - go1.6." +echo2 " - linux/amd64" +docker build -t creack-pty-test -f Dockerfile.golang --build-arg=GOVERSION=1.6 --build-arg=GOOS=linux --build-arg=GOARCH=amd64 . diff --git a/vendor/github.com/creack/pty/winsize.go b/vendor/github.com/creack/pty/winsize.go new file mode 100644 index 00000000..9660a93b --- /dev/null +++ b/vendor/github.com/creack/pty/winsize.go @@ -0,0 +1,24 @@ +package pty + +import "os" + +// InheritSize applies the terminal size of pty to tty. This should be run +// in a signal handler for syscall.SIGWINCH to automatically resize the tty when +// the pty receives a window size change notification. +func InheritSize(pty, tty *os.File) error { + size, err := GetsizeFull(pty) + if err != nil { + return err + } + if err := Setsize(tty, size); err != nil { + return err + } + return nil +} + +// Getsize returns the number of rows (lines) and cols (positions +// in each line) in terminal t. +func Getsize(t *os.File) (rows, cols int, err error) { + ws, err := GetsizeFull(t) + return int(ws.Rows), int(ws.Cols), err +} diff --git a/vendor/github.com/creack/pty/winsize_unix.go b/vendor/github.com/creack/pty/winsize_unix.go new file mode 100644 index 00000000..f358e908 --- /dev/null +++ b/vendor/github.com/creack/pty/winsize_unix.go @@ -0,0 +1,35 @@ +//go:build !windows +//+build !windows + +package pty + +import ( + "os" + "syscall" + "unsafe" +) + +// Winsize describes the terminal size. +type Winsize struct { + Rows uint16 // ws_row: Number of rows (in cells) + Cols uint16 // ws_col: Number of columns (in cells) + X uint16 // ws_xpixel: Width in pixels + Y uint16 // ws_ypixel: Height in pixels +} + +// Setsize resizes t to s. +func Setsize(t *os.File, ws *Winsize) error { + //nolint:gosec // Expected unsafe pointer for Syscall call. + return ioctl(t.Fd(), syscall.TIOCSWINSZ, uintptr(unsafe.Pointer(ws))) +} + +// GetsizeFull returns the full terminal size description. +func GetsizeFull(t *os.File) (size *Winsize, err error) { + var ws Winsize + + //nolint:gosec // Expected unsafe pointer for Syscall call. + if err := ioctl(t.Fd(), syscall.TIOCGWINSZ, uintptr(unsafe.Pointer(&ws))); err != nil { + return nil, err + } + return &ws, nil +} diff --git a/vendor/github.com/creack/pty/winsize_unsupported.go b/vendor/github.com/creack/pty/winsize_unsupported.go new file mode 100644 index 00000000..c4bff44e --- /dev/null +++ b/vendor/github.com/creack/pty/winsize_unsupported.go @@ -0,0 +1,23 @@ +//go:build windows +//+build windows + +package pty + +import ( + "os" +) + +// Winsize is a dummy struct to enable compilation on unsupported platforms. +type Winsize struct { + Rows, Cols, X, Y uint +} + +// Setsize resizes t to s. +func Setsize(*os.File, *Winsize) error { + return ErrUnsupported +} + +// GetsizeFull returns the full terminal size description. +func GetsizeFull(*os.File) (*Winsize, error) { + return nil, ErrUnsupported +} diff --git a/vendor/github.com/creack/pty/ztypes_386.go b/vendor/github.com/creack/pty/ztypes_386.go new file mode 100644 index 00000000..794515b4 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_386.go @@ -0,0 +1,12 @@ +//go:build 386 +//+build 386 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_amd64.go b/vendor/github.com/creack/pty/ztypes_amd64.go new file mode 100644 index 00000000..dc6c5252 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_amd64.go @@ -0,0 +1,12 @@ +//go:build amd64 +//+build amd64 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_arm.go b/vendor/github.com/creack/pty/ztypes_arm.go new file mode 100644 index 00000000..eac9b1ef --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_arm.go @@ -0,0 +1,12 @@ +//go:build arm +//+build arm + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_arm64.go b/vendor/github.com/creack/pty/ztypes_arm64.go new file mode 100644 index 00000000..ecb3ddca --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_arm64.go @@ -0,0 +1,12 @@ +//go:build arm64 +//+build arm64 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_dragonfly_amd64.go b/vendor/github.com/creack/pty/ztypes_dragonfly_amd64.go new file mode 100644 index 00000000..f4054cb6 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_dragonfly_amd64.go @@ -0,0 +1,17 @@ +//go:build amd64 && dragonfly +//+build amd64,dragonfly + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_dragonfly.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Name *byte + Len uint32 + Pad_cgo_0 [4]byte +} diff --git a/vendor/github.com/creack/pty/ztypes_freebsd_386.go b/vendor/github.com/creack/pty/ztypes_freebsd_386.go new file mode 100644 index 00000000..95a20ab3 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_freebsd_386.go @@ -0,0 +1,16 @@ +//go:build 386 && freebsd +//+build 386,freebsd + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/creack/pty/ztypes_freebsd_amd64.go b/vendor/github.com/creack/pty/ztypes_freebsd_amd64.go new file mode 100644 index 00000000..e03a071c --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_freebsd_amd64.go @@ -0,0 +1,17 @@ +//go:build amd64 && freebsd +//+build amd64,freebsd + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Pad_cgo_0 [4]byte + Buf *byte +} diff --git a/vendor/github.com/creack/pty/ztypes_freebsd_arm.go b/vendor/github.com/creack/pty/ztypes_freebsd_arm.go new file mode 100644 index 00000000..7665bd3c --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_freebsd_arm.go @@ -0,0 +1,16 @@ +//go:build arm && freebsd +//+build arm,freebsd + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/creack/pty/ztypes_freebsd_arm64.go b/vendor/github.com/creack/pty/ztypes_freebsd_arm64.go new file mode 100644 index 00000000..3f95bb8b --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_freebsd_arm64.go @@ -0,0 +1,16 @@ +//go:build arm64 && freebsd +//+build arm64,freebsd + +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs types_freebsd.go + +package pty + +const ( + _C_SPECNAMELEN = 0xff +) + +type fiodgnameArg struct { + Len int32 + Buf *byte +} diff --git a/vendor/github.com/creack/pty/ztypes_loongarchx.go b/vendor/github.com/creack/pty/ztypes_loongarchx.go new file mode 100644 index 00000000..674d2a40 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_loongarchx.go @@ -0,0 +1,13 @@ +//go:build (loongarch32 || loongarch64) && linux +//+build linux +//+build loongarch32 loongarch64 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_mipsx.go b/vendor/github.com/creack/pty/ztypes_mipsx.go new file mode 100644 index 00000000..eddad163 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_mipsx.go @@ -0,0 +1,13 @@ +//go:build (mips || mipsle || mips64 || mips64le) && linux +//+build linux +//+build mips mipsle mips64 mips64le + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_netbsd_32bit_int.go b/vendor/github.com/creack/pty/ztypes_netbsd_32bit_int.go new file mode 100644 index 00000000..5b32e63e --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_netbsd_32bit_int.go @@ -0,0 +1,17 @@ +//go:build (386 || amd64 || arm || arm64) && netbsd +//+build netbsd +//+build 386 amd64 arm arm64 + +package pty + +type ptmget struct { + Cfd int32 + Sfd int32 + Cn [1024]int8 + Sn [1024]int8 +} + +var ( + ioctl_TIOCPTSNAME = 0x48087448 + ioctl_TIOCGRANTPT = 0x20007447 +) diff --git a/vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go b/vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go new file mode 100644 index 00000000..c9aa3161 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_openbsd_32bit_int.go @@ -0,0 +1,14 @@ +//go:build (386 || amd64 || arm || arm64 || mips64) && openbsd +//+build openbsd +//+build 386 amd64 arm arm64 mips64 + +package pty + +type ptmget struct { + Cfd int32 + Sfd int32 + Cn [16]int8 + Sn [16]int8 +} + +var ioctl_PTMGET = 0x40287401 diff --git a/vendor/github.com/creack/pty/ztypes_ppc64.go b/vendor/github.com/creack/pty/ztypes_ppc64.go new file mode 100644 index 00000000..68634439 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_ppc64.go @@ -0,0 +1,12 @@ +//go:build ppc64 +//+build ppc64 + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_ppc64le.go b/vendor/github.com/creack/pty/ztypes_ppc64le.go new file mode 100644 index 00000000..6b5621b1 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_ppc64le.go @@ -0,0 +1,12 @@ +//go:build ppc64le +//+build ppc64le + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_riscvx.go b/vendor/github.com/creack/pty/ztypes_riscvx.go new file mode 100644 index 00000000..1233e75b --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_riscvx.go @@ -0,0 +1,12 @@ +//go:build riscv || riscv64 +//+build riscv riscv64 + +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/creack/pty/ztypes_s390x.go b/vendor/github.com/creack/pty/ztypes_s390x.go new file mode 100644 index 00000000..02facea6 --- /dev/null +++ b/vendor/github.com/creack/pty/ztypes_s390x.go @@ -0,0 +1,12 @@ +//go:build s390x +//+build s390x + +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md index 9d92c11f..f765a46f 100644 --- a/vendor/github.com/google/uuid/README.md +++ b/vendor/github.com/google/uuid/README.md @@ -16,4 +16,4 @@ change is the ability to represent an invalid UUID (vs a NIL UUID). Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: -http://godoc.org/github.com/google/uuid +http://pkg.go.dev/github.com/google/uuid diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go index 7f9e0c6c..14bd3407 100644 --- a/vendor/github.com/google/uuid/marshal.go +++ b/vendor/github.com/google/uuid/marshal.go @@ -16,10 +16,11 @@ func (uuid UUID) MarshalText() ([]byte, error) { // UnmarshalText implements encoding.TextUnmarshaler. func (uuid *UUID) UnmarshalText(data []byte) error { id, err := ParseBytes(data) - if err == nil { - *uuid = id + if err != nil { + return err } - return err + *uuid = id + return nil } // MarshalBinary implements encoding.BinaryMarshaler. diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go index 199a1ac6..46310962 100644 --- a/vendor/github.com/google/uuid/version1.go +++ b/vendor/github.com/google/uuid/version1.go @@ -17,12 +17,6 @@ import ( // // In most cases, New should be used. func NewUUID() (UUID, error) { - nodeMu.Lock() - if nodeID == zeroID { - setNodeInterface("") - } - nodeMu.Unlock() - var uuid UUID now, seq, err := GetTime() if err != nil { @@ -38,7 +32,13 @@ func NewUUID() (UUID, error) { binary.BigEndian.PutUint16(uuid[4:], timeMid) binary.BigEndian.PutUint16(uuid[6:], timeHi) binary.BigEndian.PutUint16(uuid[8:], seq) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() return uuid, nil } diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go index 84af91c9..c110465d 100644 --- a/vendor/github.com/google/uuid/version4.go +++ b/vendor/github.com/google/uuid/version4.go @@ -27,8 +27,13 @@ func New() UUID { // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() (UUID, error) { + return NewRandomFromReader(rander) +} + +// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. +func NewRandomFromReader(r io.Reader) (UUID, error) { var uuid UUID - _, err := io.ReadFull(rander, uuid[:]) + _, err := io.ReadFull(r, uuid[:]) if err != nil { return Nil, err } diff --git a/vendor/github.com/james-barrow/golang-ipc/.gitattributes b/vendor/github.com/james-barrow/golang-ipc/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/vendor/github.com/james-barrow/golang-ipc/LICENSE b/vendor/github.com/james-barrow/golang-ipc/LICENSE new file mode 100644 index 00000000..f2de0792 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 james-barrow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/james-barrow/golang-ipc/README.md b/vendor/github.com/james-barrow/golang-ipc/README.md new file mode 100644 index 00000000..2b54a1e4 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/README.md @@ -0,0 +1,91 @@ +# golang-ipc + Golang Inter-process communication library for Window, Mac and Linux. + + + ### Overview + + A simple to use package that uses unix sockets on Macos/Linux and named pipes on Windows to create a communication channel between two go processes. + + +## Usage + +Create a server with the default configuation and start listening for the client: + +```go + + sc, err := ipc.StartServer("", nil) + if err != nil { + log.Println(err) + return + } + +``` + +Create a client and connect to the server: + +```go + + cc, err := ipc.StartClient("", nil) + if err != nil { + log.Println(err) + return + } + +``` +Read and write data to the connection: + +```go + // write data + _ = sc.Write(1, []byte("Message from server")) + + _ = cc.Write(5, []byte("Message from client")) + + + // Read data + for { + + dataType, data, err := sc.Read() + + if err == nil { + log.Println("Server recieved: "+string(data)+" - Message type: ", dataType) + } else { + log.Println(err) + break + } + } + + + for { + + dataType, data, err := cc.Read() + + if err == nil { + log.Println("Client recieved: "+string(data)+" - Message type: ", dataType) + } else { + log.Println(err) + break + } + } + +``` + + ### Encryption + + By default the connection established will be encypted, ECDH384 is used for the key exchange and AES 256 GCM is used for the cipher. + + Encryption can be swithed off by passing in a custom configuation to the server & client start functions. + +```go + + config := &ipc.ServerConfig{Encryption: false} + sc, err := ipc.StartServer("", config) + +``` + + ### Testing + + The package has been tested on Mac, Windows and Linux and has extensive test coverage. + +### Licence + +MIT \ No newline at end of file diff --git a/vendor/github.com/james-barrow/golang-ipc/client_all.go b/vendor/github.com/james-barrow/golang-ipc/client_all.go new file mode 100644 index 00000000..66313abf --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/client_all.go @@ -0,0 +1,283 @@ +package ipc + +import ( + "bufio" + "errors" + "strings" + "time" +) + +// StartClient - start the ipc client. +// +// ipcName = is the name of the unix socket or named pipe that the client will try and connect to. +// timeout = number of seconds before the socket/pipe times out trying to connect/re-cconnect - if -1 or 0 it never times out. +// retryTimer = number of seconds before the client tries to connect again. +// +func StartClient(ipcName string, config *ClientConfig) (*Client, error) { + + err := checkIpcName(ipcName) + if err != nil { + return nil, err + + } + + cc := &Client{ + Name: ipcName, + status: NotConnected, + recieved: make(chan *Message), + toWrite: make(chan *Message), + } + + if config == nil { + + cc.timeout = 0 + cc.retryTimer = time.Duration(1) + cc.encryptionReq = true + + } else { + + if config.Timeout < 0 { + cc.timeout = 0 + } else { + cc.timeout = config.Timeout + } + + if config.RetryTimer < 1 { + cc.retryTimer = time.Duration(1) + } else { + cc.retryTimer = time.Duration(config.RetryTimer) + } + + if config.Encryption == false { + cc.encryptionReq = false + } else { + cc.encryptionReq = true // defualt is to always enforce encryption + } + } + + go startClient(cc) + + return cc, nil + +} + +func startClient(cc *Client) { + + cc.status = Connecting + cc.recieved <- &Message{Status: cc.status.String(), MsgType: -1} + + err := cc.dial() + if err != nil { + cc.recieved <- &Message{err: err, MsgType: -2} + return + } + + cc.status = Connected + cc.recieved <- &Message{Status: cc.status.String(), MsgType: -1} + + go cc.read() + go cc.write() + +} + +func (cc *Client) read() { + bLen := make([]byte, 4) + + for { + + res := cc.readData(bLen) + if res == false { + break + } + + mLen := bytesToInt(bLen) + + msgRecvd := make([]byte, mLen) + + res = cc.readData(msgRecvd) + if res == false { + break + } + + if cc.encryption == true { + msgFinal, err := decrypt(*cc.enc.cipher, msgRecvd) + if err != nil { + break + } + + if bytesToInt(msgFinal[:4]) == 0 { + // type 0 = control message + } else { + cc.recieved <- &Message{Data: msgFinal[4:], MsgType: bytesToInt(msgFinal[:4])} + } + + } else { + + if bytesToInt(msgRecvd[:4]) == 0 { + // type 0 = control message + } else { + cc.recieved <- &Message{Data: msgRecvd[4:], MsgType: bytesToInt(msgRecvd[:4])} + } + } + } +} + +func (cc *Client) readData(buff []byte) bool { + + _, err := cc.conn.Read(buff) + if err != nil { + if strings.Contains(err.Error(), "EOF") { // the connection has been closed by the client. + cc.conn.Close() + + if cc.status != Closing || cc.status == Closed { + go cc.reconnect() + } + return false + } + + if cc.status == Closing { + cc.status = Closed + cc.recieved <- &Message{Status: cc.status.String(), MsgType: -1} + cc.recieved <- &Message{err: errors.New("Client has closed the connection"), MsgType: -2} + return false + } + + // other read error + return false + + } + + return true + +} + +func (cc *Client) reconnect() { + + cc.status = ReConnecting + cc.recieved <- &Message{Status: cc.status.String(), MsgType: -1} + + err := cc.dial() // connect to the pipe + if err != nil { + if err.Error() == "Timed out trying to connect" { + cc.status = Timeout + cc.recieved <- &Message{Status: cc.status.String(), MsgType: -1} + cc.recieved <- &Message{err: errors.New("Timed out trying to re-connect"), MsgType: -2} + } + + return + } + + cc.status = Connected + cc.recieved <- &Message{Status: cc.status.String(), MsgType: -1} + + go cc.read() + +} + +// Read - blocking function that waits until an non multipart message is recieved +// returns the message type, data and any error. +// +func (cc *Client) Read() (*Message, error) { + + m, ok := (<-cc.recieved) + if ok == false { + return nil, errors.New("the recieve channel has been closed") + } + + if m.err != nil { + close(cc.recieved) + close(cc.toWrite) + return nil, m.err + } + + return m, nil + +} + +// Write - writes a non multipart message to the ipc connection. +// msgType - denotes the type of data being sent. 0 is a reserved type for internal messages and errors. +// +func (cc *Client) Write(msgType int, message []byte) error { + + if msgType == 0 { + return errors.New("Message type 0 is reserved") + } + + if cc.status != Connected { + return errors.New(cc.status.String()) + } + + mlen := len(message) + if mlen > cc.maxMsgSize { + return errors.New("Message exceeds maximum message length") + } + + cc.toWrite <- &Message{MsgType: msgType, Data: message} + + return nil + +} + +func (cc *Client) write() { + + for { + + m, ok := <-cc.toWrite + + if ok == false { + break + } + + toSend := intToBytes(m.MsgType) + + writer := bufio.NewWriter(cc.conn) + + if cc.encryption == true { + toSend = append(toSend, m.Data...) + toSendEnc, err := encrypt(*cc.enc.cipher, toSend) + if err != nil { + //return err + } + toSend = toSendEnc + } else { + + toSend = append(toSend, m.Data...) + + } + + writer.Write(intToBytes(len(toSend))) + writer.Write(toSend) + + err := writer.Flush() + if err != nil { + //return err + } + + } +} + +// getStatus - get the current status of the connection +func (cc *Client) getStatus() Status { + + return cc.status + +} + +// StatusCode - returns the current connection status +func (cc *Client) StatusCode() Status { + return cc.status +} + +// Status - returns the current connection status as a string +func (cc *Client) Status() string { + + return cc.status.String() + +} + +// Close - closes the connection +func (cc *Client) Close() { + + cc.status = Closing + cc.conn.Close() +} diff --git a/vendor/github.com/james-barrow/golang-ipc/connect_other.go b/vendor/github.com/james-barrow/golang-ipc/connect_other.go new file mode 100644 index 00000000..187273c5 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/connect_other.go @@ -0,0 +1,88 @@ +// +build linux darwin + +package ipc + +import ( + "errors" + "net" + "os" + "strings" + "time" +) + +// Server create a unix socket and start listening connections - for unix and linux +func (sc *Server) run() error { + + base := "/tmp/" + sock := ".sock" + + if err := os.RemoveAll(base + sc.name + sock); err != nil { + return err + } + + listen, err := net.Listen("unix", base+sc.name+sock) + if err != nil { + return err + } + + sc.listen = listen + + sc.status = Listening + sc.recieved <- &Message{Status: sc.status.String(), MsgType: -1} + sc.connChannel = make(chan bool) + + go sc.acceptLoop() + + err = sc.connectionTimer() + if err != nil { + return err + } + + return nil + +} + +// Client connect to the unix socket created by the server - for unix and linux +func (cc *Client) dial() error { + + base := "/tmp/" + sock := ".sock" + + startTime := time.Now() + + for { + if cc.timeout != 0 { + if time.Now().Sub(startTime).Seconds() > cc.timeout { + cc.status = Closed + return errors.New("Timed out trying to connect") + } + } + + conn, err := net.Dial("unix", base+cc.Name+sock) + if err != nil { + + if strings.Contains(err.Error(), "connect: no such file or directory") == true { + + } else if strings.Contains(err.Error(), "connect: connection refused") == true { + + } else { + cc.recieved <- &Message{err: err, MsgType: -2} + } + + } else { + + cc.conn = conn + + err = cc.handshake() + if err != nil { + return err + } + + return nil + } + + time.Sleep(cc.retryTimer * time.Second) + + } + +} diff --git a/vendor/github.com/james-barrow/golang-ipc/connect_windows.go b/vendor/github.com/james-barrow/golang-ipc/connect_windows.go new file mode 100644 index 00000000..41c7e488 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/connect_windows.go @@ -0,0 +1,79 @@ +package ipc + +import ( + "errors" + "strings" + "time" + + "github.com/Microsoft/go-winio" +) + +// Server function +// Create the named pipe (if it doesn't already exist) and start listening for a client to connect. +// when a client connects and connection is accepted the read function is called on a go routine. +func (sc *Server) run() error { + + var pipeBase = `\\.\pipe\` + + listen, err := winio.ListenPipe(pipeBase+sc.name, nil) + if err != nil { + + return err + } + + sc.listen = listen + + sc.status = Listening + + sc.connChannel = make(chan bool) + + go sc.acceptLoop() + + err2 := sc.connectionTimer() + if err2 != nil { + return err2 + } + + return nil + +} + +// Client function +// dial - attempts to connect to a named pipe created by the server +func (cc *Client) dial() error { + + var pipeBase = `\\.\pipe\` + + startTime := time.Now() + + for { + if cc.timeout != 0 { + if time.Now().Sub(startTime).Seconds() > cc.timeout { + cc.status = Closed + return errors.New("Timed out trying to connect") + } + } + pn, err := winio.DialPipe(pipeBase+cc.Name, nil) + if err != nil { + + if strings.Contains(err.Error(), "The system cannot find the file specified.") == true { + + } else { + return err + } + + } else { + + cc.conn = pn + + err = cc.handshake() + if err != nil { + return err + } + return nil + } + + time.Sleep(cc.retryTimer * time.Second) + + } +} diff --git a/vendor/github.com/james-barrow/golang-ipc/encryption.go b/vendor/github.com/james-barrow/golang-ipc/encryption.go new file mode 100644 index 00000000..004a04a7 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/encryption.go @@ -0,0 +1,188 @@ +package ipc + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "errors" + "io" + "net" +) + +func (sc *Server) keyExchange() ([32]byte, error) { + + var shared [32]byte + + priv, pub, err := generateKeys() + if err != nil { + return shared, err + } + + // send servers public key + err = sendPublic(sc.conn, pub) + if err != nil { + return shared, err + } + + // recieve clients public key + pubRecvd, err := recvPublic(sc.conn) + if err != nil { + return shared, err + } + + b, _ := pubRecvd.Curve.ScalarMult(pubRecvd.X, pubRecvd.Y, priv.D.Bytes()) + + shared = sha256.Sum256(b.Bytes()) + + return shared, nil + +} + +func (cc *Client) keyExchange() ([32]byte, error) { + + var shared [32]byte + + priv, pub, err := generateKeys() + if err != nil { + return shared, err + } + + // recieve servers public key + pubRecvd, err := recvPublic(cc.conn) + if err != nil { + return shared, err + } + + // send clients public key + err = sendPublic(cc.conn, pub) + if err != nil { + return shared, err + } + + b, _ := pubRecvd.Curve.ScalarMult(pubRecvd.X, pubRecvd.Y, priv.D.Bytes()) + + shared = sha256.Sum256(b.Bytes()) + + return shared, nil +} + +func generateKeys() (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) { + + priva, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, nil, err + } + + puba := &priva.PublicKey + + if priva.IsOnCurve(puba.X, puba.Y) == false { + return nil, nil, errors.New("keys created arn't on curve") + } + + return priva, puba, err + +} + +func sendPublic(conn net.Conn, pub *ecdsa.PublicKey) error { + + pubSend := publicKeyToBytes(pub) + if pubSend == nil { + return errors.New("public key cannot be converted to bytes") + } + + _, err := conn.Write(pubSend) + if err != nil { + return errors.New("could not sent public key") + } + + return nil +} + +func recvPublic(conn net.Conn) (*ecdsa.PublicKey, error) { + + buff := make([]byte, 300) + i, err := conn.Read(buff) + if err != nil { + return nil, errors.New("didn't recieve public key") + } + + if i != 97 { + return nil, errors.New("public key recieved isn't valid length") + } + + recvdPub := bytesToPublicKey(buff[:i]) + + if recvdPub.IsOnCurve(recvdPub.X, recvdPub.Y) == false { + return nil, errors.New("didn't recieve valid public key") + } + + return recvdPub, nil +} + +func publicKeyToBytes(pub *ecdsa.PublicKey) []byte { + + if pub == nil || pub.X == nil || pub.Y == nil { + return nil + } + + return elliptic.Marshal(elliptic.P384(), pub.X, pub.Y) +} + +func bytesToPublicKey(recvdPub []byte) *ecdsa.PublicKey { + + if len(recvdPub) == 0 { + return nil + } + + x, y := elliptic.Unmarshal(elliptic.P384(), recvdPub) + return &ecdsa.PublicKey{Curve: elliptic.P384(), X: x, Y: y} + +} + +func createCipher(shared [32]byte) (*cipher.AEAD, error) { + + b, err := aes.NewCipher(shared[:]) + + if err != nil { + return nil, err + } + + gcm, err := cipher.NewGCM(b) + if err != nil { + return nil, err + } + + return &gcm, nil +} + +func encrypt(g cipher.AEAD, data []byte) ([]byte, error) { + + nonce := make([]byte, g.NonceSize()) + + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return nil, err + } + + return g.Seal(nonce, nonce, data, nil), nil + +} + +func decrypt(g cipher.AEAD, recdData []byte) ([]byte, error) { + + nonceSize := g.NonceSize() + if len(recdData) < nonceSize { + return nil, errors.New("not enough data to decrypt") + } + + nonce, recdData := recdData[:nonceSize], recdData[nonceSize:] + plain, err := g.Open(nil, nonce, recdData, nil) + if err != nil { + return nil, err + } + + return plain, nil + +} diff --git a/vendor/github.com/james-barrow/golang-ipc/go.mod b/vendor/github.com/james-barrow/golang-ipc/go.mod new file mode 100644 index 00000000..c9465da5 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/go.mod @@ -0,0 +1,5 @@ +module github.com/james-barrow/golang-ipc + +go 1.15 + +require github.com/Microsoft/go-winio v0.4.16 diff --git a/vendor/github.com/james-barrow/golang-ipc/go.sum b/vendor/github.com/james-barrow/golang-ipc/go.sum new file mode 100644 index 00000000..284f8a41 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/go.sum @@ -0,0 +1,12 @@ +github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/james-barrow/golang-ipc/handshake.go b/vendor/github.com/james-barrow/golang-ipc/handshake.go new file mode 100644 index 00000000..15112d48 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/handshake.go @@ -0,0 +1,255 @@ +package ipc + +import ( + "bytes" + "encoding/binary" + "errors" +) + +// 1st message sent from the server +// byte 0 = protocal version no. +// byte 1 = whether encryption is to be used - 0 no , 1 = encryption +func (sc *Server) handshake() error { + + err := sc.one() + if err != nil { + return err + } + + if sc.encryption == true { + err = sc.startEncryption() + if err != nil { + return err + } + } + + err = sc.msgLength() + if err != nil { + return err + } + + return nil + +} + +func (sc *Server) one() error { + + buff := make([]byte, 2) + + buff[0] = byte(version) + + if sc.encryption == true { + buff[1] = byte(1) + } else { + buff[1] = byte(0) + } + + _, err := sc.conn.Write(buff) + if err != nil { + return errors.New("unable to send handshake ") + } + + recv := make([]byte, 1) + _, err = sc.conn.Read(recv) + if err != nil { + return errors.New("failed to recieve handshake reply") + } + + switch result := recv[0]; result { + case 0: + return nil + case 1: + return errors.New("client has a different version number") + case 2: + return errors.New("client is enforcing encryption") + case 3: + return errors.New("server failed to get handshake reply") + + } + + return errors.New("other error - handshake failed") + +} + +func (sc *Server) startEncryption() error { + + shared, err := sc.keyExchange() + if err != nil { + return err + } + + gcm, err := createCipher(shared) + if err != nil { + return err + } + + sc.enc = &encryption{ + keyExchange: "ecdsa", + encryption: "AES-GCM-256", + cipher: gcm, + } + + return nil + +} + +func (sc *Server) msgLength() error { + + toSend := make([]byte, 4) + + buff := make([]byte, 4) + binary.BigEndian.PutUint32(buff, uint32(sc.maxMsgSize)) + + if sc.encryption == true { + maxMsg, err := encrypt(*sc.enc.cipher, buff) + if err != nil { + return err + } + + binary.BigEndian.PutUint32(toSend, uint32(len(maxMsg))) + toSend = append(toSend, maxMsg...) + + } else { + + binary.BigEndian.PutUint32(toSend, uint32(len(buff))) + toSend = append(toSend, buff...) + } + + _, err := sc.conn.Write(toSend) + if err != nil { + return errors.New("unable to send max message length ") + } + + reply := make([]byte, 1) + + _, err = sc.conn.Read(reply) + if err != nil { + return errors.New("did not recieve message length reply") + } + + return nil + +} + +// 1st message recieved by the client +func (cc *Client) handshake() error { + + err := cc.one() + if err != nil { + return err + } + + if cc.encryption == true { + err := cc.startEncryption() + if err != nil { + return err + } + } + + err = cc.msgLength() + if err != nil { + return err + } + + return nil + +} + +func (cc *Client) one() error { + + recv := make([]byte, 2) + _, err := cc.conn.Read(recv) + if err != nil { + return errors.New("failed to recieve handshake message") + } + + if recv[0] != version { + cc.handshakeSendReply(1) + return errors.New("server has sent a different version number") + } + + if recv[1] != 1 && cc.encryptionReq == true { + cc.handshakeSendReply(2) + return errors.New("server tried to connect without encryption") + } + + if recv[1] == 0 { + cc.encryption = false + } else { + cc.encryption = true + } + + cc.handshakeSendReply(0) // 0 is ok + return nil + +} + +func (cc *Client) startEncryption() error { + + shared, err := cc.keyExchange() + + if err != nil { + return err + } + + gcm, err := createCipher(shared) + if err != nil { + return err + } + + cc.enc = &encryption{ + keyExchange: "ECDSA", + encryption: "AES-GCM-256", + cipher: gcm, + } + + return nil +} + +func (cc *Client) msgLength() error { + + buff := make([]byte, 4) + + _, err := cc.conn.Read(buff) + if err != nil { + return errors.New("failed to recieve max message length 1") + } + + var msgLen uint32 + binary.Read(bytes.NewReader(buff), binary.BigEndian, &msgLen) // message length + + buff = make([]byte, int(msgLen)) + + _, err = cc.conn.Read(buff) + if err != nil { + return errors.New("failed to recieve max message length 2") + } + var buff2 []byte + if cc.encryption == true { + buff2, err = decrypt(*cc.enc.cipher, buff) + if err != nil { + return errors.New("failed to recieve max message length 3") + } + + } else { + buff2 = buff + } + + var maxMsgSize uint32 + binary.Read(bytes.NewReader(buff2), binary.BigEndian, &maxMsgSize) // message length + + cc.maxMsgSize = int(maxMsgSize) + cc.handshakeSendReply(0) + + return nil + +} + +func (cc *Client) handshakeSendReply(result byte) { + + buff := make([]byte, 1) + buff[0] = result + + cc.conn.Write(buff) + +} diff --git a/vendor/github.com/james-barrow/golang-ipc/headers.go b/vendor/github.com/james-barrow/golang-ipc/headers.go new file mode 100644 index 00000000..c048f38c --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/headers.go @@ -0,0 +1,25 @@ +package ipc + +import ( + "bytes" + "encoding/binary" +) + +func intToBytes(mLen int) []byte { + + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, uint32(mLen)) + + return b + +} + +func bytesToInt(b []byte) int { + + var mlen uint32 + + binary.Read(bytes.NewReader(b[:]), binary.BigEndian, &mlen) // message length + + return int(mlen) + +} diff --git a/vendor/github.com/james-barrow/golang-ipc/server_all.go b/vendor/github.com/james-barrow/golang-ipc/server_all.go new file mode 100644 index 00000000..19f964e5 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/server_all.go @@ -0,0 +1,325 @@ +package ipc + +import ( + "bufio" + "errors" + "time" +) + +// StartServer - starts the ipc server. +// +// ipcName = is the name of the unix socket or named pipe that will be created. +// timeout = number of seconds before the socket/pipe times out waiting for a connection/re-cconnection - if -1 or 0 it never times out. +// +func StartServer(ipcName string, config *ServerConfig) (*Server, error) { + + err := checkIpcName(ipcName) + if err != nil { + return nil, err + } + + sc := &Server{ + name: ipcName, + status: NotConnected, + recieved: make(chan *Message), + toWrite: make(chan *Message), + } + + if config == nil { + sc.timeout = 0 + sc.maxMsgSize = maxMsgSize + sc.encryption = true + + } else { + + if config.Timeout < 0 { + sc.timeout = 0 + } else { + sc.timeout = config.Timeout + } + + if config.MaxMsgSize < 1024 { + sc.maxMsgSize = maxMsgSize + } else { + sc.maxMsgSize = config.MaxMsgSize + } + + if config.Encryption == false { + sc.encryption = false + } else { + sc.encryption = true + } + + } + + go startServer(sc) + + return sc, err +} + +func startServer(sc *Server) { + + err := sc.run() + if err != nil { + sc.recieved <- &Message{err: err, MsgType: -2} + } +} + +func (sc *Server) acceptLoop() { + for { + conn, err := sc.listen.Accept() + if err != nil { + break + } + + if sc.status == Listening || sc.status == ReConnecting { + + sc.conn = conn + + err2 := sc.handshake() + if err2 != nil { + sc.recieved <- &Message{err: err2, MsgType: -2} + sc.status = Error + sc.listen.Close() + sc.conn.Close() + + } else { + go sc.read() + go sc.write() + + sc.status = Connected + sc.recieved <- &Message{Status: sc.status.String(), MsgType: -1} + sc.connChannel <- true + } + + } + + } + +} + +func (sc *Server) connectionTimer() error { + + if sc.timeout != 0 { + + timeout := make(chan bool) + + go func() { + time.Sleep(sc.timeout * time.Second) + timeout <- true + }() + + select { + + case <-sc.connChannel: + return nil + case <-timeout: + sc.listen.Close() + return errors.New("Timed out waiting for client to connect") + } + } + + select { + + case <-sc.connChannel: + return nil + } + +} + +func (sc *Server) read() { + + bLen := make([]byte, 4) + + for { + + res := sc.readData(bLen) + if res == false { + break + } + + mLen := bytesToInt(bLen) + + msgRecvd := make([]byte, mLen) + + res = sc.readData(msgRecvd) + if res == false { + break + } + + if sc.encryption == true { + msgFinal, err := decrypt(*sc.enc.cipher, msgRecvd) + if err != nil { + sc.recieved <- &Message{err: err, MsgType: -2} + continue + } + + if bytesToInt(msgFinal[:4]) == 0 { + // type 0 = control message + } else { + sc.recieved <- &Message{Data: msgFinal[4:], MsgType: bytesToInt(msgFinal[:4])} + } + + } else { + if bytesToInt(msgRecvd[:4]) == 0 { + // type 0 = control message + } else { + sc.recieved <- &Message{Data: msgRecvd[4:], MsgType: bytesToInt(msgRecvd[:4])} + } + } + + } +} + +func (sc *Server) readData(buff []byte) bool { + + _, err := sc.conn.Read(buff) + if err != nil { + + if sc.status == Closing { + + sc.status = Closed + sc.recieved <- &Message{Status: sc.status.String(), MsgType: -1} + sc.recieved <- &Message{err: errors.New("Server has closed the connection"), MsgType: -2} + return false + } + + go sc.reConnect() + return false + + } + + return true + +} + +func (sc *Server) reConnect() { + + sc.status = ReConnecting + sc.recieved <- &Message{Status: sc.status.String(), MsgType: -1} + + err := sc.connectionTimer() + if err != nil { + sc.status = Timeout + sc.recieved <- &Message{Status: sc.status.String(), MsgType: -1} + + sc.recieved <- &Message{err: err, MsgType: -2} + + } + +} + +// Read - blocking function that waits until an non multipart message is recieved + +func (sc *Server) Read() (*Message, error) { + + m, ok := (<-sc.recieved) + if ok == false { + return nil, errors.New("the recieve channel has been closed") + } + + if m.err != nil { + close(sc.recieved) + close(sc.toWrite) + return nil, m.err + } + + return m, nil + +} + +// Write - writes a non multipart message to the ipc connection. +// msgType - denotes the type of data being sent. 0 is a reserved type for internal messages and errors. +// +func (sc *Server) Write(msgType int, message []byte) error { + + if msgType == 0 { + return errors.New("Message type 0 is reserved") + } + + mlen := len(message) + + if mlen > sc.maxMsgSize { + return errors.New("Message exceeds maximum message length") + } + + if sc.status == Connected { + + sc.toWrite <- &Message{MsgType: msgType, Data: message} + + } else { + return errors.New(sc.status.String()) + } + + return nil + +} + +func (sc *Server) write() { + + for { + + m, ok := <-sc.toWrite + + if ok == false { + break + } + + toSend := intToBytes(m.MsgType) + + writer := bufio.NewWriter(sc.conn) + + if sc.encryption == true { + toSend = append(toSend, m.Data...) + toSendEnc, err := encrypt(*sc.enc.cipher, toSend) + if err != nil { + //return err + } + toSend = toSendEnc + } else { + + toSend = append(toSend, m.Data...) + + } + + writer.Write(intToBytes(len(toSend))) + writer.Write(toSend) + + err := writer.Flush() + if err != nil { + //return err + } + + time.Sleep(2 * time.Millisecond) + + } + +} + +// getStatus - get the current status of the connection +func (sc *Server) getStatus() Status { + + return sc.status + +} + +// StatusCode - returns the current connection status +func (sc *Server) StatusCode() Status { + return sc.status +} + +// Status - returns the current connection status as a string +func (sc *Server) Status() string { + + return sc.status.String() + +} + +// Close - closes the connection +func (sc *Server) Close() { + + sc.status = Closing + sc.listen.Close() + sc.conn.Close() + +} diff --git a/vendor/github.com/james-barrow/golang-ipc/shared.go b/vendor/github.com/james-barrow/golang-ipc/shared.go new file mode 100644 index 00000000..f9103302 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/shared.go @@ -0,0 +1,41 @@ +package ipc + +import "errors" + +// returns the status of the connection as a string +func (status *Status) String() string { + + switch *status { + case NotConnected: + return "Not Connected" + case Connecting: + return "Connecting" + case Connected: + return "Connected" + case Listening: + return "Listening" + case Closing: + return "Closing" + case ReConnecting: + return "Re-connecting" + case Timeout: + return "Timeout" + case Closed: + return "Closed" + case Error: + return "Error" + default: + return "Status not found" + } +} + +// checks the name passed into the start function to ensure it's ok/will work. +func checkIpcName(ipcName string) error { + + if len(ipcName) == 0 { + return errors.New("ipcName cannot be an empty string") + } + + return nil + +} diff --git a/vendor/github.com/james-barrow/golang-ipc/types.go b/vendor/github.com/james-barrow/golang-ipc/types.go new file mode 100644 index 00000000..c0797710 --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/types.go @@ -0,0 +1,91 @@ +package ipc + +import ( + "crypto/cipher" + "net" + "time" +) + +// Server - holds the details of the server connection & config. +type Server struct { + name string + listen net.Listener + conn net.Conn + status Status + recieved chan (*Message) + connChannel chan bool + toWrite chan (*Message) + timeout time.Duration + encryption bool + maxMsgSize int + enc *encryption +} + +// Client - holds the details of the client connection and config. +type Client struct { + Name string + conn net.Conn + status Status + timeout float64 // + retryTimer time.Duration // number of seconds before trying to connect again + recieved chan (*Message) + toWrite chan (*Message) + encryption bool + encryptionReq bool + maxMsgSize int + enc *encryption +} + +// Message - contains the recieved message +type Message struct { + err error // details of any error + MsgType int // type of message sent - 0 is reserved + Data []byte // message data recieved + Status string +} + +// Status - Status of the connection +type Status int + +const ( + + // NotConnected - 0 + NotConnected Status = iota + // Listening - 1 + Listening Status = iota + // Connecting - 2 + Connecting Status = iota + // Connected - 3 + Connected Status = iota + // ReConnecting - 4 + ReConnecting Status = iota + // Closed - 5 + Closed Status = iota + // Closing - 6 + Closing Status = iota + // Error - 7 + Error Status = iota + // Timeout - 8 + Timeout Status = iota +) + +// ServerConfig - used to pass configuation overrides to ServerStart() +type ServerConfig struct { + Timeout time.Duration + MaxMsgSize int + Encryption bool +} + +// ClientConfig - used to pass configuation overrides to ClientStart() +type ClientConfig struct { + Timeout float64 + RetryTimer time.Duration + Encryption bool +} + +// Encryption - encryption settings +type encryption struct { + keyExchange string + encryption string + cipher *cipher.AEAD +} diff --git a/vendor/github.com/james-barrow/golang-ipc/vars.go b/vendor/github.com/james-barrow/golang-ipc/vars.go new file mode 100644 index 00000000..3773d93b --- /dev/null +++ b/vendor/github.com/james-barrow/golang-ipc/vars.go @@ -0,0 +1,5 @@ +package ipc + +const version = 2 // ipc package version + +const maxMsgSize = 3145728 // 3Mb - Maximum bytes allowed for each message diff --git a/vendor/github.com/json-iterator/go/README.md b/vendor/github.com/json-iterator/go/README.md index 52b111d5..c589addf 100644 --- a/vendor/github.com/json-iterator/go/README.md +++ b/vendor/github.com/json-iterator/go/README.md @@ -8,8 +8,6 @@ A high-performance 100% compatible drop-in replacement of "encoding/json" -You can also use thrift like JSON using [thrift-iterator](https://github.com/thrift-iterator/go) - # Benchmark ![benchmark](http://jsoniter.com/benchmarks/go-benchmark.png) diff --git a/vendor/github.com/json-iterator/go/go.mod b/vendor/github.com/json-iterator/go/go.mod index e05c42ff..e817cccb 100644 --- a/vendor/github.com/json-iterator/go/go.mod +++ b/vendor/github.com/json-iterator/go/go.mod @@ -6,6 +6,6 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/google/gofuzz v1.0.0 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 - github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 + github.com/modern-go/reflect2 v1.0.2 github.com/stretchr/testify v1.3.0 ) diff --git a/vendor/github.com/json-iterator/go/go.sum b/vendor/github.com/json-iterator/go/go.sum index be00a6df..4b7bb8a2 100644 --- a/vendor/github.com/json-iterator/go/go.sum +++ b/vendor/github.com/json-iterator/go/go.sum @@ -5,11 +5,10 @@ github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/klauspost/compress/LICENSE new file mode 100644 index 00000000..1eb75ef6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2019 Klaus Post. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/klauspost/compress/flate/deflate.go b/vendor/github.com/klauspost/compress/flate/deflate.go new file mode 100644 index 00000000..25dbe3e1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/deflate.go @@ -0,0 +1,821 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Copyright (c) 2015 Klaus Post +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "fmt" + "io" + "math" +) + +const ( + NoCompression = 0 + BestSpeed = 1 + BestCompression = 9 + DefaultCompression = -1 + + // HuffmanOnly disables Lempel-Ziv match searching and only performs Huffman + // entropy encoding. This mode is useful in compressing data that has + // already been compressed with an LZ style algorithm (e.g. Snappy or LZ4) + // that lacks an entropy encoder. Compression gains are achieved when + // certain bytes in the input stream occur more frequently than others. + // + // Note that HuffmanOnly produces a compressed output that is + // RFC 1951 compliant. That is, any valid DEFLATE decompressor will + // continue to be able to decompress this output. + HuffmanOnly = -2 + ConstantCompression = HuffmanOnly // compatibility alias. + + logWindowSize = 15 + windowSize = 1 << logWindowSize + windowMask = windowSize - 1 + logMaxOffsetSize = 15 // Standard DEFLATE + minMatchLength = 4 // The smallest match that the compressor looks for + maxMatchLength = 258 // The longest match for the compressor + minOffsetSize = 1 // The shortest offset that makes any sense + + // The maximum number of tokens we put into a single flat block, just too + // stop things from getting too large. + maxFlateBlockTokens = 1 << 14 + maxStoreBlockSize = 65535 + hashBits = 17 // After 17 performance degrades + hashSize = 1 << hashBits + hashMask = (1 << hashBits) - 1 + hashShift = (hashBits + minMatchLength - 1) / minMatchLength + maxHashOffset = 1 << 24 + + skipNever = math.MaxInt32 + + debugDeflate = false +) + +type compressionLevel struct { + good, lazy, nice, chain, fastSkipHashing, level int +} + +// Compression levels have been rebalanced from zlib deflate defaults +// to give a bigger spread in speed and compression. +// See https://blog.klauspost.com/rebalancing-deflate-compression-levels/ +var levels = []compressionLevel{ + {}, // 0 + // Level 1-6 uses specialized algorithm - values not used + {0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 2}, + {0, 0, 0, 0, 0, 3}, + {0, 0, 0, 0, 0, 4}, + {0, 0, 0, 0, 0, 5}, + {0, 0, 0, 0, 0, 6}, + // Levels 7-9 use increasingly more lazy matching + // and increasingly stringent conditions for "good enough". + {8, 8, 24, 16, skipNever, 7}, + {10, 16, 24, 64, skipNever, 8}, + {32, 258, 258, 4096, skipNever, 9}, +} + +// advancedState contains state for the advanced levels, with bigger hash tables, etc. +type advancedState struct { + // deflate state + length int + offset int + maxInsertIndex int + + // Input hash chains + // hashHead[hashValue] contains the largest inputIndex with the specified hash value + // If hashHead[hashValue] is within the current window, then + // hashPrev[hashHead[hashValue] & windowMask] contains the previous index + // with the same hash value. + chainHead int + hashHead [hashSize]uint32 + hashPrev [windowSize]uint32 + hashOffset int + + // input window: unprocessed data is window[index:windowEnd] + index int + hashMatch [maxMatchLength + minMatchLength]uint32 + + hash uint32 + ii uint16 // position of last match, intended to overflow to reset. +} + +type compressor struct { + compressionLevel + + w *huffmanBitWriter + + // compression algorithm + fill func(*compressor, []byte) int // copy data to window + step func(*compressor) // process window + + window []byte + windowEnd int + blockStart int // window index where current tokens start + err error + + // queued output tokens + tokens tokens + fast fastEnc + state *advancedState + + sync bool // requesting flush + byteAvailable bool // if true, still need to process window[index-1]. +} + +func (d *compressor) fillDeflate(b []byte) int { + s := d.state + if s.index >= 2*windowSize-(minMatchLength+maxMatchLength) { + // shift the window by windowSize + copy(d.window[:], d.window[windowSize:2*windowSize]) + s.index -= windowSize + d.windowEnd -= windowSize + if d.blockStart >= windowSize { + d.blockStart -= windowSize + } else { + d.blockStart = math.MaxInt32 + } + s.hashOffset += windowSize + if s.hashOffset > maxHashOffset { + delta := s.hashOffset - 1 + s.hashOffset -= delta + s.chainHead -= delta + // Iterate over slices instead of arrays to avoid copying + // the entire table onto the stack (Issue #18625). + for i, v := range s.hashPrev[:] { + if int(v) > delta { + s.hashPrev[i] = uint32(int(v) - delta) + } else { + s.hashPrev[i] = 0 + } + } + for i, v := range s.hashHead[:] { + if int(v) > delta { + s.hashHead[i] = uint32(int(v) - delta) + } else { + s.hashHead[i] = 0 + } + } + } + } + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +func (d *compressor) writeBlock(tok *tokens, index int, eof bool) error { + if index > 0 || eof { + var window []byte + if d.blockStart <= index { + window = d.window[d.blockStart:index] + } + d.blockStart = index + d.w.writeBlock(tok, eof, window) + return d.w.err + } + return nil +} + +// writeBlockSkip writes the current block and uses the number of tokens +// to determine if the block should be stored on no matches, or +// only huffman encoded. +func (d *compressor) writeBlockSkip(tok *tokens, index int, eof bool) error { + if index > 0 || eof { + if d.blockStart <= index { + window := d.window[d.blockStart:index] + // If we removed less than a 64th of all literals + // we huffman compress the block. + if int(tok.n) > len(window)-int(tok.n>>6) { + d.w.writeBlockHuff(eof, window, d.sync) + } else { + // Write a dynamic huffman block. + d.w.writeBlockDynamic(tok, eof, window, d.sync) + } + } else { + d.w.writeBlock(tok, eof, nil) + } + d.blockStart = index + return d.w.err + } + return nil +} + +// fillWindow will fill the current window with the supplied +// dictionary and calculate all hashes. +// This is much faster than doing a full encode. +// Should only be used after a start/reset. +func (d *compressor) fillWindow(b []byte) { + // Do not fill window if we are in store-only or huffman mode. + if d.level <= 0 { + return + } + if d.fast != nil { + // encode the last data, but discard the result + if len(b) > maxMatchOffset { + b = b[len(b)-maxMatchOffset:] + } + d.fast.Encode(&d.tokens, b) + d.tokens.Reset() + return + } + s := d.state + // If we are given too much, cut it. + if len(b) > windowSize { + b = b[len(b)-windowSize:] + } + // Add all to window. + n := copy(d.window[d.windowEnd:], b) + + // Calculate 256 hashes at the time (more L1 cache hits) + loops := (n + 256 - minMatchLength) / 256 + for j := 0; j < loops; j++ { + startindex := j * 256 + end := startindex + 256 + minMatchLength - 1 + if end > n { + end = n + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + + if dstSize <= 0 { + continue + } + + dst := s.hashMatch[:dstSize] + bulkHash4(tocheck, dst) + var newH uint32 + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + s.hashPrev[di&windowMask] = s.hashHead[newH] + // Set the head of the hash chain to us. + s.hashHead[newH] = uint32(di + s.hashOffset) + } + s.hash = newH + } + // Update window information. + d.windowEnd += n + s.index = n +} + +// Try to find a match starting at index whose length is greater than prevSize. +// We only look at chainCount possibilities before giving up. +// pos = s.index, prevHead = s.chainHead-s.hashOffset, prevLength=minMatchLength-1, lookahead +func (d *compressor) findMatch(pos int, prevHead int, prevLength int, lookahead int) (length, offset int, ok bool) { + minMatchLook := maxMatchLength + if lookahead < minMatchLook { + minMatchLook = lookahead + } + + win := d.window[0 : pos+minMatchLook] + + // We quit when we get a match that's at least nice long + nice := len(win) - pos + if d.nice < nice { + nice = d.nice + } + + // If we've got a match that's good enough, only look in 1/4 the chain. + tries := d.chain + length = prevLength + if length >= d.good { + tries >>= 2 + } + + wEnd := win[pos+length] + wPos := win[pos:] + minIndex := pos - windowSize + + for i := prevHead; tries > 0; tries-- { + if wEnd == win[i+length] { + n := matchLen(win[i:i+minMatchLook], wPos) + + if n > length && (n > minMatchLength || pos-i <= 4096) { + length = n + offset = pos - i + ok = true + if n >= nice { + // The match is good enough that we don't try to find a better one. + break + } + wEnd = win[pos+n] + } + } + if i == minIndex { + // hashPrev[i & windowMask] has already been overwritten, so stop now. + break + } + i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset + if i < minIndex || i < 0 { + break + } + } + return +} + +func (d *compressor) writeStoredBlock(buf []byte) error { + if d.w.writeStoredHeader(len(buf), false); d.w.err != nil { + return d.w.err + } + d.w.writeBytes(buf) + return d.w.err +} + +// hash4 returns a hash representation of the first 4 bytes +// of the supplied slice. +// The caller must ensure that len(b) >= 4. +func hash4(b []byte) uint32 { + b = b[:4] + return hash4u(uint32(b[3])|uint32(b[2])<<8|uint32(b[1])<<16|uint32(b[0])<<24, hashBits) +} + +// bulkHash4 will compute hashes using the same +// algorithm as hash4 +func bulkHash4(b []byte, dst []uint32) { + if len(b) < 4 { + return + } + hb := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 + dst[0] = hash4u(hb, hashBits) + end := len(b) - 4 + 1 + for i := 1; i < end; i++ { + hb = (hb << 8) | uint32(b[i+3]) + dst[i] = hash4u(hb, hashBits) + } +} + +func (d *compressor) initDeflate() { + d.window = make([]byte, 2*windowSize) + d.byteAvailable = false + d.err = nil + if d.state == nil { + return + } + s := d.state + s.index = 0 + s.hashOffset = 1 + s.length = minMatchLength - 1 + s.offset = 0 + s.hash = 0 + s.chainHead = -1 +} + +// deflateLazy is the same as deflate, but with d.fastSkipHashing == skipNever, +// meaning it always has lazy matching on. +func (d *compressor) deflateLazy() { + s := d.state + // Sanity enables additional runtime tests. + // It's intended to be used during development + // to supplement the currently ad-hoc unit tests. + const sanity = debugDeflate + + if d.windowEnd-s.index < minMatchLength+maxMatchLength && !d.sync { + return + } + + s.maxInsertIndex = d.windowEnd - (minMatchLength - 1) + if s.index < s.maxInsertIndex { + s.hash = hash4(d.window[s.index : s.index+minMatchLength]) + } + + for { + if sanity && s.index > d.windowEnd { + panic("index > windowEnd") + } + lookahead := d.windowEnd - s.index + if lookahead < minMatchLength+maxMatchLength { + if !d.sync { + return + } + if sanity && s.index > d.windowEnd { + panic("index > windowEnd") + } + if lookahead == 0 { + // Flush current output block if any. + if d.byteAvailable { + // There is still one pending token that needs to be flushed + d.tokens.AddLiteral(d.window[s.index-1]) + d.byteAvailable = false + } + if d.tokens.n > 0 { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + return + } + } + if s.index < s.maxInsertIndex { + // Update the hash + s.hash = hash4(d.window[s.index : s.index+minMatchLength]) + ch := s.hashHead[s.hash&hashMask] + s.chainHead = int(ch) + s.hashPrev[s.index&windowMask] = ch + s.hashHead[s.hash&hashMask] = uint32(s.index + s.hashOffset) + } + prevLength := s.length + prevOffset := s.offset + s.length = minMatchLength - 1 + s.offset = 0 + minIndex := s.index - windowSize + if minIndex < 0 { + minIndex = 0 + } + + if s.chainHead-s.hashOffset >= minIndex && lookahead > prevLength && prevLength < d.lazy { + if newLength, newOffset, ok := d.findMatch(s.index, s.chainHead-s.hashOffset, minMatchLength-1, lookahead); ok { + s.length = newLength + s.offset = newOffset + } + } + if prevLength >= minMatchLength && s.length <= prevLength { + // There was a match at the previous step, and the current match is + // not better. Output the previous match. + d.tokens.AddMatch(uint32(prevLength-3), uint32(prevOffset-minOffsetSize)) + + // Insert in the hash table all strings up to the end of the match. + // index and index-1 are already inserted. If there is not enough + // lookahead, the last two strings are not inserted into the hash + // table. + var newIndex int + newIndex = s.index + prevLength - 1 + // Calculate missing hashes + end := newIndex + if end > s.maxInsertIndex { + end = s.maxInsertIndex + } + end += minMatchLength - 1 + startindex := s.index + 1 + if startindex > s.maxInsertIndex { + startindex = s.maxInsertIndex + } + tocheck := d.window[startindex:end] + dstSize := len(tocheck) - minMatchLength + 1 + if dstSize > 0 { + dst := s.hashMatch[:dstSize] + bulkHash4(tocheck, dst) + var newH uint32 + for i, val := range dst { + di := i + startindex + newH = val & hashMask + // Get previous value with the same hash. + // Our chain should point to the previous value. + s.hashPrev[di&windowMask] = s.hashHead[newH] + // Set the head of the hash chain to us. + s.hashHead[newH] = uint32(di + s.hashOffset) + } + s.hash = newH + } + + s.index = newIndex + d.byteAvailable = false + s.length = minMatchLength - 1 + if d.tokens.n == maxFlateBlockTokens { + // The block includes the current character + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + } else { + // Reset, if we got a match this run. + if s.length >= minMatchLength { + s.ii = 0 + } + // We have a byte waiting. Emit it. + if d.byteAvailable { + s.ii++ + d.tokens.AddLiteral(d.window[s.index-1]) + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + s.index++ + + // If we have a long run of no matches, skip additional bytes + // Resets when s.ii overflows after 64KB. + if s.ii > 31 { + n := int(s.ii >> 5) + for j := 0; j < n; j++ { + if s.index >= d.windowEnd-1 { + break + } + + d.tokens.AddLiteral(d.window[s.index-1]) + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + s.index++ + } + // Flush last byte + d.tokens.AddLiteral(d.window[s.index-1]) + d.byteAvailable = false + // s.length = minMatchLength - 1 // not needed, since s.ii is reset above, so it should never be > minMatchLength + if d.tokens.n == maxFlateBlockTokens { + if d.err = d.writeBlock(&d.tokens, s.index, false); d.err != nil { + return + } + d.tokens.Reset() + } + } + } else { + s.index++ + d.byteAvailable = true + } + } + } +} + +func (d *compressor) store() { + if d.windowEnd > 0 && (d.windowEnd == maxStoreBlockSize || d.sync) { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + d.windowEnd = 0 + } +} + +// fillWindow will fill the buffer with data for huffman-only compression. +// The number of bytes copied is returned. +func (d *compressor) fillBlock(b []byte) int { + n := copy(d.window[d.windowEnd:], b) + d.windowEnd += n + return n +} + +// storeHuff will compress and store the currently added data, +// if enough has been accumulated or we at the end of the stream. +// Any error that occurred will be in d.err +func (d *compressor) storeHuff() { + if d.windowEnd < len(d.window) && !d.sync || d.windowEnd == 0 { + return + } + d.w.writeBlockHuff(false, d.window[:d.windowEnd], d.sync) + d.err = d.w.err + d.windowEnd = 0 +} + +// storeFast will compress and store the currently added data, +// if enough has been accumulated or we at the end of the stream. +// Any error that occurred will be in d.err +func (d *compressor) storeFast() { + // We only compress if we have maxStoreBlockSize. + if d.windowEnd < len(d.window) { + if !d.sync { + return + } + // Handle extremely small sizes. + if d.windowEnd < 128 { + if d.windowEnd == 0 { + return + } + if d.windowEnd <= 32 { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + } else { + d.w.writeBlockHuff(false, d.window[:d.windowEnd], true) + d.err = d.w.err + } + d.tokens.Reset() + d.windowEnd = 0 + d.fast.Reset() + return + } + } + + d.fast.Encode(&d.tokens, d.window[:d.windowEnd]) + // If we made zero matches, store the block as is. + if d.tokens.n == 0 { + d.err = d.writeStoredBlock(d.window[:d.windowEnd]) + // If we removed less than 1/16th, huffman compress the block. + } else if int(d.tokens.n) > d.windowEnd-(d.windowEnd>>4) { + d.w.writeBlockHuff(false, d.window[:d.windowEnd], d.sync) + d.err = d.w.err + } else { + d.w.writeBlockDynamic(&d.tokens, false, d.window[:d.windowEnd], d.sync) + d.err = d.w.err + } + d.tokens.Reset() + d.windowEnd = 0 +} + +// write will add input byte to the stream. +// Unless an error occurs all bytes will be consumed. +func (d *compressor) write(b []byte) (n int, err error) { + if d.err != nil { + return 0, d.err + } + n = len(b) + for len(b) > 0 { + d.step(d) + b = b[d.fill(d, b):] + if d.err != nil { + return 0, d.err + } + } + return n, d.err +} + +func (d *compressor) syncFlush() error { + d.sync = true + if d.err != nil { + return d.err + } + d.step(d) + if d.err == nil { + d.w.writeStoredHeader(0, false) + d.w.flush() + d.err = d.w.err + } + d.sync = false + return d.err +} + +func (d *compressor) init(w io.Writer, level int) (err error) { + d.w = newHuffmanBitWriter(w) + + switch { + case level == NoCompression: + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillBlock + d.step = (*compressor).store + case level == ConstantCompression: + d.w.logNewTablePenalty = 4 + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillBlock + d.step = (*compressor).storeHuff + case level == DefaultCompression: + level = 5 + fallthrough + case level >= 1 && level <= 6: + d.w.logNewTablePenalty = 6 + d.fast = newFastEnc(level) + d.window = make([]byte, maxStoreBlockSize) + d.fill = (*compressor).fillBlock + d.step = (*compressor).storeFast + case 7 <= level && level <= 9: + d.w.logNewTablePenalty = 10 + d.state = &advancedState{} + d.compressionLevel = levels[level] + d.initDeflate() + d.fill = (*compressor).fillDeflate + d.step = (*compressor).deflateLazy + default: + return fmt.Errorf("flate: invalid compression level %d: want value in range [-2, 9]", level) + } + d.level = level + return nil +} + +// reset the state of the compressor. +func (d *compressor) reset(w io.Writer) { + d.w.reset(w) + d.sync = false + d.err = nil + // We only need to reset a few things for Snappy. + if d.fast != nil { + d.fast.Reset() + d.windowEnd = 0 + d.tokens.Reset() + return + } + switch d.compressionLevel.chain { + case 0: + // level was NoCompression or ConstantCompresssion. + d.windowEnd = 0 + default: + s := d.state + s.chainHead = -1 + for i := range s.hashHead { + s.hashHead[i] = 0 + } + for i := range s.hashPrev { + s.hashPrev[i] = 0 + } + s.hashOffset = 1 + s.index, d.windowEnd = 0, 0 + d.blockStart, d.byteAvailable = 0, false + d.tokens.Reset() + s.length = minMatchLength - 1 + s.offset = 0 + s.hash = 0 + s.ii = 0 + s.maxInsertIndex = 0 + } +} + +func (d *compressor) close() error { + if d.err != nil { + return d.err + } + d.sync = true + d.step(d) + if d.err != nil { + return d.err + } + if d.w.writeStoredHeader(0, true); d.w.err != nil { + return d.w.err + } + d.w.flush() + d.w.reset(nil) + return d.w.err +} + +// NewWriter returns a new Writer compressing data at the given level. +// Following zlib, levels range from 1 (BestSpeed) to 9 (BestCompression); +// higher levels typically run slower but compress more. +// Level 0 (NoCompression) does not attempt any compression; it only adds the +// necessary DEFLATE framing. +// Level -1 (DefaultCompression) uses the default compression level. +// Level -2 (ConstantCompression) will use Huffman compression only, giving +// a very fast compression for all types of input, but sacrificing considerable +// compression efficiency. +// +// If level is in the range [-2, 9] then the error returned will be nil. +// Otherwise the error returned will be non-nil. +func NewWriter(w io.Writer, level int) (*Writer, error) { + var dw Writer + if err := dw.d.init(w, level); err != nil { + return nil, err + } + return &dw, nil +} + +// NewWriterDict is like NewWriter but initializes the new +// Writer with a preset dictionary. The returned Writer behaves +// as if the dictionary had been written to it without producing +// any compressed output. The compressed data written to w +// can only be decompressed by a Reader initialized with the +// same dictionary. +func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error) { + zw, err := NewWriter(w, level) + if err != nil { + return nil, err + } + zw.d.fillWindow(dict) + zw.dict = append(zw.dict, dict...) // duplicate dictionary for Reset method. + return zw, err +} + +// A Writer takes data written to it and writes the compressed +// form of that data to an underlying writer (see NewWriter). +type Writer struct { + d compressor + dict []byte +} + +// Write writes data to w, which will eventually write the +// compressed form of data to its underlying writer. +func (w *Writer) Write(data []byte) (n int, err error) { + return w.d.write(data) +} + +// Flush flushes any pending data to the underlying writer. +// It is useful mainly in compressed network protocols, to ensure that +// a remote reader has enough data to reconstruct a packet. +// Flush does not return until the data has been written. +// Calling Flush when there is no pending data still causes the Writer +// to emit a sync marker of at least 4 bytes. +// If the underlying writer returns an error, Flush returns that error. +// +// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. +func (w *Writer) Flush() error { + // For more about flushing: + // http://www.bolet.org/~pornin/deflate-flush.html + return w.d.syncFlush() +} + +// Close flushes and closes the writer. +func (w *Writer) Close() error { + return w.d.close() +} + +// Reset discards the writer's state and makes it equivalent to +// the result of NewWriter or NewWriterDict called with dst +// and w's level and dictionary. +func (w *Writer) Reset(dst io.Writer) { + if len(w.dict) > 0 { + // w was created with NewWriterDict + w.d.reset(dst) + if dst != nil { + w.d.fillWindow(w.dict) + } + } else { + // w was created with NewWriter + w.d.reset(dst) + } +} + +// ResetDict discards the writer's state and makes it equivalent to +// the result of NewWriter or NewWriterDict called with dst +// and w's level, but sets a specific dictionary. +func (w *Writer) ResetDict(dst io.Writer, dict []byte) { + w.dict = dict + w.d.reset(dst) + w.d.fillWindow(w.dict) +} diff --git a/vendor/github.com/klauspost/compress/flate/dict_decoder.go b/vendor/github.com/klauspost/compress/flate/dict_decoder.go new file mode 100644 index 00000000..71c75a06 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/dict_decoder.go @@ -0,0 +1,184 @@ +// Copyright 2016 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 flate + +// dictDecoder implements the LZ77 sliding dictionary as used in decompression. +// LZ77 decompresses data through sequences of two forms of commands: +// +// * Literal insertions: Runs of one or more symbols are inserted into the data +// stream as is. This is accomplished through the writeByte method for a +// single symbol, or combinations of writeSlice/writeMark for multiple symbols. +// Any valid stream must start with a literal insertion if no preset dictionary +// is used. +// +// * Backward copies: Runs of one or more symbols are copied from previously +// emitted data. Backward copies come as the tuple (dist, length) where dist +// determines how far back in the stream to copy from and length determines how +// many bytes to copy. Note that it is valid for the length to be greater than +// the distance. Since LZ77 uses forward copies, that situation is used to +// perform a form of run-length encoding on repeated runs of symbols. +// The writeCopy and tryWriteCopy are used to implement this command. +// +// For performance reasons, this implementation performs little to no sanity +// checks about the arguments. As such, the invariants documented for each +// method call must be respected. +type dictDecoder struct { + hist []byte // Sliding window history + + // Invariant: 0 <= rdPos <= wrPos <= len(hist) + wrPos int // Current output position in buffer + rdPos int // Have emitted hist[:rdPos] already + full bool // Has a full window length been written yet? +} + +// init initializes dictDecoder to have a sliding window dictionary of the given +// size. If a preset dict is provided, it will initialize the dictionary with +// the contents of dict. +func (dd *dictDecoder) init(size int, dict []byte) { + *dd = dictDecoder{hist: dd.hist} + + if cap(dd.hist) < size { + dd.hist = make([]byte, size) + } + dd.hist = dd.hist[:size] + + if len(dict) > len(dd.hist) { + dict = dict[len(dict)-len(dd.hist):] + } + dd.wrPos = copy(dd.hist, dict) + if dd.wrPos == len(dd.hist) { + dd.wrPos = 0 + dd.full = true + } + dd.rdPos = dd.wrPos +} + +// histSize reports the total amount of historical data in the dictionary. +func (dd *dictDecoder) histSize() int { + if dd.full { + return len(dd.hist) + } + return dd.wrPos +} + +// availRead reports the number of bytes that can be flushed by readFlush. +func (dd *dictDecoder) availRead() int { + return dd.wrPos - dd.rdPos +} + +// availWrite reports the available amount of output buffer space. +func (dd *dictDecoder) availWrite() int { + return len(dd.hist) - dd.wrPos +} + +// writeSlice returns a slice of the available buffer to write data to. +// +// This invariant will be kept: len(s) <= availWrite() +func (dd *dictDecoder) writeSlice() []byte { + return dd.hist[dd.wrPos:] +} + +// writeMark advances the writer pointer by cnt. +// +// This invariant must be kept: 0 <= cnt <= availWrite() +func (dd *dictDecoder) writeMark(cnt int) { + dd.wrPos += cnt +} + +// writeByte writes a single byte to the dictionary. +// +// This invariant must be kept: 0 < availWrite() +func (dd *dictDecoder) writeByte(c byte) { + dd.hist[dd.wrPos] = c + dd.wrPos++ +} + +// writeCopy copies a string at a given (dist, length) to the output. +// This returns the number of bytes copied and may be less than the requested +// length if the available space in the output buffer is too small. +// +// This invariant must be kept: 0 < dist <= histSize() +func (dd *dictDecoder) writeCopy(dist, length int) int { + dstBase := dd.wrPos + dstPos := dstBase + srcPos := dstPos - dist + endPos := dstPos + length + if endPos > len(dd.hist) { + endPos = len(dd.hist) + } + + // Copy non-overlapping section after destination position. + // + // This section is non-overlapping in that the copy length for this section + // is always less than or equal to the backwards distance. This can occur + // if a distance refers to data that wraps-around in the buffer. + // Thus, a backwards copy is performed here; that is, the exact bytes in + // the source prior to the copy is placed in the destination. + if srcPos < 0 { + srcPos += len(dd.hist) + dstPos += copy(dd.hist[dstPos:endPos], dd.hist[srcPos:]) + srcPos = 0 + } + + // Copy possibly overlapping section before destination position. + // + // This section can overlap if the copy length for this section is larger + // than the backwards distance. This is allowed by LZ77 so that repeated + // strings can be succinctly represented using (dist, length) pairs. + // Thus, a forwards copy is performed here; that is, the bytes copied is + // possibly dependent on the resulting bytes in the destination as the copy + // progresses along. This is functionally equivalent to the following: + // + // for i := 0; i < endPos-dstPos; i++ { + // dd.hist[dstPos+i] = dd.hist[srcPos+i] + // } + // dstPos = endPos + // + for dstPos < endPos { + dstPos += copy(dd.hist[dstPos:endPos], dd.hist[srcPos:dstPos]) + } + + dd.wrPos = dstPos + return dstPos - dstBase +} + +// tryWriteCopy tries to copy a string at a given (distance, length) to the +// output. This specialized version is optimized for short distances. +// +// This method is designed to be inlined for performance reasons. +// +// This invariant must be kept: 0 < dist <= histSize() +func (dd *dictDecoder) tryWriteCopy(dist, length int) int { + dstPos := dd.wrPos + endPos := dstPos + length + if dstPos < dist || endPos > len(dd.hist) { + return 0 + } + dstBase := dstPos + srcPos := dstPos - dist + + // Copy possibly overlapping section before destination position. +loop: + dstPos += copy(dd.hist[dstPos:endPos], dd.hist[srcPos:dstPos]) + if dstPos < endPos { + goto loop // Avoid for-loop so that this function can be inlined + } + + dd.wrPos = dstPos + return dstPos - dstBase +} + +// readFlush returns a slice of the historical buffer that is ready to be +// emitted to the user. The data returned by readFlush must be fully consumed +// before calling any other dictDecoder methods. +func (dd *dictDecoder) readFlush() []byte { + toRead := dd.hist[dd.rdPos:dd.wrPos] + dd.rdPos = dd.wrPos + if dd.wrPos == len(dd.hist) { + dd.wrPos, dd.rdPos = 0, 0 + dd.full = true + } + return toRead +} diff --git a/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/vendor/github.com/klauspost/compress/flate/fast_encoder.go new file mode 100644 index 00000000..4a73e1bd --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/fast_encoder.go @@ -0,0 +1,254 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Modified for deflate by Klaus Post (c) 2015. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flate + +import ( + "fmt" + "math/bits" +) + +type fastEnc interface { + Encode(dst *tokens, src []byte) + Reset() +} + +func newFastEnc(level int) fastEnc { + switch level { + case 1: + return &fastEncL1{fastGen: fastGen{cur: maxStoreBlockSize}} + case 2: + return &fastEncL2{fastGen: fastGen{cur: maxStoreBlockSize}} + case 3: + return &fastEncL3{fastGen: fastGen{cur: maxStoreBlockSize}} + case 4: + return &fastEncL4{fastGen: fastGen{cur: maxStoreBlockSize}} + case 5: + return &fastEncL5{fastGen: fastGen{cur: maxStoreBlockSize}} + case 6: + return &fastEncL6{fastGen: fastGen{cur: maxStoreBlockSize}} + default: + panic("invalid level specified") + } +} + +const ( + tableBits = 15 // Bits used in the table + tableSize = 1 << tableBits // Size of the table + tableShift = 32 - tableBits // Right-shift to get the tableBits most significant bits of a uint32. + baseMatchOffset = 1 // The smallest match offset + baseMatchLength = 3 // The smallest match length per the RFC section 3.2.5 + maxMatchOffset = 1 << 15 // The largest match offset + + bTableBits = 17 // Bits used in the big tables + bTableSize = 1 << bTableBits // Size of the table + allocHistory = maxStoreBlockSize * 10 // Size to preallocate for history. + bufferReset = (1 << 31) - allocHistory - maxStoreBlockSize - 1 // Reset the buffer offset when reaching this. +) + +const ( + prime3bytes = 506832829 + prime4bytes = 2654435761 + prime5bytes = 889523592379 + prime6bytes = 227718039650203 + prime7bytes = 58295818150454627 + prime8bytes = 0xcf1bbcdcb7a56463 +) + +func load32(b []byte, i int) uint32 { + // Help the compiler eliminate bounds checks on the read so it can be done in a single read. + b = b[i:] + b = b[:4] + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func load64(b []byte, i int) uint64 { + // Help the compiler eliminate bounds checks on the read so it can be done in a single read. + b = b[i:] + b = b[:8] + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func load3232(b []byte, i int32) uint32 { + // Help the compiler eliminate bounds checks on the read so it can be done in a single read. + b = b[i:] + b = b[:4] + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func load6432(b []byte, i int32) uint64 { + // Help the compiler eliminate bounds checks on the read so it can be done in a single read. + b = b[i:] + b = b[:8] + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func hash(u uint32) uint32 { + return (u * 0x1e35a7bd) >> tableShift +} + +type tableEntry struct { + offset int32 +} + +// fastGen maintains the table for matches, +// and the previous byte block for level 2. +// This is the generic implementation. +type fastGen struct { + hist []byte + cur int32 +} + +func (e *fastGen) addBlock(src []byte) int32 { + // check if we have space already + if len(e.hist)+len(src) > cap(e.hist) { + if cap(e.hist) == 0 { + e.hist = make([]byte, 0, allocHistory) + } else { + if cap(e.hist) < maxMatchOffset*2 { + panic("unexpected buffer size") + } + // Move down + offset := int32(len(e.hist)) - maxMatchOffset + copy(e.hist[0:maxMatchOffset], e.hist[offset:]) + e.cur += offset + e.hist = e.hist[:maxMatchOffset] + } + } + s := int32(len(e.hist)) + e.hist = append(e.hist, src...) + return s +} + +// hash4 returns the hash of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <32. +func hash4u(u uint32, h uint8) uint32 { + return (u * prime4bytes) >> ((32 - h) & reg8SizeMask32) +} + +type tableEntryPrev struct { + Cur tableEntry + Prev tableEntry +} + +// hash4x64 returns the hash of the lowest 4 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <32. +func hash4x64(u uint64, h uint8) uint32 { + return (uint32(u) * prime4bytes) >> ((32 - h) & reg8SizeMask32) +} + +// hash7 returns the hash of the lowest 7 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash7(u uint64, h uint8) uint32 { + return uint32(((u << (64 - 56)) * prime7bytes) >> ((64 - h) & reg8SizeMask64)) +} + +// hash8 returns the hash of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash8(u uint64, h uint8) uint32 { + return uint32((u * prime8bytes) >> ((64 - h) & reg8SizeMask64)) +} + +// hash6 returns the hash of the lowest 6 bytes of u to fit in a hash table with h bits. +// Preferably h should be a constant and should always be <64. +func hash6(u uint64, h uint8) uint32 { + return uint32(((u << (64 - 48)) * prime6bytes) >> ((64 - h) & reg8SizeMask64)) +} + +// matchlen will return the match length between offsets and t in src. +// The maximum length returned is maxMatchLength - 4. +// It is assumed that s > t, that t >=0 and s < len(src). +func (e *fastGen) matchlen(s, t int32, src []byte) int32 { + if debugDecode { + if t >= s { + panic(fmt.Sprint("t >=s:", t, s)) + } + if int(s) >= len(src) { + panic(fmt.Sprint("s >= len(src):", s, len(src))) + } + if t < 0 { + panic(fmt.Sprint("t < 0:", t)) + } + if s-t > maxMatchOffset { + panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) + } + } + s1 := int(s) + maxMatchLength - 4 + if s1 > len(src) { + s1 = len(src) + } + + // Extend the match to be as long as possible. + return int32(matchLen(src[s:s1], src[t:])) +} + +// matchlenLong will return the match length between offsets and t in src. +// It is assumed that s > t, that t >=0 and s < len(src). +func (e *fastGen) matchlenLong(s, t int32, src []byte) int32 { + if debugDecode { + if t >= s { + panic(fmt.Sprint("t >=s:", t, s)) + } + if int(s) >= len(src) { + panic(fmt.Sprint("s >= len(src):", s, len(src))) + } + if t < 0 { + panic(fmt.Sprint("t < 0:", t)) + } + if s-t > maxMatchOffset { + panic(fmt.Sprint(s, "-", t, "(", s-t, ") > maxMatchLength (", maxMatchOffset, ")")) + } + } + // Extend the match to be as long as possible. + return int32(matchLen(src[s:], src[t:])) +} + +// Reset the encoding table. +func (e *fastGen) Reset() { + if cap(e.hist) < allocHistory { + e.hist = make([]byte, 0, allocHistory) + } + // We offset current position so everything will be out of reach. + // If we are above the buffer reset it will be cleared anyway since len(hist) == 0. + if e.cur <= bufferReset { + e.cur += maxMatchOffset + int32(len(e.hist)) + } + e.hist = e.hist[:0] +} + +// matchLen returns the maximum length. +// 'a' must be the shortest of the two. +func matchLen(a, b []byte) int { + b = b[:len(a)] + var checked int + if len(a) > 4 { + // Try 4 bytes first + if diff := load32(a, 0) ^ load32(b, 0); diff != 0 { + return bits.TrailingZeros32(diff) >> 3 + } + // Switch to 8 byte matching. + checked = 4 + a = a[4:] + b = b[4:] + for len(a) >= 8 { + b = b[:len(a)] + if diff := load64(a, 0) ^ load64(b, 0); diff != 0 { + return checked + (bits.TrailingZeros64(diff) >> 3) + } + checked += 8 + a = a[8:] + b = b[8:] + } + } + b = b[:len(a)] + for i := range a { + if a[i] != b[i] { + return int(i) + checked + } + } + return len(a) + checked +} diff --git a/vendor/github.com/klauspost/compress/flate/gen_inflate.go b/vendor/github.com/klauspost/compress/flate/gen_inflate.go new file mode 100644 index 00000000..b26d19ec --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/gen_inflate.go @@ -0,0 +1,276 @@ +// +build generate + +//go:generate go run $GOFILE && gofmt -w inflate_gen.go + +package main + +import ( + "os" + "strings" +) + +func main() { + f, err := os.Create("inflate_gen.go") + if err != nil { + panic(err) + } + defer f.Close() + types := []string{"*bytes.Buffer", "*bytes.Reader", "*bufio.Reader", "*strings.Reader"} + names := []string{"BytesBuffer", "BytesReader", "BufioReader", "StringsReader"} + imports := []string{"bytes", "bufio", "io", "strings", "math/bits"} + f.WriteString(`// Code generated by go generate gen_inflate.go. DO NOT EDIT. + +package flate + +import ( +`) + + for _, imp := range imports { + f.WriteString("\t\"" + imp + "\"\n") + } + f.WriteString(")\n\n") + + template := ` + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) $FUNCNAME$() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.($TYPE$) + moreBits := func() error { + c, err := fr.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << f.nb + f.nb += 8 + return nil + } + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := fr.ReadByte() + if err != nil { + f.b = b + f.nb = nb + f.err = noEOF(err) + return + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := f.hl.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var n uint // number of bits extra + var length int + var err error + switch { + case v < 256: + f.dict.writeByte(byte(v)) + if f.dict.availWrite() == 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).$FUNCNAME$ + f.stepState = stateInit + return + } + goto readLiteral + case v == 256: + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + } + length += int(f.b & uint32(1<<(n®SizeMaskUint32)-1)) + f.b >>= n & regSizeMaskUint32 + f.nb -= n + } + + var dist uint32 + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + } + dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3))) + f.b >>= 5 + f.nb -= 5 + } else { + sym, err := f.huffSym(f.hd) + if err != nil { + if debugDecode { + fmt.Println("huffsym:", err) + } + f.err = err + return + } + dist = uint32(sym) + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for f.nb < nb { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + f.nb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + default: + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(f.dict.histSize()) { + if debugDecode { + fmt.Println("dist > f.dict.histSize():", dist, f.dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := f.dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = f.dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).$FUNCNAME$ // We need to continue this work + f.stepState = stateDict + return + } + goto readLiteral + } +} + +` + for i, t := range types { + s := strings.Replace(template, "$FUNCNAME$", "huffman"+names[i], -1) + s = strings.Replace(s, "$TYPE$", t, -1) + f.WriteString(s) + } + f.WriteString("func (f *decompressor) huffmanBlockDecoder() func() {\n") + f.WriteString("\tswitch f.r.(type) {\n") + for i, t := range types { + f.WriteString("\t\tcase " + t + ":\n") + f.WriteString("\t\t\treturn f.huffman" + names[i] + "\n") + } + f.WriteString("\t\tdefault:\n") + f.WriteString("\t\t\treturn f.huffmanBlockGeneric") + f.WriteString("\t}\n}\n") +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go new file mode 100644 index 00000000..208d6671 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go @@ -0,0 +1,911 @@ +// Copyright 2009 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 flate + +import ( + "io" +) + +const ( + // The largest offset code. + offsetCodeCount = 30 + + // The special code used to mark the end of a block. + endBlockMarker = 256 + + // The first length code. + lengthCodesStart = 257 + + // The number of codegen codes. + codegenCodeCount = 19 + badCode = 255 + + // bufferFlushSize indicates the buffer size + // after which bytes are flushed to the writer. + // Should preferably be a multiple of 6, since + // we accumulate 6 bytes between writes to the buffer. + bufferFlushSize = 240 + + // bufferSize is the actual output byte buffer size. + // It must have additional headroom for a flush + // which can contain up to 8 bytes. + bufferSize = bufferFlushSize + 8 +) + +// The number of extra bits needed by length code X - LENGTH_CODES_START. +var lengthExtraBits = [32]int8{ + /* 257 */ 0, 0, 0, + /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, + /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, + /* 280 */ 4, 5, 5, 5, 5, 0, +} + +// The length indicated by length code X - LENGTH_CODES_START. +var lengthBase = [32]uint8{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, + 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 255, +} + +// offset code word extra bits. +var offsetExtraBits = [64]int8{ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, + 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, + /* extended window */ + 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, +} + +var offsetBase = [64]uint32{ + /* normal deflate */ + 0x000000, 0x000001, 0x000002, 0x000003, 0x000004, + 0x000006, 0x000008, 0x00000c, 0x000010, 0x000018, + 0x000020, 0x000030, 0x000040, 0x000060, 0x000080, + 0x0000c0, 0x000100, 0x000180, 0x000200, 0x000300, + 0x000400, 0x000600, 0x000800, 0x000c00, 0x001000, + 0x001800, 0x002000, 0x003000, 0x004000, 0x006000, + + /* extended window */ + 0x008000, 0x00c000, 0x010000, 0x018000, 0x020000, + 0x030000, 0x040000, 0x060000, 0x080000, 0x0c0000, + 0x100000, 0x180000, 0x200000, 0x300000, +} + +// The odd order in which the codegen code sizes are written. +var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} + +type huffmanBitWriter struct { + // writer is the underlying writer. + // Do not use it directly; use the write method, which ensures + // that Write errors are sticky. + writer io.Writer + + // Data waiting to be written is bytes[0:nbytes] + // and then the low nbits of bits. + bits uint64 + nbits uint16 + nbytes uint8 + literalEncoding *huffmanEncoder + offsetEncoding *huffmanEncoder + codegenEncoding *huffmanEncoder + err error + lastHeader int + // Set between 0 (reused block can be up to 2x the size) + logNewTablePenalty uint + lastHuffMan bool + bytes [256]byte + literalFreq [lengthCodesStart + 32]uint16 + offsetFreq [32]uint16 + codegenFreq [codegenCodeCount]uint16 + + // codegen must have an extra space for the final symbol. + codegen [literalCount + offsetCodeCount + 1]uint8 +} + +// Huffman reuse. +// +// The huffmanBitWriter supports reusing huffman tables and thereby combining block sections. +// +// This is controlled by several variables: +// +// If lastHeader is non-zero the Huffman table can be reused. +// This also indicates that a Huffman table has been generated that can output all +// possible symbols. +// It also indicates that an EOB has not yet been emitted, so if a new tabel is generated +// an EOB with the previous table must be written. +// +// If lastHuffMan is set, a table for outputting literals has been generated and offsets are invalid. +// +// An incoming block estimates the output size of a new table using a 'fresh' by calculating the +// optimal size and adding a penalty in 'logNewTablePenalty'. +// A Huffman table is not optimal, which is why we add a penalty, and generating a new table +// is slower both for compression and decompression. + +func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter { + return &huffmanBitWriter{ + writer: w, + literalEncoding: newHuffmanEncoder(literalCount), + codegenEncoding: newHuffmanEncoder(codegenCodeCount), + offsetEncoding: newHuffmanEncoder(offsetCodeCount), + } +} + +func (w *huffmanBitWriter) reset(writer io.Writer) { + w.writer = writer + w.bits, w.nbits, w.nbytes, w.err = 0, 0, 0, nil + w.lastHeader = 0 + w.lastHuffMan = false +} + +func (w *huffmanBitWriter) canReuse(t *tokens) (offsets, lits bool) { + offsets, lits = true, true + a := t.offHist[:offsetCodeCount] + b := w.offsetFreq[:len(a)] + for i := range a { + if b[i] == 0 && a[i] != 0 { + offsets = false + break + } + } + + a = t.extraHist[:literalCount-256] + b = w.literalFreq[256:literalCount] + b = b[:len(a)] + for i := range a { + if b[i] == 0 && a[i] != 0 { + lits = false + break + } + } + if lits { + a = t.litHist[:] + b = w.literalFreq[:len(a)] + for i := range a { + if b[i] == 0 && a[i] != 0 { + lits = false + break + } + } + } + return +} + +func (w *huffmanBitWriter) flush() { + if w.err != nil { + w.nbits = 0 + return + } + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + n := w.nbytes + for w.nbits != 0 { + w.bytes[n] = byte(w.bits) + w.bits >>= 8 + if w.nbits > 8 { // Avoid underflow + w.nbits -= 8 + } else { + w.nbits = 0 + } + n++ + } + w.bits = 0 + w.write(w.bytes[:n]) + w.nbytes = 0 +} + +func (w *huffmanBitWriter) write(b []byte) { + if w.err != nil { + return + } + _, w.err = w.writer.Write(b) +} + +func (w *huffmanBitWriter) writeBits(b int32, nb uint16) { + w.bits |= uint64(b) << (w.nbits & reg16SizeMask64) + w.nbits += nb + if w.nbits >= 48 { + w.writeOutBits() + } +} + +func (w *huffmanBitWriter) writeBytes(bytes []byte) { + if w.err != nil { + return + } + n := w.nbytes + if w.nbits&7 != 0 { + w.err = InternalError("writeBytes with unfinished bits") + return + } + for w.nbits != 0 { + w.bytes[n] = byte(w.bits) + w.bits >>= 8 + w.nbits -= 8 + n++ + } + if n != 0 { + w.write(w.bytes[:n]) + } + w.nbytes = 0 + w.write(bytes) +} + +// RFC 1951 3.2.7 specifies a special run-length encoding for specifying +// the literal and offset lengths arrays (which are concatenated into a single +// array). This method generates that run-length encoding. +// +// The result is written into the codegen array, and the frequencies +// of each code is written into the codegenFreq array. +// Codes 0-15 are single byte codes. Codes 16-18 are followed by additional +// information. Code badCode is an end marker +// +// numLiterals The number of literals in literalEncoding +// numOffsets The number of offsets in offsetEncoding +// litenc, offenc The literal and offset encoder to use +func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, litEnc, offEnc *huffmanEncoder) { + for i := range w.codegenFreq { + w.codegenFreq[i] = 0 + } + // Note that we are using codegen both as a temporary variable for holding + // a copy of the frequencies, and as the place where we put the result. + // This is fine because the output is always shorter than the input used + // so far. + codegen := w.codegen[:] // cache + // Copy the concatenated code sizes to codegen. Put a marker at the end. + cgnl := codegen[:numLiterals] + for i := range cgnl { + cgnl[i] = uint8(litEnc.codes[i].len) + } + + cgnl = codegen[numLiterals : numLiterals+numOffsets] + for i := range cgnl { + cgnl[i] = uint8(offEnc.codes[i].len) + } + codegen[numLiterals+numOffsets] = badCode + + size := codegen[0] + count := 1 + outIndex := 0 + for inIndex := 1; size != badCode; inIndex++ { + // INVARIANT: We have seen "count" copies of size that have not yet + // had output generated for them. + nextSize := codegen[inIndex] + if nextSize == size { + count++ + continue + } + // We need to generate codegen indicating "count" of size. + if size != 0 { + codegen[outIndex] = size + outIndex++ + w.codegenFreq[size]++ + count-- + for count >= 3 { + n := 6 + if n > count { + n = count + } + codegen[outIndex] = 16 + outIndex++ + codegen[outIndex] = uint8(n - 3) + outIndex++ + w.codegenFreq[16]++ + count -= n + } + } else { + for count >= 11 { + n := 138 + if n > count { + n = count + } + codegen[outIndex] = 18 + outIndex++ + codegen[outIndex] = uint8(n - 11) + outIndex++ + w.codegenFreq[18]++ + count -= n + } + if count >= 3 { + // count >= 3 && count <= 10 + codegen[outIndex] = 17 + outIndex++ + codegen[outIndex] = uint8(count - 3) + outIndex++ + w.codegenFreq[17]++ + count = 0 + } + } + count-- + for ; count >= 0; count-- { + codegen[outIndex] = size + outIndex++ + w.codegenFreq[size]++ + } + // Set up invariant for next time through the loop. + size = nextSize + count = 1 + } + // Marker indicating the end of the codegen. + codegen[outIndex] = badCode +} + +func (w *huffmanBitWriter) codegens() int { + numCodegens := len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + return numCodegens +} + +func (w *huffmanBitWriter) headerSize() (size, numCodegens int) { + numCodegens = len(w.codegenFreq) + for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { + numCodegens-- + } + return 3 + 5 + 5 + 4 + (3 * numCodegens) + + w.codegenEncoding.bitLength(w.codegenFreq[:]) + + int(w.codegenFreq[16])*2 + + int(w.codegenFreq[17])*3 + + int(w.codegenFreq[18])*7, numCodegens +} + +// dynamicSize returns the size of dynamically encoded data in bits. +func (w *huffmanBitWriter) dynamicReuseSize(litEnc, offEnc *huffmanEncoder) (size int) { + size = litEnc.bitLength(w.literalFreq[:]) + + offEnc.bitLength(w.offsetFreq[:]) + return size +} + +// dynamicSize returns the size of dynamically encoded data in bits. +func (w *huffmanBitWriter) dynamicSize(litEnc, offEnc *huffmanEncoder, extraBits int) (size, numCodegens int) { + header, numCodegens := w.headerSize() + size = header + + litEnc.bitLength(w.literalFreq[:]) + + offEnc.bitLength(w.offsetFreq[:]) + + extraBits + return size, numCodegens +} + +// extraBitSize will return the number of bits that will be written +// as "extra" bits on matches. +func (w *huffmanBitWriter) extraBitSize() int { + total := 0 + for i, n := range w.literalFreq[257:literalCount] { + total += int(n) * int(lengthExtraBits[i&31]) + } + for i, n := range w.offsetFreq[:offsetCodeCount] { + total += int(n) * int(offsetExtraBits[i&31]) + } + return total +} + +// fixedSize returns the size of dynamically encoded data in bits. +func (w *huffmanBitWriter) fixedSize(extraBits int) int { + return 3 + + fixedLiteralEncoding.bitLength(w.literalFreq[:]) + + fixedOffsetEncoding.bitLength(w.offsetFreq[:]) + + extraBits +} + +// storedSize calculates the stored size, including header. +// The function returns the size in bits and whether the block +// fits inside a single block. +func (w *huffmanBitWriter) storedSize(in []byte) (int, bool) { + if in == nil { + return 0, false + } + if len(in) <= maxStoreBlockSize { + return (len(in) + 5) * 8, true + } + return 0, false +} + +func (w *huffmanBitWriter) writeCode(c hcode) { + // The function does not get inlined if we "& 63" the shift. + w.bits |= uint64(c.code) << w.nbits + w.nbits += c.len + if w.nbits >= 48 { + w.writeOutBits() + } +} + +// writeOutBits will write bits to the buffer. +func (w *huffmanBitWriter) writeOutBits() { + bits := w.bits + w.bits >>= 48 + w.nbits -= 48 + n := w.nbytes + w.bytes[n] = byte(bits) + w.bytes[n+1] = byte(bits >> 8) + w.bytes[n+2] = byte(bits >> 16) + w.bytes[n+3] = byte(bits >> 24) + w.bytes[n+4] = byte(bits >> 32) + w.bytes[n+5] = byte(bits >> 40) + n += 6 + if n >= bufferFlushSize { + if w.err != nil { + n = 0 + return + } + w.write(w.bytes[:n]) + n = 0 + } + w.nbytes = n +} + +// Write the header of a dynamic Huffman block to the output stream. +// +// numLiterals The number of literals specified in codegen +// numOffsets The number of offsets specified in codegen +// numCodegens The number of codegens used in codegen +func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) { + if w.err != nil { + return + } + var firstBits int32 = 4 + if isEof { + firstBits = 5 + } + w.writeBits(firstBits, 3) + w.writeBits(int32(numLiterals-257), 5) + w.writeBits(int32(numOffsets-1), 5) + w.writeBits(int32(numCodegens-4), 4) + + for i := 0; i < numCodegens; i++ { + value := uint(w.codegenEncoding.codes[codegenOrder[i]].len) + w.writeBits(int32(value), 3) + } + + i := 0 + for { + var codeWord = uint32(w.codegen[i]) + i++ + if codeWord == badCode { + break + } + w.writeCode(w.codegenEncoding.codes[codeWord]) + + switch codeWord { + case 16: + w.writeBits(int32(w.codegen[i]), 2) + i++ + case 17: + w.writeBits(int32(w.codegen[i]), 3) + i++ + case 18: + w.writeBits(int32(w.codegen[i]), 7) + i++ + } + } +} + +// writeStoredHeader will write a stored header. +// If the stored block is only used for EOF, +// it is replaced with a fixed huffman block. +func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) { + if w.err != nil { + return + } + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + + // To write EOF, use a fixed encoding block. 10 bits instead of 5 bytes. + if length == 0 && isEof { + w.writeFixedHeader(isEof) + // EOB: 7 bits, value: 0 + w.writeBits(0, 7) + w.flush() + return + } + + var flag int32 + if isEof { + flag = 1 + } + w.writeBits(flag, 3) + w.flush() + w.writeBits(int32(length), 16) + w.writeBits(int32(^uint16(length)), 16) +} + +func (w *huffmanBitWriter) writeFixedHeader(isEof bool) { + if w.err != nil { + return + } + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + + // Indicate that we are a fixed Huffman block + var value int32 = 2 + if isEof { + value = 3 + } + w.writeBits(value, 3) +} + +// writeBlock will write a block of tokens with the smallest encoding. +// The original input can be supplied, and if the huffman encoded data +// is larger than the original bytes, the data will be written as a +// stored block. +// If the input is nil, the tokens will always be Huffman encoded. +func (w *huffmanBitWriter) writeBlock(tokens *tokens, eof bool, input []byte) { + if w.err != nil { + return + } + + tokens.AddEOB() + if w.lastHeader > 0 { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + numLiterals, numOffsets := w.indexTokens(tokens, false) + w.generate(tokens) + var extraBits int + storedSize, storable := w.storedSize(input) + if storable { + extraBits = w.extraBitSize() + } + + // Figure out smallest code. + // Fixed Huffman baseline. + var literalEncoding = fixedLiteralEncoding + var offsetEncoding = fixedOffsetEncoding + var size = w.fixedSize(extraBits) + + // Dynamic Huffman? + var numCodegens int + + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding) + w.codegenEncoding.generate(w.codegenFreq[:], 7) + dynamicSize, numCodegens := w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits) + + if dynamicSize < size { + size = dynamicSize + literalEncoding = w.literalEncoding + offsetEncoding = w.offsetEncoding + } + + // Stored bytes? + if storable && storedSize < size { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + + // Huffman. + if literalEncoding == fixedLiteralEncoding { + w.writeFixedHeader(eof) + } else { + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + } + + // Write the tokens. + w.writeTokens(tokens.Slice(), literalEncoding.codes, offsetEncoding.codes) +} + +// writeBlockDynamic encodes a block using a dynamic Huffman table. +// This should be used if the symbols used have a disproportionate +// histogram distribution. +// If input is supplied and the compression savings are below 1/16th of the +// input size the block is stored. +func (w *huffmanBitWriter) writeBlockDynamic(tokens *tokens, eof bool, input []byte, sync bool) { + if w.err != nil { + return + } + + sync = sync || eof + if sync { + tokens.AddEOB() + } + + // We cannot reuse pure huffman table, and must mark as EOF. + if (w.lastHuffMan || eof) && w.lastHeader > 0 { + // We will not try to reuse. + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + w.lastHuffMan = false + } + if !sync { + tokens.Fill() + } + numLiterals, numOffsets := w.indexTokens(tokens, !sync) + + var size int + // Check if we should reuse. + if w.lastHeader > 0 { + // Estimate size for using a new table. + // Use the previous header size as the best estimate. + newSize := w.lastHeader + tokens.EstimatedBits() + newSize += newSize >> w.logNewTablePenalty + + // The estimated size is calculated as an optimal table. + // We add a penalty to make it more realistic and re-use a bit more. + reuseSize := w.dynamicReuseSize(w.literalEncoding, w.offsetEncoding) + w.extraBitSize() + + // Check if a new table is better. + if newSize < reuseSize { + // Write the EOB we owe. + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + size = newSize + w.lastHeader = 0 + } else { + size = reuseSize + } + // Check if we get a reasonable size decrease. + if ssize, storable := w.storedSize(input); storable && ssize < (size+size>>4) { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + w.lastHeader = 0 + return + } + } + + // We want a new block/table + if w.lastHeader == 0 { + w.generate(tokens) + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding) + w.codegenEncoding.generate(w.codegenFreq[:], 7) + var numCodegens int + size, numCodegens = w.dynamicSize(w.literalEncoding, w.offsetEncoding, w.extraBitSize()) + // Store bytes, if we don't get a reasonable improvement. + if ssize, storable := w.storedSize(input); storable && ssize < (size+size>>4) { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + w.lastHeader = 0 + return + } + + // Write Huffman table. + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + w.lastHeader, _ = w.headerSize() + w.lastHuffMan = false + } + + if sync { + w.lastHeader = 0 + } + // Write the tokens. + w.writeTokens(tokens.Slice(), w.literalEncoding.codes, w.offsetEncoding.codes) +} + +// indexTokens indexes a slice of tokens, and updates +// literalFreq and offsetFreq, and generates literalEncoding +// and offsetEncoding. +// The number of literal and offset tokens is returned. +func (w *huffmanBitWriter) indexTokens(t *tokens, filled bool) (numLiterals, numOffsets int) { + copy(w.literalFreq[:], t.litHist[:]) + copy(w.literalFreq[256:], t.extraHist[:]) + copy(w.offsetFreq[:], t.offHist[:offsetCodeCount]) + + if t.n == 0 { + return + } + if filled { + return maxNumLit, maxNumDist + } + // get the number of literals + numLiterals = len(w.literalFreq) + for w.literalFreq[numLiterals-1] == 0 { + numLiterals-- + } + // get the number of offsets + numOffsets = len(w.offsetFreq) + for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 { + numOffsets-- + } + if numOffsets == 0 { + // We haven't found a single match. If we want to go with the dynamic encoding, + // we should count at least one offset to be sure that the offset huffman tree could be encoded. + w.offsetFreq[0] = 1 + numOffsets = 1 + } + return +} + +func (w *huffmanBitWriter) generate(t *tokens) { + w.literalEncoding.generate(w.literalFreq[:literalCount], 15) + w.offsetEncoding.generate(w.offsetFreq[:offsetCodeCount], 15) +} + +// writeTokens writes a slice of tokens to the output. +// codes for literal and offset encoding must be supplied. +func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) { + if w.err != nil { + return + } + if len(tokens) == 0 { + return + } + + // Only last token should be endBlockMarker. + var deferEOB bool + if tokens[len(tokens)-1] == endBlockMarker { + tokens = tokens[:len(tokens)-1] + deferEOB = true + } + + // Create slices up to the next power of two to avoid bounds checks. + lits := leCodes[:256] + offs := oeCodes[:32] + lengths := leCodes[lengthCodesStart:] + lengths = lengths[:32] + for _, t := range tokens { + if t < matchType { + w.writeCode(lits[t.literal()]) + continue + } + + // Write the length + length := t.length() + lengthCode := lengthCode(length) + if false { + w.writeCode(lengths[lengthCode&31]) + } else { + // inlined + c := lengths[lengthCode&31] + w.bits |= uint64(c.code) << (w.nbits & reg16SizeMask64) + w.nbits += c.len + if w.nbits >= 48 { + w.writeOutBits() + } + } + + extraLengthBits := uint16(lengthExtraBits[lengthCode&31]) + if extraLengthBits > 0 { + extraLength := int32(length - lengthBase[lengthCode&31]) + w.writeBits(extraLength, extraLengthBits) + } + // Write the offset + offset := t.offset() + offsetCode := offsetCode(offset) + if false { + w.writeCode(offs[offsetCode&31]) + } else { + // inlined + c := offs[offsetCode&31] + w.bits |= uint64(c.code) << (w.nbits & reg16SizeMask64) + w.nbits += c.len + if w.nbits >= 48 { + w.writeOutBits() + } + } + extraOffsetBits := uint16(offsetExtraBits[offsetCode&63]) + if extraOffsetBits > 0 { + extraOffset := int32(offset - offsetBase[offsetCode&63]) + w.writeBits(extraOffset, extraOffsetBits) + } + } + if deferEOB { + w.writeCode(leCodes[endBlockMarker]) + } +} + +// huffOffset is a static offset encoder used for huffman only encoding. +// It can be reused since we will not be encoding offset values. +var huffOffset *huffmanEncoder + +func init() { + w := newHuffmanBitWriter(nil) + w.offsetFreq[0] = 1 + huffOffset = newHuffmanEncoder(offsetCodeCount) + huffOffset.generate(w.offsetFreq[:offsetCodeCount], 15) +} + +// writeBlockHuff encodes a block of bytes as either +// Huffman encoded literals or uncompressed bytes if the +// results only gains very little from compression. +func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) { + if w.err != nil { + return + } + + // Clear histogram + for i := range w.literalFreq[:] { + w.literalFreq[i] = 0 + } + if !w.lastHuffMan { + for i := range w.offsetFreq[:] { + w.offsetFreq[i] = 0 + } + } + + // Add everything as literals + // We have to estimate the header size. + // Assume header is around 70 bytes: + // https://stackoverflow.com/a/25454430 + const guessHeaderSizeBits = 70 * 8 + estBits, estExtra := histogramSize(input, w.literalFreq[:], !eof && !sync) + estBits += w.lastHeader + 15 + if w.lastHeader == 0 { + estBits += guessHeaderSizeBits + } + estBits += estBits >> w.logNewTablePenalty + + // Store bytes, if we don't get a reasonable improvement. + ssize, storable := w.storedSize(input) + if storable && ssize < estBits { + w.writeStoredHeader(len(input), eof) + w.writeBytes(input) + return + } + + if w.lastHeader > 0 { + reuseSize := w.literalEncoding.bitLength(w.literalFreq[:256]) + estBits += estExtra + + if estBits < reuseSize { + // We owe an EOB + w.writeCode(w.literalEncoding.codes[endBlockMarker]) + w.lastHeader = 0 + } + } + + const numLiterals = endBlockMarker + 1 + const numOffsets = 1 + if w.lastHeader == 0 { + w.literalFreq[endBlockMarker] = 1 + w.literalEncoding.generate(w.literalFreq[:numLiterals], 15) + + // Generate codegen and codegenFrequencies, which indicates how to encode + // the literalEncoding and the offsetEncoding. + w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, huffOffset) + w.codegenEncoding.generate(w.codegenFreq[:], 7) + numCodegens := w.codegens() + + // Huffman. + w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) + w.lastHuffMan = true + w.lastHeader, _ = w.headerSize() + } + + encoding := w.literalEncoding.codes[:257] + for _, t := range input { + // Bitwriting inlined, ~30% speedup + c := encoding[t] + w.bits |= uint64(c.code) << ((w.nbits) & reg16SizeMask64) + w.nbits += c.len + if w.nbits >= 48 { + bits := w.bits + w.bits >>= 48 + w.nbits -= 48 + n := w.nbytes + w.bytes[n] = byte(bits) + w.bytes[n+1] = byte(bits >> 8) + w.bytes[n+2] = byte(bits >> 16) + w.bytes[n+3] = byte(bits >> 24) + w.bytes[n+4] = byte(bits >> 32) + w.bytes[n+5] = byte(bits >> 40) + n += 6 + if n >= bufferFlushSize { + if w.err != nil { + n = 0 + return + } + w.write(w.bytes[:n]) + n = 0 + } + w.nbytes = n + } + } + if eof || sync { + w.writeCode(encoding[endBlockMarker]) + w.lastHeader = 0 + w.lastHuffMan = false + } +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_code.go b/vendor/github.com/klauspost/compress/flate/huffman_code.go new file mode 100644 index 00000000..4c39a301 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_code.go @@ -0,0 +1,363 @@ +// Copyright 2009 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 flate + +import ( + "math" + "math/bits" +) + +const ( + maxBitsLimit = 16 + // number of valid literals + literalCount = 286 +) + +// hcode is a huffman code with a bit code and bit length. +type hcode struct { + code, len uint16 +} + +type huffmanEncoder struct { + codes []hcode + freqcache []literalNode + bitCount [17]int32 +} + +type literalNode struct { + literal uint16 + freq uint16 +} + +// A levelInfo describes the state of the constructed tree for a given depth. +type levelInfo struct { + // Our level. for better printing + level int32 + + // The frequency of the last node at this level + lastFreq int32 + + // The frequency of the next character to add to this level + nextCharFreq int32 + + // The frequency of the next pair (from level below) to add to this level. + // Only valid if the "needed" value of the next lower level is 0. + nextPairFreq int32 + + // The number of chains remaining to generate for this level before moving + // up to the next level + needed int32 +} + +// set sets the code and length of an hcode. +func (h *hcode) set(code uint16, length uint16) { + h.len = length + h.code = code +} + +func reverseBits(number uint16, bitLength byte) uint16 { + return bits.Reverse16(number << ((16 - bitLength) & 15)) +} + +func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxUint16} } + +func newHuffmanEncoder(size int) *huffmanEncoder { + // Make capacity to next power of two. + c := uint(bits.Len32(uint32(size - 1))) + return &huffmanEncoder{codes: make([]hcode, size, 1<= 3 +// The cases of 0, 1, and 2 literals are handled by special case code. +// +// list An array of the literals with non-zero frequencies +// and their associated frequencies. The array is in order of increasing +// frequency, and has as its last element a special element with frequency +// MaxInt32 +// maxBits The maximum number of bits that should be used to encode any literal. +// Must be less than 16. +// return An integer array in which array[i] indicates the number of literals +// that should be encoded in i bits. +func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { + if maxBits >= maxBitsLimit { + panic("flate: maxBits too large") + } + n := int32(len(list)) + list = list[0 : n+1] + list[n] = maxNode() + + // The tree can't have greater depth than n - 1, no matter what. This + // saves a little bit of work in some small cases + if maxBits > n-1 { + maxBits = n - 1 + } + + // Create information about each of the levels. + // A bogus "Level 0" whose sole purpose is so that + // level1.prev.needed==0. This makes level1.nextPairFreq + // be a legitimate value that never gets chosen. + var levels [maxBitsLimit]levelInfo + // leafCounts[i] counts the number of literals at the left + // of ancestors of the rightmost node at level i. + // leafCounts[i][j] is the number of literals at the left + // of the level j ancestor. + var leafCounts [maxBitsLimit][maxBitsLimit]int32 + + for level := int32(1); level <= maxBits; level++ { + // For every level, the first two items are the first two characters. + // We initialize the levels as if we had already figured this out. + levels[level] = levelInfo{ + level: level, + lastFreq: int32(list[1].freq), + nextCharFreq: int32(list[2].freq), + nextPairFreq: int32(list[0].freq) + int32(list[1].freq), + } + leafCounts[level][level] = 2 + if level == 1 { + levels[level].nextPairFreq = math.MaxInt32 + } + } + + // We need a total of 2*n - 2 items at top level and have already generated 2. + levels[maxBits].needed = 2*n - 4 + + level := maxBits + for { + l := &levels[level] + if l.nextPairFreq == math.MaxInt32 && l.nextCharFreq == math.MaxInt32 { + // We've run out of both leafs and pairs. + // End all calculations for this level. + // To make sure we never come back to this level or any lower level, + // set nextPairFreq impossibly large. + l.needed = 0 + levels[level+1].nextPairFreq = math.MaxInt32 + level++ + continue + } + + prevFreq := l.lastFreq + if l.nextCharFreq < l.nextPairFreq { + // The next item on this row is a leaf node. + n := leafCounts[level][level] + 1 + l.lastFreq = l.nextCharFreq + // Lower leafCounts are the same of the previous node. + leafCounts[level][level] = n + e := list[n] + if e.literal < math.MaxUint16 { + l.nextCharFreq = int32(e.freq) + } else { + l.nextCharFreq = math.MaxInt32 + } + } else { + // The next item on this row is a pair from the previous row. + // nextPairFreq isn't valid until we generate two + // more values in the level below + l.lastFreq = l.nextPairFreq + // Take leaf counts from the lower level, except counts[level] remains the same. + copy(leafCounts[level][:level], leafCounts[level-1][:level]) + levels[l.level-1].needed = 2 + } + + if l.needed--; l.needed == 0 { + // We've done everything we need to do for this level. + // Continue calculating one level up. Fill in nextPairFreq + // of that level with the sum of the two nodes we've just calculated on + // this level. + if l.level == maxBits { + // All done! + break + } + levels[l.level+1].nextPairFreq = prevFreq + l.lastFreq + level++ + } else { + // If we stole from below, move down temporarily to replenish it. + for levels[level-1].needed > 0 { + level-- + } + } + } + + // Somethings is wrong if at the end, the top level is null or hasn't used + // all of the leaves. + if leafCounts[maxBits][maxBits] != n { + panic("leafCounts[maxBits][maxBits] != n") + } + + bitCount := h.bitCount[:maxBits+1] + bits := 1 + counts := &leafCounts[maxBits] + for level := maxBits; level > 0; level-- { + // chain.leafCount gives the number of literals requiring at least "bits" + // bits to encode. + bitCount[bits] = counts[level] - counts[level-1] + bits++ + } + return bitCount +} + +// Look at the leaves and assign them a bit count and an encoding as specified +// in RFC 1951 3.2.2 +func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode) { + code := uint16(0) + for n, bits := range bitCount { + code <<= 1 + if n == 0 || bits == 0 { + continue + } + // The literals list[len(list)-bits] .. list[len(list)-bits] + // are encoded using "bits" bits, and get the values + // code, code + 1, .... The code values are + // assigned in literal order (not frequency order). + chunk := list[len(list)-int(bits):] + + sortByLiteral(chunk) + for _, node := range chunk { + h.codes[node.literal] = hcode{code: reverseBits(code, uint8(n)), len: uint16(n)} + code++ + } + list = list[0 : len(list)-int(bits)] + } +} + +// Update this Huffman Code object to be the minimum code for the specified frequency count. +// +// freq An array of frequencies, in which frequency[i] gives the frequency of literal i. +// maxBits The maximum number of bits to use for any literal. +func (h *huffmanEncoder) generate(freq []uint16, maxBits int32) { + if h.freqcache == nil { + // Allocate a reusable buffer with the longest possible frequency table. + // Possible lengths are codegenCodeCount, offsetCodeCount and literalCount. + // The largest of these is literalCount, so we allocate for that case. + h.freqcache = make([]literalNode, literalCount+1) + } + list := h.freqcache[:len(freq)+1] + // Number of non-zero literals + count := 0 + // Set list to be the set of all non-zero literals and their frequencies + for i, f := range freq { + if f != 0 { + list[count] = literalNode{uint16(i), f} + count++ + } else { + list[count] = literalNode{} + h.codes[i].len = 0 + } + } + list[len(freq)] = literalNode{} + + list = list[:count] + if count <= 2 { + // Handle the small cases here, because they are awkward for the general case code. With + // two or fewer literals, everything has bit length 1. + for i, node := range list { + // "list" is in order of increasing literal value. + h.codes[node.literal].set(uint16(i), 1) + } + return + } + sortByFreq(list) + + // Get the number of literals for each bit count + bitCount := h.bitCounts(list, maxBits) + // And do the assignment + h.assignEncodingAndSize(bitCount, list) +} + +func atLeastOne(v float32) float32 { + if v < 1 { + return 1 + } + return v +} + +// histogramSize accumulates a histogram of b in h. +// An estimated size in bits is returned. +// Unassigned values are assigned '1' in the histogram. +// len(h) must be >= 256, and h's elements must be all zeroes. +func histogramSize(b []byte, h []uint16, fill bool) (int, int) { + h = h[:256] + for _, t := range b { + h[t]++ + } + invTotal := 1.0 / float32(len(b)) + shannon := float32(0.0) + var extra float32 + if fill { + oneBits := atLeastOne(-mFastLog2(invTotal)) + for i, v := range h[:] { + if v > 0 { + n := float32(v) + shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + } else { + h[i] = 1 + extra += oneBits + } + } + } else { + for _, v := range h[:] { + if v > 0 { + n := float32(v) + shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + } + } + } + + return int(shannon + 0.99), int(extra + 0.99) +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go b/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go new file mode 100644 index 00000000..20778029 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go @@ -0,0 +1,178 @@ +// Copyright 2009 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 flate + +// Sort sorts data. +// It makes one call to data.Len to determine n, and O(n*log(n)) calls to +// data.Less and data.Swap. The sort is not guaranteed to be stable. +func sortByFreq(data []literalNode) { + n := len(data) + quickSortByFreq(data, 0, n, maxDepth(n)) +} + +func quickSortByFreq(data []literalNode, a, b, maxDepth int) { + for b-a > 12 { // Use ShellSort for slices <= 12 elements + if maxDepth == 0 { + heapSort(data, a, b) + return + } + maxDepth-- + mlo, mhi := doPivotByFreq(data, a, b) + // Avoiding recursion on the larger subproblem guarantees + // a stack depth of at most lg(b-a). + if mlo-a < b-mhi { + quickSortByFreq(data, a, mlo, maxDepth) + a = mhi // i.e., quickSortByFreq(data, mhi, b) + } else { + quickSortByFreq(data, mhi, b, maxDepth) + b = mlo // i.e., quickSortByFreq(data, a, mlo) + } + } + if b-a > 1 { + // Do ShellSort pass with gap 6 + // It could be written in this simplified form cause b-a <= 12 + for i := a + 6; i < b; i++ { + if data[i].freq == data[i-6].freq && data[i].literal < data[i-6].literal || data[i].freq < data[i-6].freq { + data[i], data[i-6] = data[i-6], data[i] + } + } + insertionSortByFreq(data, a, b) + } +} + +// siftDownByFreq implements the heap property on data[lo, hi). +// first is an offset into the array where the root of the heap lies. +func siftDownByFreq(data []literalNode, lo, hi, first int) { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && (data[first+child].freq == data[first+child+1].freq && data[first+child].literal < data[first+child+1].literal || data[first+child].freq < data[first+child+1].freq) { + child++ + } + if data[first+root].freq == data[first+child].freq && data[first+root].literal > data[first+child].literal || data[first+root].freq > data[first+child].freq { + return + } + data[first+root], data[first+child] = data[first+child], data[first+root] + root = child + } +} +func doPivotByFreq(data []literalNode, lo, hi int) (midlo, midhi int) { + m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow. + if hi-lo > 40 { + // Tukey's ``Ninther,'' median of three medians of three. + s := (hi - lo) / 8 + medianOfThreeSortByFreq(data, lo, lo+s, lo+2*s) + medianOfThreeSortByFreq(data, m, m-s, m+s) + medianOfThreeSortByFreq(data, hi-1, hi-1-s, hi-1-2*s) + } + medianOfThreeSortByFreq(data, lo, m, hi-1) + + // Invariants are: + // data[lo] = pivot (set up by ChoosePivot) + // data[lo < i < a] < pivot + // data[a <= i < b] <= pivot + // data[b <= i < c] unexamined + // data[c <= i < hi-1] > pivot + // data[hi-1] >= pivot + pivot := lo + a, c := lo+1, hi-1 + + for ; a < c && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { + } + b := a + for { + for ; b < c && (data[pivot].freq == data[b].freq && data[pivot].literal > data[b].literal || data[pivot].freq > data[b].freq); b++ { // data[b] <= pivot + } + for ; b < c && (data[pivot].freq == data[c-1].freq && data[pivot].literal < data[c-1].literal || data[pivot].freq < data[c-1].freq); c-- { // data[c-1] > pivot + } + if b >= c { + break + } + // data[b] > pivot; data[c-1] <= pivot + data[b], data[c-1] = data[c-1], data[b] + b++ + c-- + } + // If hi-c<3 then there are duplicates (by property of median of nine). + // Let's be a bit more conservative, and set border to 5. + protect := hi-c < 5 + if !protect && hi-c < (hi-lo)/4 { + // Lets test some points for equality to pivot + dups := 0 + if data[pivot].freq == data[hi-1].freq && data[pivot].literal > data[hi-1].literal || data[pivot].freq > data[hi-1].freq { // data[hi-1] = pivot + data[c], data[hi-1] = data[hi-1], data[c] + c++ + dups++ + } + if data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq { // data[b-1] = pivot + b-- + dups++ + } + // m-lo = (hi-lo)/2 > 6 + // b-lo > (hi-lo)*3/4-1 > 8 + // ==> m < b ==> data[m] <= pivot + if data[m].freq == data[pivot].freq && data[m].literal > data[pivot].literal || data[m].freq > data[pivot].freq { // data[m] = pivot + data[m], data[b-1] = data[b-1], data[m] + b-- + dups++ + } + // if at least 2 points are equal to pivot, assume skewed distribution + protect = dups > 1 + } + if protect { + // Protect against a lot of duplicates + // Add invariant: + // data[a <= i < b] unexamined + // data[b <= i < c] = pivot + for { + for ; a < b && (data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq); b-- { // data[b] == pivot + } + for ; a < b && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { // data[a] < pivot + } + if a >= b { + break + } + // data[a] == pivot; data[b-1] < pivot + data[a], data[b-1] = data[b-1], data[a] + a++ + b-- + } + } + // Swap pivot into middle + data[pivot], data[b-1] = data[b-1], data[pivot] + return b - 1, c +} + +// Insertion sort +func insertionSortByFreq(data []literalNode, a, b int) { + for i := a + 1; i < b; i++ { + for j := i; j > a && (data[j].freq == data[j-1].freq && data[j].literal < data[j-1].literal || data[j].freq < data[j-1].freq); j-- { + data[j], data[j-1] = data[j-1], data[j] + } + } +} + +// quickSortByFreq, loosely following Bentley and McIlroy, +// ``Engineering a Sort Function,'' SP&E November 1993. + +// medianOfThreeSortByFreq moves the median of the three values data[m0], data[m1], data[m2] into data[m1]. +func medianOfThreeSortByFreq(data []literalNode, m1, m0, m2 int) { + // sort 3 elements + if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq { + data[m1], data[m0] = data[m0], data[m1] + } + // data[m0] <= data[m1] + if data[m2].freq == data[m1].freq && data[m2].literal < data[m1].literal || data[m2].freq < data[m1].freq { + data[m2], data[m1] = data[m1], data[m2] + // data[m0] <= data[m2] && data[m1] < data[m2] + if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq { + data[m1], data[m0] = data[m0], data[m1] + } + } + // now data[m0] <= data[m1] <= data[m2] +} diff --git a/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go b/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go new file mode 100644 index 00000000..93f1aea1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go @@ -0,0 +1,201 @@ +// Copyright 2009 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 flate + +// Sort sorts data. +// It makes one call to data.Len to determine n, and O(n*log(n)) calls to +// data.Less and data.Swap. The sort is not guaranteed to be stable. +func sortByLiteral(data []literalNode) { + n := len(data) + quickSort(data, 0, n, maxDepth(n)) +} + +func quickSort(data []literalNode, a, b, maxDepth int) { + for b-a > 12 { // Use ShellSort for slices <= 12 elements + if maxDepth == 0 { + heapSort(data, a, b) + return + } + maxDepth-- + mlo, mhi := doPivot(data, a, b) + // Avoiding recursion on the larger subproblem guarantees + // a stack depth of at most lg(b-a). + if mlo-a < b-mhi { + quickSort(data, a, mlo, maxDepth) + a = mhi // i.e., quickSort(data, mhi, b) + } else { + quickSort(data, mhi, b, maxDepth) + b = mlo // i.e., quickSort(data, a, mlo) + } + } + if b-a > 1 { + // Do ShellSort pass with gap 6 + // It could be written in this simplified form cause b-a <= 12 + for i := a + 6; i < b; i++ { + if data[i].literal < data[i-6].literal { + data[i], data[i-6] = data[i-6], data[i] + } + } + insertionSort(data, a, b) + } +} +func heapSort(data []literalNode, a, b int) { + first := a + lo := 0 + hi := b - a + + // Build heap with greatest element at top. + for i := (hi - 1) / 2; i >= 0; i-- { + siftDown(data, i, hi, first) + } + + // Pop elements, largest first, into end of data. + for i := hi - 1; i >= 0; i-- { + data[first], data[first+i] = data[first+i], data[first] + siftDown(data, lo, i, first) + } +} + +// siftDown implements the heap property on data[lo, hi). +// first is an offset into the array where the root of the heap lies. +func siftDown(data []literalNode, lo, hi, first int) { + root := lo + for { + child := 2*root + 1 + if child >= hi { + break + } + if child+1 < hi && data[first+child].literal < data[first+child+1].literal { + child++ + } + if data[first+root].literal > data[first+child].literal { + return + } + data[first+root], data[first+child] = data[first+child], data[first+root] + root = child + } +} +func doPivot(data []literalNode, lo, hi int) (midlo, midhi int) { + m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow. + if hi-lo > 40 { + // Tukey's ``Ninther,'' median of three medians of three. + s := (hi - lo) / 8 + medianOfThree(data, lo, lo+s, lo+2*s) + medianOfThree(data, m, m-s, m+s) + medianOfThree(data, hi-1, hi-1-s, hi-1-2*s) + } + medianOfThree(data, lo, m, hi-1) + + // Invariants are: + // data[lo] = pivot (set up by ChoosePivot) + // data[lo < i < a] < pivot + // data[a <= i < b] <= pivot + // data[b <= i < c] unexamined + // data[c <= i < hi-1] > pivot + // data[hi-1] >= pivot + pivot := lo + a, c := lo+1, hi-1 + + for ; a < c && data[a].literal < data[pivot].literal; a++ { + } + b := a + for { + for ; b < c && data[pivot].literal > data[b].literal; b++ { // data[b] <= pivot + } + for ; b < c && data[pivot].literal < data[c-1].literal; c-- { // data[c-1] > pivot + } + if b >= c { + break + } + // data[b] > pivot; data[c-1] <= pivot + data[b], data[c-1] = data[c-1], data[b] + b++ + c-- + } + // If hi-c<3 then there are duplicates (by property of median of nine). + // Let's be a bit more conservative, and set border to 5. + protect := hi-c < 5 + if !protect && hi-c < (hi-lo)/4 { + // Lets test some points for equality to pivot + dups := 0 + if data[pivot].literal > data[hi-1].literal { // data[hi-1] = pivot + data[c], data[hi-1] = data[hi-1], data[c] + c++ + dups++ + } + if data[b-1].literal > data[pivot].literal { // data[b-1] = pivot + b-- + dups++ + } + // m-lo = (hi-lo)/2 > 6 + // b-lo > (hi-lo)*3/4-1 > 8 + // ==> m < b ==> data[m] <= pivot + if data[m].literal > data[pivot].literal { // data[m] = pivot + data[m], data[b-1] = data[b-1], data[m] + b-- + dups++ + } + // if at least 2 points are equal to pivot, assume skewed distribution + protect = dups > 1 + } + if protect { + // Protect against a lot of duplicates + // Add invariant: + // data[a <= i < b] unexamined + // data[b <= i < c] = pivot + for { + for ; a < b && data[b-1].literal > data[pivot].literal; b-- { // data[b] == pivot + } + for ; a < b && data[a].literal < data[pivot].literal; a++ { // data[a] < pivot + } + if a >= b { + break + } + // data[a] == pivot; data[b-1] < pivot + data[a], data[b-1] = data[b-1], data[a] + a++ + b-- + } + } + // Swap pivot into middle + data[pivot], data[b-1] = data[b-1], data[pivot] + return b - 1, c +} + +// Insertion sort +func insertionSort(data []literalNode, a, b int) { + for i := a + 1; i < b; i++ { + for j := i; j > a && data[j].literal < data[j-1].literal; j-- { + data[j], data[j-1] = data[j-1], data[j] + } + } +} + +// maxDepth returns a threshold at which quicksort should switch +// to heapsort. It returns 2*ceil(lg(n+1)). +func maxDepth(n int) int { + var depth int + for i := n; i > 0; i >>= 1 { + depth++ + } + return depth * 2 +} + +// medianOfThree moves the median of the three values data[m0], data[m1], data[m2] into data[m1]. +func medianOfThree(data []literalNode, m1, m0, m2 int) { + // sort 3 elements + if data[m1].literal < data[m0].literal { + data[m1], data[m0] = data[m0], data[m1] + } + // data[m0] <= data[m1] + if data[m2].literal < data[m1].literal { + data[m2], data[m1] = data[m1], data[m2] + // data[m0] <= data[m2] && data[m1] < data[m2] + if data[m1].literal < data[m0].literal { + data[m1], data[m0] = data[m0], data[m1] + } + } + // now data[m0] <= data[m1] <= data[m2] +} diff --git a/vendor/github.com/klauspost/compress/flate/inflate.go b/vendor/github.com/klauspost/compress/flate/inflate.go new file mode 100644 index 00000000..189e9fe0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/inflate.go @@ -0,0 +1,1003 @@ +// Copyright 2009 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 flate implements the DEFLATE compressed data format, described in +// RFC 1951. The gzip and zlib packages implement access to DEFLATE-based file +// formats. +package flate + +import ( + "bufio" + "fmt" + "io" + "math/bits" + "strconv" + "sync" +) + +const ( + maxCodeLen = 16 // max length of Huffman code + maxCodeLenMask = 15 // mask for max length of Huffman code + // The next three numbers come from the RFC section 3.2.7, with the + // additional proviso in section 3.2.5 which implies that distance codes + // 30 and 31 should never occur in compressed data. + maxNumLit = 286 + maxNumDist = 30 + numCodes = 19 // number of codes in Huffman meta-code + + debugDecode = false +) + +// Initialize the fixedHuffmanDecoder only once upon first use. +var fixedOnce sync.Once +var fixedHuffmanDecoder huffmanDecoder + +// A CorruptInputError reports the presence of corrupt input at a given offset. +type CorruptInputError int64 + +func (e CorruptInputError) Error() string { + return "flate: corrupt input before offset " + strconv.FormatInt(int64(e), 10) +} + +// An InternalError reports an error in the flate code itself. +type InternalError string + +func (e InternalError) Error() string { return "flate: internal error: " + string(e) } + +// A ReadError reports an error encountered while reading input. +// +// Deprecated: No longer returned. +type ReadError struct { + Offset int64 // byte offset where error occurred + Err error // error returned by underlying Read +} + +func (e *ReadError) Error() string { + return "flate: read error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error() +} + +// A WriteError reports an error encountered while writing output. +// +// Deprecated: No longer returned. +type WriteError struct { + Offset int64 // byte offset where error occurred + Err error // error returned by underlying Write +} + +func (e *WriteError) Error() string { + return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error() +} + +// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to +// to switch to a new underlying Reader. This permits reusing a ReadCloser +// instead of allocating a new one. +type Resetter interface { + // Reset discards any buffered data and resets the Resetter as if it was + // newly initialized with the given reader. + Reset(r io.Reader, dict []byte) error +} + +// The data structure for decoding Huffman tables is based on that of +// zlib. There is a lookup table of a fixed bit width (huffmanChunkBits), +// For codes smaller than the table width, there are multiple entries +// (each combination of trailing bits has the same value). For codes +// larger than the table width, the table contains a link to an overflow +// table. The width of each entry in the link table is the maximum code +// size minus the chunk width. +// +// Note that you can do a lookup in the table even without all bits +// filled. Since the extra bits are zero, and the DEFLATE Huffman codes +// have the property that shorter codes come before longer ones, the +// bit length estimate in the result is a lower bound on the actual +// number of bits. +// +// See the following: +// http://www.gzip.org/algorithm.txt + +// chunk & 15 is number of bits +// chunk >> 4 is value, including table link + +const ( + huffmanChunkBits = 9 + huffmanNumChunks = 1 << huffmanChunkBits + huffmanCountMask = 15 + huffmanValueShift = 4 +) + +type huffmanDecoder struct { + maxRead int // the maximum number of bits we can read and not overread + chunks *[huffmanNumChunks]uint16 // chunks as described above + links [][]uint16 // overflow links + linkMask uint32 // mask the width of the link table +} + +// Initialize Huffman decoding tables from array of code lengths. +// Following this function, h is guaranteed to be initialized into a complete +// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a +// degenerate case where the tree has only a single symbol with length 1. Empty +// trees are permitted. +func (h *huffmanDecoder) init(lengths []int) bool { + // Sanity enables additional runtime tests during Huffman + // table construction. It's intended to be used during + // development to supplement the currently ad-hoc unit tests. + const sanity = false + + if h.chunks == nil { + h.chunks = &[huffmanNumChunks]uint16{} + } + if h.maxRead != 0 { + *h = huffmanDecoder{chunks: h.chunks, links: h.links} + } + + // Count number of codes of each length, + // compute maxRead and max length. + var count [maxCodeLen]int + var min, max int + for _, n := range lengths { + if n == 0 { + continue + } + if min == 0 || n < min { + min = n + } + if n > max { + max = n + } + count[n&maxCodeLenMask]++ + } + + // Empty tree. The decompressor.huffSym function will fail later if the tree + // is used. Technically, an empty tree is only valid for the HDIST tree and + // not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree + // is guaranteed to fail since it will attempt to use the tree to decode the + // codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is + // guaranteed to fail later since the compressed data section must be + // composed of at least one symbol (the end-of-block marker). + if max == 0 { + return true + } + + code := 0 + var nextcode [maxCodeLen]int + for i := min; i <= max; i++ { + code <<= 1 + nextcode[i&maxCodeLenMask] = code + code += count[i&maxCodeLenMask] + } + + // Check that the coding is complete (i.e., that we've + // assigned all 2-to-the-max possible bit sequences). + // Exception: To be compatible with zlib, we also need to + // accept degenerate single-code codings. See also + // TestDegenerateHuffmanCoding. + if code != 1< huffmanChunkBits { + numLinks := 1 << (uint(max) - huffmanChunkBits) + h.linkMask = uint32(numLinks - 1) + + // create link tables + link := nextcode[huffmanChunkBits+1] >> 1 + if cap(h.links) < huffmanNumChunks-link { + h.links = make([][]uint16, huffmanNumChunks-link) + } else { + h.links = h.links[:huffmanNumChunks-link] + } + for j := uint(link); j < huffmanNumChunks; j++ { + reverse := int(bits.Reverse16(uint16(j))) + reverse >>= uint(16 - huffmanChunkBits) + off := j - uint(link) + if sanity && h.chunks[reverse] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[reverse] = uint16(off<>= uint(16 - n) + if n <= huffmanChunkBits { + for off := reverse; off < len(h.chunks); off += 1 << uint(n) { + // We should never need to overwrite + // an existing chunk. Also, 0 is + // never a valid chunk, because the + // lower 4 "count" bits should be + // between 1 and 15. + if sanity && h.chunks[off] != 0 { + panic("impossible: overwriting existing chunk") + } + h.chunks[off] = chunk + } + } else { + j := reverse & (huffmanNumChunks - 1) + if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 { + // Longer codes should have been + // associated with a link table above. + panic("impossible: not an indirect chunk") + } + value := h.chunks[j] >> huffmanValueShift + linktab := h.links[value] + reverse >>= huffmanChunkBits + for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) { + if sanity && linktab[off] != 0 { + panic("impossible: overwriting existing chunk") + } + linktab[off] = chunk + } + } + } + + if sanity { + // Above we've sanity checked that we never overwrote + // an existing entry. Here we additionally check that + // we filled the tables completely. + for i, chunk := range h.chunks { + if chunk == 0 { + // As an exception, in the degenerate + // single-code case, we allow odd + // chunks to be missing. + if code == 1 && i%2 == 1 { + continue + } + panic("impossible: missing chunk") + } + } + for _, linktab := range h.links { + for _, chunk := range linktab { + if chunk == 0 { + panic("impossible: missing chunk") + } + } + } + } + + return true +} + +// The actual read interface needed by NewReader. +// If the passed in io.Reader does not also have ReadByte, +// the NewReader will introduce its own buffering. +type Reader interface { + io.Reader + io.ByteReader +} + +// Decompress state. +type decompressor struct { + // Input source. + r Reader + roffset int64 + + // Huffman decoders for literal/length, distance. + h1, h2 huffmanDecoder + + // Length arrays used to define Huffman codes. + bits *[maxNumLit + maxNumDist]int + codebits *[numCodes]int + + // Output history, buffer. + dict dictDecoder + + // Next step in the decompression, + // and decompression state. + step func(*decompressor) + stepState int + err error + toRead []byte + hl, hd *huffmanDecoder + copyLen int + copyDist int + + // Temporary buffer (avoids repeated allocation). + buf [4]byte + + // Input bits, in top of b. + b uint32 + + nb uint + final bool +} + +func (f *decompressor) nextBlock() { + for f.nb < 1+2 { + if f.err = f.moreBits(); f.err != nil { + return + } + } + f.final = f.b&1 == 1 + f.b >>= 1 + typ := f.b & 3 + f.b >>= 2 + f.nb -= 1 + 2 + switch typ { + case 0: + f.dataBlock() + case 1: + // compressed, fixed Huffman tables + f.hl = &fixedHuffmanDecoder + f.hd = nil + f.huffmanBlockDecoder()() + case 2: + // compressed, dynamic Huffman tables + if f.err = f.readHuffman(); f.err != nil { + break + } + f.hl = &f.h1 + f.hd = &f.h2 + f.huffmanBlockDecoder()() + default: + // 3 is reserved. + if debugDecode { + fmt.Println("reserved data block encountered") + } + f.err = CorruptInputError(f.roffset) + } +} + +func (f *decompressor) Read(b []byte) (int, error) { + for { + if len(f.toRead) > 0 { + n := copy(b, f.toRead) + f.toRead = f.toRead[n:] + if len(f.toRead) == 0 { + return n, f.err + } + return n, nil + } + if f.err != nil { + return 0, f.err + } + f.step(f) + if f.err != nil && len(f.toRead) == 0 { + f.toRead = f.dict.readFlush() // Flush what's left in case of error + } + } +} + +// Support the io.WriteTo interface for io.Copy and friends. +func (f *decompressor) WriteTo(w io.Writer) (int64, error) { + total := int64(0) + flushed := false + for { + if len(f.toRead) > 0 { + n, err := w.Write(f.toRead) + total += int64(n) + if err != nil { + f.err = err + return total, err + } + if n != len(f.toRead) { + return total, io.ErrShortWrite + } + f.toRead = f.toRead[:0] + } + if f.err != nil && flushed { + if f.err == io.EOF { + return total, nil + } + return total, f.err + } + if f.err == nil { + f.step(f) + } + if len(f.toRead) == 0 && f.err != nil && !flushed { + f.toRead = f.dict.readFlush() // Flush what's left in case of error + flushed = true + } + } +} + +func (f *decompressor) Close() error { + if f.err == io.EOF { + return nil + } + return f.err +} + +// RFC 1951 section 3.2.7. +// Compression with dynamic Huffman codes + +var codeOrder = [...]int{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} + +func (f *decompressor) readHuffman() error { + // HLIT[5], HDIST[5], HCLEN[4]. + for f.nb < 5+5+4 { + if err := f.moreBits(); err != nil { + return err + } + } + nlit := int(f.b&0x1F) + 257 + if nlit > maxNumLit { + if debugDecode { + fmt.Println("nlit > maxNumLit", nlit) + } + return CorruptInputError(f.roffset) + } + f.b >>= 5 + ndist := int(f.b&0x1F) + 1 + if ndist > maxNumDist { + if debugDecode { + fmt.Println("ndist > maxNumDist", ndist) + } + return CorruptInputError(f.roffset) + } + f.b >>= 5 + nclen := int(f.b&0xF) + 4 + // numCodes is 19, so nclen is always valid. + f.b >>= 4 + f.nb -= 5 + 5 + 4 + + // (HCLEN+4)*3 bits: code lengths in the magic codeOrder order. + for i := 0; i < nclen; i++ { + for f.nb < 3 { + if err := f.moreBits(); err != nil { + return err + } + } + f.codebits[codeOrder[i]] = int(f.b & 0x7) + f.b >>= 3 + f.nb -= 3 + } + for i := nclen; i < len(codeOrder); i++ { + f.codebits[codeOrder[i]] = 0 + } + if !f.h1.init(f.codebits[0:]) { + if debugDecode { + fmt.Println("init codebits failed") + } + return CorruptInputError(f.roffset) + } + + // HLIT + 257 code lengths, HDIST + 1 code lengths, + // using the code length Huffman code. + for i, n := 0, nlit+ndist; i < n; { + x, err := f.huffSym(&f.h1) + if err != nil { + return err + } + if x < 16 { + // Actual length. + f.bits[i] = x + i++ + continue + } + // Repeat previous length or zero. + var rep int + var nb uint + var b int + switch x { + default: + return InternalError("unexpected length code") + case 16: + rep = 3 + nb = 2 + if i == 0 { + if debugDecode { + fmt.Println("i==0") + } + return CorruptInputError(f.roffset) + } + b = f.bits[i-1] + case 17: + rep = 3 + nb = 3 + b = 0 + case 18: + rep = 11 + nb = 7 + b = 0 + } + for f.nb < nb { + if err := f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits:", err) + } + return err + } + } + rep += int(f.b & uint32(1<<(nb®SizeMaskUint32)-1)) + f.b >>= nb & regSizeMaskUint32 + f.nb -= nb + if i+rep > n { + if debugDecode { + fmt.Println("i+rep > n", i, rep, n) + } + return CorruptInputError(f.roffset) + } + for j := 0; j < rep; j++ { + f.bits[i] = b + i++ + } + } + + if !f.h1.init(f.bits[0:nlit]) || !f.h2.init(f.bits[nlit:nlit+ndist]) { + if debugDecode { + fmt.Println("init2 failed") + } + return CorruptInputError(f.roffset) + } + + // As an optimization, we can initialize the maxRead bits to read at a time + // for the HLIT tree to the length of the EOB marker since we know that + // every block must terminate with one. This preserves the property that + // we never read any extra bytes after the end of the DEFLATE stream. + if f.h1.maxRead < f.bits[endBlockMarker] { + f.h1.maxRead = f.bits[endBlockMarker] + } + if !f.final { + // If not the final block, the smallest block possible is + // a predefined table, BTYPE=01, with a single EOB marker. + // This will take up 3 + 7 bits. + f.h1.maxRead += 10 + } + + return nil +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBlockGeneric() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := f.r.ReadByte() + if err != nil { + f.b = b + f.nb = nb + f.err = noEOF(err) + return + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := f.hl.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var n uint // number of bits extra + var length int + var err error + switch { + case v < 256: + f.dict.writeByte(byte(v)) + if f.dict.availWrite() == 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBlockGeneric + f.stepState = stateInit + return + } + goto readLiteral + case v == 256: + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + } + length += int(f.b & uint32(1<<(n®SizeMaskUint32)-1)) + f.b >>= n & regSizeMaskUint32 + f.nb -= n + } + + var dist uint32 + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + } + dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3))) + f.b >>= 5 + f.nb -= 5 + } else { + sym, err := f.huffSym(f.hd) + if err != nil { + if debugDecode { + fmt.Println("huffsym:", err) + } + f.err = err + return + } + dist = uint32(sym) + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for f.nb < nb { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + f.nb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + default: + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(f.dict.histSize()) { + if debugDecode { + fmt.Println("dist > f.dict.histSize():", dist, f.dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := f.dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = f.dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBlockGeneric // We need to continue this work + f.stepState = stateDict + return + } + goto readLiteral + } +} + +// Copy a single uncompressed data block from input to output. +func (f *decompressor) dataBlock() { + // Uncompressed. + // Discard current half-byte. + left := (f.nb) & 7 + f.nb -= left + f.b >>= left + + offBytes := f.nb >> 3 + // Unfilled values will be overwritten. + f.buf[0] = uint8(f.b) + f.buf[1] = uint8(f.b >> 8) + f.buf[2] = uint8(f.b >> 16) + f.buf[3] = uint8(f.b >> 24) + + f.roffset += int64(offBytes) + f.nb, f.b = 0, 0 + + // Length then ones-complement of length. + nr, err := io.ReadFull(f.r, f.buf[offBytes:4]) + f.roffset += int64(nr) + if err != nil { + f.err = noEOF(err) + return + } + n := uint16(f.buf[0]) | uint16(f.buf[1])<<8 + nn := uint16(f.buf[2]) | uint16(f.buf[3])<<8 + if nn != ^n { + if debugDecode { + ncomp := ^n + fmt.Println("uint16(nn) != uint16(^n)", nn, ncomp) + } + f.err = CorruptInputError(f.roffset) + return + } + + if n == 0 { + f.toRead = f.dict.readFlush() + f.finishBlock() + return + } + + f.copyLen = int(n) + f.copyData() +} + +// copyData copies f.copyLen bytes from the underlying reader into f.hist. +// It pauses for reads when f.hist is full. +func (f *decompressor) copyData() { + buf := f.dict.writeSlice() + if len(buf) > f.copyLen { + buf = buf[:f.copyLen] + } + + cnt, err := io.ReadFull(f.r, buf) + f.roffset += int64(cnt) + f.copyLen -= cnt + f.dict.writeMark(cnt) + if err != nil { + f.err = noEOF(err) + return + } + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).copyData + return + } + f.finishBlock() +} + +func (f *decompressor) finishBlock() { + if f.final { + if f.dict.availRead() > 0 { + f.toRead = f.dict.readFlush() + } + f.err = io.EOF + } + f.step = (*decompressor).nextBlock +} + +// noEOF returns err, unless err == io.EOF, in which case it returns io.ErrUnexpectedEOF. +func noEOF(e error) error { + if e == io.EOF { + return io.ErrUnexpectedEOF + } + return e +} + +func (f *decompressor) moreBits() error { + c, err := f.r.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << (f.nb & regSizeMaskUint32) + f.nb += 8 + return nil +} + +// Read the next Huffman-encoded symbol from f according to h. +func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(h.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := f.r.ReadByte() + if err != nil { + f.b = b + f.nb = nb + return 0, noEOF(err) + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := h.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return 0, f.err + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + return int(chunk >> huffmanValueShift), nil + } + } +} + +func makeReader(r io.Reader) Reader { + if rr, ok := r.(Reader); ok { + return rr + } + return bufio.NewReader(r) +} + +func fixedHuffmanDecoderInit() { + fixedOnce.Do(func() { + // These come from the RFC section 3.2.6. + var bits [288]int + for i := 0; i < 144; i++ { + bits[i] = 8 + } + for i := 144; i < 256; i++ { + bits[i] = 9 + } + for i := 256; i < 280; i++ { + bits[i] = 7 + } + for i := 280; i < 288; i++ { + bits[i] = 8 + } + fixedHuffmanDecoder.init(bits[:]) + }) +} + +func (f *decompressor) Reset(r io.Reader, dict []byte) error { + *f = decompressor{ + r: makeReader(r), + bits: f.bits, + codebits: f.codebits, + h1: f.h1, + h2: f.h2, + dict: f.dict, + step: (*decompressor).nextBlock, + } + f.dict.init(maxMatchOffset, dict) + return nil +} + +// NewReader returns a new ReadCloser that can be used +// to read the uncompressed version of r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. +// It is the caller's responsibility to call Close on the ReadCloser +// when finished reading. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReader(r io.Reader) io.ReadCloser { + fixedHuffmanDecoderInit() + + var f decompressor + f.r = makeReader(r) + f.bits = new([maxNumLit + maxNumDist]int) + f.codebits = new([numCodes]int) + f.step = (*decompressor).nextBlock + f.dict.init(maxMatchOffset, nil) + return &f +} + +// NewReaderDict is like NewReader but initializes the reader +// with a preset dictionary. The returned Reader behaves as if +// the uncompressed data stream started with the given dictionary, +// which has already been read. NewReaderDict is typically used +// to read data compressed by NewWriterDict. +// +// The ReadCloser returned by NewReader also implements Resetter. +func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser { + fixedHuffmanDecoderInit() + + var f decompressor + f.r = makeReader(r) + f.bits = new([maxNumLit + maxNumDist]int) + f.codebits = new([numCodes]int) + f.step = (*decompressor).nextBlock + f.dict.init(maxMatchOffset, dict) + return &f +} diff --git a/vendor/github.com/klauspost/compress/flate/inflate_gen.go b/vendor/github.com/klauspost/compress/flate/inflate_gen.go new file mode 100644 index 00000000..9a92a1b3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/inflate_gen.go @@ -0,0 +1,930 @@ +// Code generated by go generate gen_inflate.go. DO NOT EDIT. + +package flate + +import ( + "bufio" + "bytes" + "fmt" + "math/bits" + "strings" +) + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBytesBuffer() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*bytes.Buffer) + moreBits := func() error { + c, err := fr.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << f.nb + f.nb += 8 + return nil + } + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := fr.ReadByte() + if err != nil { + f.b = b + f.nb = nb + f.err = noEOF(err) + return + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := f.hl.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var n uint // number of bits extra + var length int + var err error + switch { + case v < 256: + f.dict.writeByte(byte(v)) + if f.dict.availWrite() == 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBytesBuffer + f.stepState = stateInit + return + } + goto readLiteral + case v == 256: + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + } + length += int(f.b & uint32(1<<(n®SizeMaskUint32)-1)) + f.b >>= n & regSizeMaskUint32 + f.nb -= n + } + + var dist uint32 + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + } + dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3))) + f.b >>= 5 + f.nb -= 5 + } else { + sym, err := f.huffSym(f.hd) + if err != nil { + if debugDecode { + fmt.Println("huffsym:", err) + } + f.err = err + return + } + dist = uint32(sym) + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for f.nb < nb { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + f.nb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + default: + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(f.dict.histSize()) { + if debugDecode { + fmt.Println("dist > f.dict.histSize():", dist, f.dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := f.dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = f.dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBytesBuffer // We need to continue this work + f.stepState = stateDict + return + } + goto readLiteral + } +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBytesReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*bytes.Reader) + moreBits := func() error { + c, err := fr.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << f.nb + f.nb += 8 + return nil + } + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := fr.ReadByte() + if err != nil { + f.b = b + f.nb = nb + f.err = noEOF(err) + return + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := f.hl.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var n uint // number of bits extra + var length int + var err error + switch { + case v < 256: + f.dict.writeByte(byte(v)) + if f.dict.availWrite() == 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBytesReader + f.stepState = stateInit + return + } + goto readLiteral + case v == 256: + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + } + length += int(f.b & uint32(1<<(n®SizeMaskUint32)-1)) + f.b >>= n & regSizeMaskUint32 + f.nb -= n + } + + var dist uint32 + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + } + dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3))) + f.b >>= 5 + f.nb -= 5 + } else { + sym, err := f.huffSym(f.hd) + if err != nil { + if debugDecode { + fmt.Println("huffsym:", err) + } + f.err = err + return + } + dist = uint32(sym) + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for f.nb < nb { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + f.nb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + default: + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(f.dict.histSize()) { + if debugDecode { + fmt.Println("dist > f.dict.histSize():", dist, f.dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := f.dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = f.dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBytesReader // We need to continue this work + f.stepState = stateDict + return + } + goto readLiteral + } +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanBufioReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*bufio.Reader) + moreBits := func() error { + c, err := fr.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << f.nb + f.nb += 8 + return nil + } + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := fr.ReadByte() + if err != nil { + f.b = b + f.nb = nb + f.err = noEOF(err) + return + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := f.hl.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var n uint // number of bits extra + var length int + var err error + switch { + case v < 256: + f.dict.writeByte(byte(v)) + if f.dict.availWrite() == 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBufioReader + f.stepState = stateInit + return + } + goto readLiteral + case v == 256: + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + } + length += int(f.b & uint32(1<<(n®SizeMaskUint32)-1)) + f.b >>= n & regSizeMaskUint32 + f.nb -= n + } + + var dist uint32 + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + } + dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3))) + f.b >>= 5 + f.nb -= 5 + } else { + sym, err := f.huffSym(f.hd) + if err != nil { + if debugDecode { + fmt.Println("huffsym:", err) + } + f.err = err + return + } + dist = uint32(sym) + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for f.nb < nb { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + f.nb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + default: + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(f.dict.histSize()) { + if debugDecode { + fmt.Println("dist > f.dict.histSize():", dist, f.dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := f.dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = f.dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanBufioReader // We need to continue this work + f.stepState = stateDict + return + } + goto readLiteral + } +} + +// Decode a single Huffman block from f. +// hl and hd are the Huffman states for the lit/length values +// and the distance values, respectively. If hd == nil, using the +// fixed distance encoding associated with fixed Huffman blocks. +func (f *decompressor) huffmanStringsReader() { + const ( + stateInit = iota // Zero value must be stateInit + stateDict + ) + fr := f.r.(*strings.Reader) + moreBits := func() error { + c, err := fr.ReadByte() + if err != nil { + return noEOF(err) + } + f.roffset++ + f.b |= uint32(c) << f.nb + f.nb += 8 + return nil + } + + switch f.stepState { + case stateInit: + goto readLiteral + case stateDict: + goto copyHistory + } + +readLiteral: + // Read literal and/or (length, distance) according to RFC section 3.2.3. + { + var v int + { + // Inlined v, err := f.huffSym(f.hl) + // Since a huffmanDecoder can be empty or be composed of a degenerate tree + // with single element, huffSym must error on these two edge cases. In both + // cases, the chunks slice will be 0 for the invalid sequence, leading it + // satisfy the n == 0 check below. + n := uint(f.hl.maxRead) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b + for { + for nb < n { + c, err := fr.ReadByte() + if err != nil { + f.b = b + f.nb = nb + f.err = noEOF(err) + return + } + f.roffset++ + b |= uint32(c) << (nb & regSizeMaskUint32) + nb += 8 + } + chunk := f.hl.chunks[b&(huffmanNumChunks-1)] + n = uint(chunk & huffmanCountMask) + if n > huffmanChunkBits { + chunk = f.hl.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&f.hl.linkMask] + n = uint(chunk & huffmanCountMask) + } + if n <= nb { + if n == 0 { + f.b = b + f.nb = nb + if debugDecode { + fmt.Println("huffsym: n==0") + } + f.err = CorruptInputError(f.roffset) + return + } + f.b = b >> (n & regSizeMaskUint32) + f.nb = nb - n + v = int(chunk >> huffmanValueShift) + break + } + } + } + + var n uint // number of bits extra + var length int + var err error + switch { + case v < 256: + f.dict.writeByte(byte(v)) + if f.dict.availWrite() == 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanStringsReader + f.stepState = stateInit + return + } + goto readLiteral + case v == 256: + f.finishBlock() + return + // otherwise, reference to older data + case v < 265: + length = v - (257 - 3) + n = 0 + case v < 269: + length = v*2 - (265*2 - 11) + n = 1 + case v < 273: + length = v*4 - (269*4 - 19) + n = 2 + case v < 277: + length = v*8 - (273*8 - 35) + n = 3 + case v < 281: + length = v*16 - (277*16 - 67) + n = 4 + case v < 285: + length = v*32 - (281*32 - 131) + n = 5 + case v < maxNumLit: + length = 258 + n = 0 + default: + if debugDecode { + fmt.Println(v, ">= maxNumLit") + } + f.err = CorruptInputError(f.roffset) + return + } + if n > 0 { + for f.nb < n { + if err = moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits n>0:", err) + } + f.err = err + return + } + } + length += int(f.b & uint32(1<<(n®SizeMaskUint32)-1)) + f.b >>= n & regSizeMaskUint32 + f.nb -= n + } + + var dist uint32 + if f.hd == nil { + for f.nb < 5 { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb<5:", err) + } + f.err = err + return + } + } + dist = uint32(bits.Reverse8(uint8(f.b & 0x1F << 3))) + f.b >>= 5 + f.nb -= 5 + } else { + sym, err := f.huffSym(f.hd) + if err != nil { + if debugDecode { + fmt.Println("huffsym:", err) + } + f.err = err + return + } + dist = uint32(sym) + } + + switch { + case dist < 4: + dist++ + case dist < maxNumDist: + nb := uint(dist-2) >> 1 + // have 1 bit in bottom of dist, need nb more. + extra := (dist & 1) << (nb & regSizeMaskUint32) + for f.nb < nb { + if err = f.moreBits(); err != nil { + if debugDecode { + fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + f.nb -= nb + dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + default: + if debugDecode { + fmt.Println("dist too big:", dist, maxNumDist) + } + f.err = CorruptInputError(f.roffset) + return + } + + // No check on length; encoding can be prescient. + if dist > uint32(f.dict.histSize()) { + if debugDecode { + fmt.Println("dist > f.dict.histSize():", dist, f.dict.histSize()) + } + f.err = CorruptInputError(f.roffset) + return + } + + f.copyLen, f.copyDist = length, int(dist) + goto copyHistory + } + +copyHistory: + // Perform a backwards copy according to RFC section 3.2.3. + { + cnt := f.dict.tryWriteCopy(f.copyDist, f.copyLen) + if cnt == 0 { + cnt = f.dict.writeCopy(f.copyDist, f.copyLen) + } + f.copyLen -= cnt + + if f.dict.availWrite() == 0 || f.copyLen > 0 { + f.toRead = f.dict.readFlush() + f.step = (*decompressor).huffmanStringsReader // We need to continue this work + f.stepState = stateDict + return + } + goto readLiteral + } +} + +func (f *decompressor) huffmanBlockDecoder() func() { + switch f.r.(type) { + case *bytes.Buffer: + return f.huffmanBytesBuffer + case *bytes.Reader: + return f.huffmanBytesReader + case *bufio.Reader: + return f.huffmanBufioReader + case *strings.Reader: + return f.huffmanStringsReader + default: + return f.huffmanBlockGeneric + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level1.go b/vendor/github.com/klauspost/compress/flate/level1.go new file mode 100644 index 00000000..1e5eea39 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level1.go @@ -0,0 +1,179 @@ +package flate + +import "fmt" + +// fastGen maintains the table for matches, +// and the previous byte block for level 2. +// This is the generic implementation. +type fastEncL1 struct { + fastGen + table [tableSize]tableEntry +} + +// EncodeL1 uses a similar algorithm to level 1 +func (e *fastEncL1) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load3232(src, s) + + for { + const skipLog = 5 + const doEvery = 2 + + nextS := s + var candidate tableEntry + for { + nextHash := hash(cv) + candidate = e.table[nextHash] + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + + now := load6432(src, nextS) + e.table[nextHash] = tableEntry{offset: s + e.cur} + nextHash = hash(uint32(now)) + + offset := s - (candidate.offset - e.cur) + if offset < maxMatchOffset && cv == load3232(src, candidate.offset-e.cur) { + e.table[nextHash] = tableEntry{offset: nextS + e.cur} + break + } + + // Do one right away... + cv = uint32(now) + s = nextS + nextS++ + candidate = e.table[nextHash] + now >>= 8 + e.table[nextHash] = tableEntry{offset: s + e.cur} + + offset = s - (candidate.offset - e.cur) + if offset < maxMatchOffset && cv == load3232(src, candidate.offset-e.cur) { + e.table[nextHash] = tableEntry{offset: nextS + e.cur} + break + } + cv = uint32(now) + s = nextS + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + t := candidate.offset - e.cur + l := e.matchlenLong(s+4, t+4, src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + + // Save the match found + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + if s >= sLimit { + // Index first pair after match end. + if int(s+l+4) < len(src) { + cv := load3232(src, s) + e.table[hash(cv)] = tableEntry{offset: s + e.cur} + } + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load6432(src, s-2) + o := e.cur + s - 2 + prevHash := hash(uint32(x)) + e.table[prevHash] = tableEntry{offset: o} + x >>= 16 + currHash := hash(uint32(x)) + candidate = e.table[currHash] + e.table[currHash] = tableEntry{offset: o + 2} + + offset := s - (candidate.offset - e.cur) + if offset > maxMatchOffset || uint32(x) != load3232(src, candidate.offset-e.cur) { + cv = uint32(x >> 8) + s++ + break + } + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level2.go b/vendor/github.com/klauspost/compress/flate/level2.go new file mode 100644 index 00000000..5b986a19 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level2.go @@ -0,0 +1,205 @@ +package flate + +import "fmt" + +// fastGen maintains the table for matches, +// and the previous byte block for level 2. +// This is the generic implementation. +type fastEncL2 struct { + fastGen + table [bTableSize]tableEntry +} + +// EncodeL2 uses a similar algorithm to level 1, but is capable +// of matching across blocks giving better compression at a small slowdown. +func (e *fastEncL2) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load3232(src, s) + for { + // When should we start skipping if we haven't found matches in a long while. + const skipLog = 5 + const doEvery = 2 + + nextS := s + var candidate tableEntry + for { + nextHash := hash4u(cv, bTableBits) + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + candidate = e.table[nextHash] + now := load6432(src, nextS) + e.table[nextHash] = tableEntry{offset: s + e.cur} + nextHash = hash4u(uint32(now), bTableBits) + + offset := s - (candidate.offset - e.cur) + if offset < maxMatchOffset && cv == load3232(src, candidate.offset-e.cur) { + e.table[nextHash] = tableEntry{offset: nextS + e.cur} + break + } + + // Do one right away... + cv = uint32(now) + s = nextS + nextS++ + candidate = e.table[nextHash] + now >>= 8 + e.table[nextHash] = tableEntry{offset: s + e.cur} + + offset = s - (candidate.offset - e.cur) + if offset < maxMatchOffset && cv == load3232(src, candidate.offset-e.cur) { + break + } + cv = uint32(now) + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + t := candidate.offset - e.cur + l := e.matchlenLong(s+4, t+4, src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + // Index first pair after match end. + if int(s+l+4) < len(src) { + cv := load3232(src, s) + e.table[hash4u(cv, bTableBits)] = tableEntry{offset: s + e.cur} + } + goto emitRemainder + } + + // Store every second hash in-between, but offset by 1. + for i := s - l + 2; i < s-5; i += 7 { + x := load6432(src, int32(i)) + nextHash := hash4u(uint32(x), bTableBits) + e.table[nextHash] = tableEntry{offset: e.cur + i} + // Skip one + x >>= 16 + nextHash = hash4u(uint32(x), bTableBits) + e.table[nextHash] = tableEntry{offset: e.cur + i + 2} + // Skip one + x >>= 16 + nextHash = hash4u(uint32(x), bTableBits) + e.table[nextHash] = tableEntry{offset: e.cur + i + 4} + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 to s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load6432(src, s-2) + o := e.cur + s - 2 + prevHash := hash4u(uint32(x), bTableBits) + prevHash2 := hash4u(uint32(x>>8), bTableBits) + e.table[prevHash] = tableEntry{offset: o} + e.table[prevHash2] = tableEntry{offset: o + 1} + currHash := hash4u(uint32(x>>16), bTableBits) + candidate = e.table[currHash] + e.table[currHash] = tableEntry{offset: o + 2} + + offset := s - (candidate.offset - e.cur) + if offset > maxMatchOffset || uint32(x>>16) != load3232(src, candidate.offset-e.cur) { + cv = uint32(x >> 24) + s++ + break + } + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level3.go b/vendor/github.com/klauspost/compress/flate/level3.go new file mode 100644 index 00000000..c22b4244 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level3.go @@ -0,0 +1,229 @@ +package flate + +import "fmt" + +// fastEncL3 +type fastEncL3 struct { + fastGen + table [tableSize]tableEntryPrev +} + +// Encode uses a similar algorithm to level 2, will check up to two candidates. +func (e *fastEncL3) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 8 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + } + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + e.table[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // Skip if too small. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load3232(src, s) + for { + const skipLog = 6 + nextS := s + var candidate tableEntry + for { + nextHash := hash(cv) + s = nextS + nextS = s + 1 + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + candidates := e.table[nextHash] + now := load3232(src, nextS) + + // Safe offset distance until s + 4... + minOffset := e.cur + s - (maxMatchOffset - 4) + e.table[nextHash] = tableEntryPrev{Prev: candidates.Cur, Cur: tableEntry{offset: s + e.cur}} + + // Check both candidates + candidate = candidates.Cur + if candidate.offset < minOffset { + cv = now + // Previous will also be invalid, we have nothing. + continue + } + + if cv == load3232(src, candidate.offset-e.cur) { + if candidates.Prev.offset < minOffset || cv != load3232(src, candidates.Prev.offset-e.cur) { + break + } + // Both match and are valid, pick longest. + offset := s - (candidate.offset - e.cur) + o2 := s - (candidates.Prev.offset - e.cur) + l1, l2 := matchLen(src[s+4:], src[s-offset+4:]), matchLen(src[s+4:], src[s-o2+4:]) + if l2 > l1 { + candidate = candidates.Prev + } + break + } else { + // We only check if value mismatches. + // Offset will always be invalid in other cases. + candidate = candidates.Prev + if candidate.offset > minOffset && cv == load3232(src, candidate.offset-e.cur) { + break + } + } + cv = now + } + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + // + t := candidate.offset - e.cur + l := e.matchlenLong(s+4, t+4, src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + t += l + // Index first pair after match end. + if int(t+4) < len(src) && t > 0 { + cv := load3232(src, t) + nextHash := hash(cv) + e.table[nextHash] = tableEntryPrev{ + Prev: e.table[nextHash].Cur, + Cur: tableEntry{offset: e.cur + t}, + } + } + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-3 to s. + x := load6432(src, s-3) + prevHash := hash(uint32(x)) + e.table[prevHash] = tableEntryPrev{ + Prev: e.table[prevHash].Cur, + Cur: tableEntry{offset: e.cur + s - 3}, + } + x >>= 8 + prevHash = hash(uint32(x)) + + e.table[prevHash] = tableEntryPrev{ + Prev: e.table[prevHash].Cur, + Cur: tableEntry{offset: e.cur + s - 2}, + } + x >>= 8 + prevHash = hash(uint32(x)) + + e.table[prevHash] = tableEntryPrev{ + Prev: e.table[prevHash].Cur, + Cur: tableEntry{offset: e.cur + s - 1}, + } + x >>= 8 + currHash := hash(uint32(x)) + candidates := e.table[currHash] + cv = uint32(x) + e.table[currHash] = tableEntryPrev{ + Prev: candidates.Cur, + Cur: tableEntry{offset: s + e.cur}, + } + + // Check both candidates + candidate = candidates.Cur + minOffset := e.cur + s - (maxMatchOffset - 4) + + if candidate.offset > minOffset && cv != load3232(src, candidate.offset-e.cur) { + // We only check if value mismatches. + // Offset will always be invalid in other cases. + candidate = candidates.Prev + if candidate.offset > minOffset && cv == load3232(src, candidate.offset-e.cur) { + offset := s - (candidate.offset - e.cur) + if offset <= maxMatchOffset { + continue + } + } + } + cv = uint32(x >> 8) + s++ + break + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level4.go b/vendor/github.com/klauspost/compress/flate/level4.go new file mode 100644 index 00000000..e62f0c02 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level4.go @@ -0,0 +1,212 @@ +package flate + +import "fmt" + +type fastEncL4 struct { + fastGen + table [tableSize]tableEntry + bTable [tableSize]tableEntry +} + +func (e *fastEncL4) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntry{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.bTable[i].offset = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + const skipLog = 6 + const doEvery = 1 + + nextS := s + var t int32 + for { + nextHashS := hash4x64(cv, tableBits) + nextHashL := hash7(cv, tableBits) + + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + e.bTable[nextHashL] = entry + + t = lCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, lCandidate.offset-e.cur) { + // We got a long match. Use that. + break + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, sCandidate.offset-e.cur) { + // Found a 4 match... + lCandidate = e.bTable[hash7(next, tableBits)] + + // If the next long is a candidate, check if we should use that instead... + lOff := nextS - (lCandidate.offset - e.cur) + if lOff < maxMatchOffset && load3232(src, lCandidate.offset-e.cur) == uint32(next) { + l1, l2 := matchLen(src[s+4:], src[t+4:]), matchLen(src[nextS+4:], src[nextS-lOff+4:]) + if l2 > l1 { + s = nextS + t = lCandidate.offset - e.cur + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Extend the 4-byte match as long as possible. + l := e.matchlenLong(s+4, t+4, src) + 4 + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + if debugDeflate { + if t >= s { + panic("s-t") + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + // Index first pair after match end. + if int(s+8) < len(src) { + cv := load6432(src, s) + e.table[hash4x64(cv, tableBits)] = tableEntry{offset: s + e.cur} + e.bTable[hash7(cv, tableBits)] = tableEntry{offset: s + e.cur} + } + goto emitRemainder + } + + // Store every 3rd hash in-between + if true { + i := nextS + if i < s-1 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + e.bTable[hash7(cv, tableBits)] = t + e.bTable[hash7(cv>>8, tableBits)] = t2 + e.table[hash4u(uint32(cv>>8), tableBits)] = t2 + + i += 3 + for ; i < s-1; i += 3 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + e.bTable[hash7(cv, tableBits)] = t + e.bTable[hash7(cv>>8, tableBits)] = t2 + e.table[hash4u(uint32(cv>>8), tableBits)] = t2 + } + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + x := load6432(src, s-1) + o := e.cur + s - 1 + prevHashS := hash4x64(x, tableBits) + prevHashL := hash7(x, tableBits) + e.table[prevHashS] = tableEntry{offset: o} + e.bTable[prevHashL] = tableEntry{offset: o} + cv = x >> 8 + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level5.go b/vendor/github.com/klauspost/compress/flate/level5.go new file mode 100644 index 00000000..d513f1ff --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level5.go @@ -0,0 +1,279 @@ +package flate + +import "fmt" + +type fastEncL5 struct { + fastGen + table [tableSize]tableEntry + bTable [tableSize]tableEntryPrev +} + +func (e *fastEncL5) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + v.Prev.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + } + e.bTable[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + for { + const skipLog = 6 + const doEvery = 1 + + nextS := s + var l int32 + var t int32 + for { + nextHashS := hash4x64(cv, tableBits) + nextHashL := hash7(cv, tableBits) + + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = entry, eLong.Cur + + nextHashS = hash4x64(next, tableBits) + nextHashL = hash7(next, tableBits) + + t = lCandidate.Cur.offset - e.cur + if s-t < maxMatchOffset { + if uint32(cv) == load3232(src, lCandidate.Cur.offset-e.cur) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + t2 := lCandidate.Prev.offset - e.cur + if s-t2 < maxMatchOffset && uint32(cv) == load3232(src, lCandidate.Prev.offset-e.cur) { + l = e.matchlen(s+4, t+4, src) + 4 + ml1 := e.matchlen(s+4, t2+4, src) + 4 + if ml1 > l { + t = t2 + l = ml1 + break + } + } + break + } + t = lCandidate.Prev.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, lCandidate.Prev.offset-e.cur) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + break + } + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, sCandidate.offset-e.cur) { + // Found a 4 match... + l = e.matchlen(s+4, t+4, src) + 4 + lCandidate = e.bTable[nextHashL] + // Store the next match + + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // If the next long is a candidate, use that... + t2 := lCandidate.Cur.offset - e.cur + if nextS-t2 < maxMatchOffset { + if load3232(src, lCandidate.Cur.offset-e.cur) == uint32(next) { + ml := e.matchlen(nextS+4, t2+4, src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + // If the previous long is a candidate, use that... + t2 = lCandidate.Prev.offset - e.cur + if nextS-t2 < maxMatchOffset && load3232(src, lCandidate.Prev.offset-e.cur) == uint32(next) { + ml := e.matchlen(nextS+4, t2+4, src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Extend the 4-byte match as long as possible. + if l == 0 { + l = e.matchlenLong(s+4, t+4, src) + 4 + } else if l == maxMatchLength { + l += e.matchlenLong(s+l, t+l, src) + } + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + if debugDeflate { + if t >= s { + panic(fmt.Sprintln("s-t", s, t)) + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", s-t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + goto emitRemainder + } + + // Store every 3rd hash in-between. + if true { + const hashEvery = 3 + i := s - l + 1 + if i < s-1 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + e.table[hash4x64(cv, tableBits)] = t + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + + // Do an long at i+1 + cv >>= 8 + t = tableEntry{offset: t.offset + 1} + eLong = &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + + // We only have enough bits for a short entry at i+2 + cv >>= 8 + t = tableEntry{offset: t.offset + 1} + e.table[hash4x64(cv, tableBits)] = t + + // Skip one - otherwise we risk hitting 's' + i += 4 + for ; i < s-1; i += hashEvery { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = t, eLong.Cur + e.table[hash4u(uint32(cv>>8), tableBits)] = t2 + } + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + x := load6432(src, s-1) + o := e.cur + s - 1 + prevHashS := hash4x64(x, tableBits) + prevHashL := hash7(x, tableBits) + e.table[prevHashS] = tableEntry{offset: o} + eLong := &e.bTable[prevHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: o}, eLong.Cur + cv = x >> 8 + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/level6.go b/vendor/github.com/klauspost/compress/flate/level6.go new file mode 100644 index 00000000..a52c80ea --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/level6.go @@ -0,0 +1,282 @@ +package flate + +import "fmt" + +type fastEncL6 struct { + fastGen + table [tableSize]tableEntry + bTable [tableSize]tableEntryPrev +} + +func (e *fastEncL6) Encode(dst *tokens, src []byte) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + if debugDeflate && e.cur < 0 { + panic(fmt.Sprint("e.cur < 0: ", e.cur)) + } + + // Protect against e.cur wraparound. + for e.cur >= bufferReset { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.bTable[:] { + e.bTable[i] = tableEntryPrev{} + } + e.cur = maxMatchOffset + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - maxMatchOffset + for i := range e.table[:] { + v := e.table[i].offset + if v <= minOff { + v = 0 + } else { + v = v - e.cur + maxMatchOffset + } + e.table[i].offset = v + } + for i := range e.bTable[:] { + v := e.bTable[i] + if v.Cur.offset <= minOff { + v.Cur.offset = 0 + v.Prev.offset = 0 + } else { + v.Cur.offset = v.Cur.offset - e.cur + maxMatchOffset + if v.Prev.offset <= minOff { + v.Prev.offset = 0 + } else { + v.Prev.offset = v.Prev.offset - e.cur + maxMatchOffset + } + } + e.bTable[i] = v + } + e.cur = maxMatchOffset + } + + s := e.addBlock(src) + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = uint16(len(src)) + return + } + + // Override src + src = e.hist + nextEmit := s + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int32(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load6432(src, s) + // Repeat MUST be > 1 and within range + repeat := int32(1) + for { + const skipLog = 7 + const doEvery = 1 + + nextS := s + var l int32 + var t int32 + for { + nextHashS := hash4x64(cv, tableBits) + nextHashL := hash7(cv, tableBits) + s = nextS + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit { + goto emitRemainder + } + // Fetch a short+long candidate + sCandidate := e.table[nextHashS] + lCandidate := e.bTable[nextHashL] + next := load6432(src, nextS) + entry := tableEntry{offset: s + e.cur} + e.table[nextHashS] = entry + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = entry, eLong.Cur + + // Calculate hashes of 'next' + nextHashS = hash4x64(next, tableBits) + nextHashL = hash7(next, tableBits) + + t = lCandidate.Cur.offset - e.cur + if s-t < maxMatchOffset { + if uint32(cv) == load3232(src, lCandidate.Cur.offset-e.cur) { + // Long candidate matches at least 4 bytes. + + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // Check the previous long candidate as well. + t2 := lCandidate.Prev.offset - e.cur + if s-t2 < maxMatchOffset && uint32(cv) == load3232(src, lCandidate.Prev.offset-e.cur) { + l = e.matchlen(s+4, t+4, src) + 4 + ml1 := e.matchlen(s+4, t2+4, src) + 4 + if ml1 > l { + t = t2 + l = ml1 + break + } + } + break + } + // Current value did not match, but check if previous long value does. + t = lCandidate.Prev.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, lCandidate.Prev.offset-e.cur) { + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + break + } + } + + t = sCandidate.offset - e.cur + if s-t < maxMatchOffset && uint32(cv) == load3232(src, sCandidate.offset-e.cur) { + // Found a 4 match... + l = e.matchlen(s+4, t+4, src) + 4 + + // Look up next long candidate (at nextS) + lCandidate = e.bTable[nextHashL] + + // Store the next match + e.table[nextHashS] = tableEntry{offset: nextS + e.cur} + eLong := &e.bTable[nextHashL] + eLong.Cur, eLong.Prev = tableEntry{offset: nextS + e.cur}, eLong.Cur + + // Check repeat at s + repOff + const repOff = 1 + t2 := s - repeat + repOff + if load3232(src, t2) == uint32(cv>>(8*repOff)) { + ml := e.matchlen(s+4+repOff, t2+4, src) + 4 + if ml > l { + t = t2 + l = ml + s += repOff + // Not worth checking more. + break + } + } + + // If the next long is a candidate, use that... + t2 = lCandidate.Cur.offset - e.cur + if nextS-t2 < maxMatchOffset { + if load3232(src, lCandidate.Cur.offset-e.cur) == uint32(next) { + ml := e.matchlen(nextS+4, t2+4, src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + // This is ok, but check previous as well. + } + } + // If the previous long is a candidate, use that... + t2 = lCandidate.Prev.offset - e.cur + if nextS-t2 < maxMatchOffset && load3232(src, lCandidate.Prev.offset-e.cur) == uint32(next) { + ml := e.matchlen(nextS+4, t2+4, src) + 4 + if ml > l { + t = t2 + s = nextS + l = ml + break + } + } + } + break + } + cv = next + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + + // Extend the 4-byte match as long as possible. + if l == 0 { + l = e.matchlenLong(s+4, t+4, src) + 4 + } else if l == maxMatchLength { + l += e.matchlenLong(s+l, t+l, src) + } + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + if false { + if t >= s { + panic(fmt.Sprintln("s-t", s, t)) + } + if (s - t) > maxMatchOffset { + panic(fmt.Sprintln("mmo", s-t)) + } + if l < baseMatchLength { + panic("bml") + } + } + + dst.AddMatchLong(l, uint32(s-t-baseMatchOffset)) + repeat = s - t + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + + if s >= sLimit { + // Index after match end. + for i := nextS + 1; i < int32(len(src))-8; i += 2 { + cv := load6432(src, i) + e.table[hash4x64(cv, tableBits)] = tableEntry{offset: i + e.cur} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong.Cur, eLong.Prev = tableEntry{offset: i + e.cur}, eLong.Cur + } + goto emitRemainder + } + + // Store every long hash in-between and every second short. + if true { + for i := nextS + 1; i < s-1; i += 2 { + cv := load6432(src, i) + t := tableEntry{offset: i + e.cur} + t2 := tableEntry{offset: t.offset + 1} + eLong := &e.bTable[hash7(cv, tableBits)] + eLong2 := &e.bTable[hash7(cv>>8, tableBits)] + e.table[hash4x64(cv, tableBits)] = t + eLong.Cur, eLong.Prev = t, eLong.Cur + eLong2.Cur, eLong2.Prev = t2, eLong2.Cur + } + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. + cv = load6432(src, s) + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/regmask_amd64.go b/vendor/github.com/klauspost/compress/flate/regmask_amd64.go new file mode 100644 index 00000000..6ed28061 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/regmask_amd64.go @@ -0,0 +1,37 @@ +package flate + +const ( + // Masks for shifts with register sizes of the shift value. + // This can be used to work around the x86 design of shifting by mod register size. + // It can be used when a variable shift is always smaller than the register size. + + // reg8SizeMaskX - shift value is 8 bits, shifted is X + reg8SizeMask8 = 7 + reg8SizeMask16 = 15 + reg8SizeMask32 = 31 + reg8SizeMask64 = 63 + + // reg16SizeMaskX - shift value is 16 bits, shifted is X + reg16SizeMask8 = reg8SizeMask8 + reg16SizeMask16 = reg8SizeMask16 + reg16SizeMask32 = reg8SizeMask32 + reg16SizeMask64 = reg8SizeMask64 + + // reg32SizeMaskX - shift value is 32 bits, shifted is X + reg32SizeMask8 = reg8SizeMask8 + reg32SizeMask16 = reg8SizeMask16 + reg32SizeMask32 = reg8SizeMask32 + reg32SizeMask64 = reg8SizeMask64 + + // reg64SizeMaskX - shift value is 64 bits, shifted is X + reg64SizeMask8 = reg8SizeMask8 + reg64SizeMask16 = reg8SizeMask16 + reg64SizeMask32 = reg8SizeMask32 + reg64SizeMask64 = reg8SizeMask64 + + // regSizeMaskUintX - shift value is uint, shifted is X + regSizeMaskUint8 = reg8SizeMask8 + regSizeMaskUint16 = reg8SizeMask16 + regSizeMaskUint32 = reg8SizeMask32 + regSizeMaskUint64 = reg8SizeMask64 +) diff --git a/vendor/github.com/klauspost/compress/flate/regmask_other.go b/vendor/github.com/klauspost/compress/flate/regmask_other.go new file mode 100644 index 00000000..f477a5d6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/regmask_other.go @@ -0,0 +1,39 @@ +//+build !amd64 + +package flate + +const ( + // Masks for shifts with register sizes of the shift value. + // This can be used to work around the x86 design of shifting by mod register size. + // It can be used when a variable shift is always smaller than the register size. + + // reg8SizeMaskX - shift value is 8 bits, shifted is X + reg8SizeMask8 = 0xff + reg8SizeMask16 = 0xff + reg8SizeMask32 = 0xff + reg8SizeMask64 = 0xff + + // reg16SizeMaskX - shift value is 16 bits, shifted is X + reg16SizeMask8 = 0xffff + reg16SizeMask16 = 0xffff + reg16SizeMask32 = 0xffff + reg16SizeMask64 = 0xffff + + // reg32SizeMaskX - shift value is 32 bits, shifted is X + reg32SizeMask8 = 0xffffffff + reg32SizeMask16 = 0xffffffff + reg32SizeMask32 = 0xffffffff + reg32SizeMask64 = 0xffffffff + + // reg64SizeMaskX - shift value is 64 bits, shifted is X + reg64SizeMask8 = 0xffffffffffffffff + reg64SizeMask16 = 0xffffffffffffffff + reg64SizeMask32 = 0xffffffffffffffff + reg64SizeMask64 = 0xffffffffffffffff + + // regSizeMaskUintX - shift value is uint, shifted is X + regSizeMaskUint8 = ^uint(0) + regSizeMaskUint16 = ^uint(0) + regSizeMaskUint32 = ^uint(0) + regSizeMaskUint64 = ^uint(0) +) diff --git a/vendor/github.com/klauspost/compress/flate/stateless.go b/vendor/github.com/klauspost/compress/flate/stateless.go new file mode 100644 index 00000000..53e89912 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/stateless.go @@ -0,0 +1,297 @@ +package flate + +import ( + "io" + "math" + "sync" +) + +const ( + maxStatelessBlock = math.MaxInt16 + // dictionary will be taken from maxStatelessBlock, so limit it. + maxStatelessDict = 8 << 10 + + slTableBits = 13 + slTableSize = 1 << slTableBits + slTableShift = 32 - slTableBits +) + +type statelessWriter struct { + dst io.Writer + closed bool +} + +func (s *statelessWriter) Close() error { + if s.closed { + return nil + } + s.closed = true + // Emit EOF block + return StatelessDeflate(s.dst, nil, true, nil) +} + +func (s *statelessWriter) Write(p []byte) (n int, err error) { + err = StatelessDeflate(s.dst, p, false, nil) + if err != nil { + return 0, err + } + return len(p), nil +} + +func (s *statelessWriter) Reset(w io.Writer) { + s.dst = w + s.closed = false +} + +// NewStatelessWriter will do compression but without maintaining any state +// between Write calls. +// There will be no memory kept between Write calls, +// but compression and speed will be suboptimal. +// Because of this, the size of actual Write calls will affect output size. +func NewStatelessWriter(dst io.Writer) io.WriteCloser { + return &statelessWriter{dst: dst} +} + +// bitWriterPool contains bit writers that can be reused. +var bitWriterPool = sync.Pool{ + New: func() interface{} { + return newHuffmanBitWriter(nil) + }, +} + +// StatelessDeflate allows to compress directly to a Writer without retaining state. +// When returning everything will be flushed. +// Up to 8KB of an optional dictionary can be given which is presumed to presumed to precede the block. +// Longer dictionaries will be truncated and will still produce valid output. +// Sending nil dictionary is perfectly fine. +func StatelessDeflate(out io.Writer, in []byte, eof bool, dict []byte) error { + var dst tokens + bw := bitWriterPool.Get().(*huffmanBitWriter) + bw.reset(out) + defer func() { + // don't keep a reference to our output + bw.reset(nil) + bitWriterPool.Put(bw) + }() + if eof && len(in) == 0 { + // Just write an EOF block. + // Could be faster... + bw.writeStoredHeader(0, true) + bw.flush() + return bw.err + } + + // Truncate dict + if len(dict) > maxStatelessDict { + dict = dict[len(dict)-maxStatelessDict:] + } + + for len(in) > 0 { + todo := in + if len(todo) > maxStatelessBlock-len(dict) { + todo = todo[:maxStatelessBlock-len(dict)] + } + in = in[len(todo):] + uncompressed := todo + if len(dict) > 0 { + // combine dict and source + bufLen := len(todo) + len(dict) + combined := make([]byte, bufLen) + copy(combined, dict) + copy(combined[len(dict):], todo) + todo = combined + } + // Compress + statelessEnc(&dst, todo, int16(len(dict))) + isEof := eof && len(in) == 0 + + if dst.n == 0 { + bw.writeStoredHeader(len(uncompressed), isEof) + if bw.err != nil { + return bw.err + } + bw.writeBytes(uncompressed) + } else if int(dst.n) > len(uncompressed)-len(uncompressed)>>4 { + // If we removed less than 1/16th, huffman compress the block. + bw.writeBlockHuff(isEof, uncompressed, len(in) == 0) + } else { + bw.writeBlockDynamic(&dst, isEof, uncompressed, len(in) == 0) + } + if len(in) > 0 { + // Retain a dict if we have more + dict = todo[len(todo)-maxStatelessDict:] + dst.Reset() + } + if bw.err != nil { + return bw.err + } + } + if !eof { + // Align, only a stored block can do that. + bw.writeStoredHeader(0, false) + } + bw.flush() + return bw.err +} + +func hashSL(u uint32) uint32 { + return (u * 0x1e35a7bd) >> slTableShift +} + +func load3216(b []byte, i int16) uint32 { + // Help the compiler eliminate bounds checks on the read so it can be done in a single read. + b = b[i:] + b = b[:4] + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func load6416(b []byte, i int16) uint64 { + // Help the compiler eliminate bounds checks on the read so it can be done in a single read. + b = b[i:] + b = b[:8] + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +func statelessEnc(dst *tokens, src []byte, startAt int16) { + const ( + inputMargin = 12 - 1 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + + type tableEntry struct { + offset int16 + } + + var table [slTableSize]tableEntry + + // This check isn't in the Snappy implementation, but there, the caller + // instead of the callee handles this case. + if len(src)-int(startAt) < minNonLiteralBlockSize { + // We do not fill the token table. + // This will be picked up by caller. + dst.n = 0 + return + } + // Index until startAt + if startAt > 0 { + cv := load3232(src, 0) + for i := int16(0); i < startAt; i++ { + table[hashSL(cv)] = tableEntry{offset: i} + cv = (cv >> 8) | (uint32(src[i+4]) << 24) + } + } + + s := startAt + 1 + nextEmit := startAt + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := int16(len(src) - inputMargin) + + // nextEmit is where in src the next emitLiteral should start from. + cv := load3216(src, s) + + for { + const skipLog = 5 + const doEvery = 2 + + nextS := s + var candidate tableEntry + for { + nextHash := hashSL(cv) + candidate = table[nextHash] + nextS = s + doEvery + (s-nextEmit)>>skipLog + if nextS > sLimit || nextS <= 0 { + goto emitRemainder + } + + now := load6416(src, nextS) + table[nextHash] = tableEntry{offset: s} + nextHash = hashSL(uint32(now)) + + if cv == load3216(src, candidate.offset) { + table[nextHash] = tableEntry{offset: nextS} + break + } + + // Do one right away... + cv = uint32(now) + s = nextS + nextS++ + candidate = table[nextHash] + now >>= 8 + table[nextHash] = tableEntry{offset: s} + + if cv == load3216(src, candidate.offset) { + table[nextHash] = tableEntry{offset: nextS} + break + } + cv = uint32(now) + s = nextS + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + + // Extend the 4-byte match as long as possible. + t := candidate.offset + l := int16(matchLen(src[s+4:], src[t+4:]) + 4) + + // Extend backwards + for t > 0 && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + if nextEmit < s { + emitLiteral(dst, src[nextEmit:s]) + } + + // Save the match found + dst.AddMatchLong(int32(l), uint32(s-t-baseMatchOffset)) + s += l + nextEmit = s + if nextS >= s { + s = nextS + 1 + } + if s >= sLimit { + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-2 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load6416(src, s-2) + o := s - 2 + prevHash := hashSL(uint32(x)) + table[prevHash] = tableEntry{offset: o} + x >>= 16 + currHash := hashSL(uint32(x)) + candidate = table[currHash] + table[currHash] = tableEntry{offset: o + 2} + + if uint32(x) != load3216(src, candidate.offset) { + cv = uint32(x >> 8) + s++ + break + } + } + } + +emitRemainder: + if int(nextEmit) < len(src) { + // If nothing was added, don't encode literals. + if dst.n == 0 { + return + } + emitLiteral(dst, src[nextEmit:]) + } +} diff --git a/vendor/github.com/klauspost/compress/flate/token.go b/vendor/github.com/klauspost/compress/flate/token.go new file mode 100644 index 00000000..f9abf606 --- /dev/null +++ b/vendor/github.com/klauspost/compress/flate/token.go @@ -0,0 +1,375 @@ +// Copyright 2009 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 flate + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "math" +) + +const ( + // 2 bits: type 0 = literal 1=EOF 2=Match 3=Unused + // 8 bits: xlength = length - MIN_MATCH_LENGTH + // 22 bits xoffset = offset - MIN_OFFSET_SIZE, or literal + lengthShift = 22 + offsetMask = 1<maxnumlit + offHist [32]uint16 // offset codes + litHist [256]uint16 // codes 0->255 + n uint16 // Must be able to contain maxStoreBlockSize + tokens [maxStoreBlockSize + 1]token +} + +func (t *tokens) Reset() { + if t.n == 0 { + return + } + t.n = 0 + t.nLits = 0 + for i := range t.litHist[:] { + t.litHist[i] = 0 + } + for i := range t.extraHist[:] { + t.extraHist[i] = 0 + } + for i := range t.offHist[:] { + t.offHist[i] = 0 + } +} + +func (t *tokens) Fill() { + if t.n == 0 { + return + } + for i, v := range t.litHist[:] { + if v == 0 { + t.litHist[i] = 1 + t.nLits++ + } + } + for i, v := range t.extraHist[:literalCount-256] { + if v == 0 { + t.nLits++ + t.extraHist[i] = 1 + } + } + for i, v := range t.offHist[:offsetCodeCount] { + if v == 0 { + t.offHist[i] = 1 + } + } +} + +func indexTokens(in []token) tokens { + var t tokens + t.indexTokens(in) + return t +} + +func (t *tokens) indexTokens(in []token) { + t.Reset() + for _, tok := range in { + if tok < matchType { + t.AddLiteral(tok.literal()) + continue + } + t.AddMatch(uint32(tok.length()), tok.offset()) + } +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +func emitLiteral(dst *tokens, lit []byte) { + ol := int(dst.n) + for i, v := range lit { + dst.tokens[(i+ol)&maxStoreBlockSize] = token(v) + dst.litHist[v]++ + } + dst.n += uint16(len(lit)) + dst.nLits += len(lit) +} + +func (t *tokens) AddLiteral(lit byte) { + t.tokens[t.n] = token(lit) + t.litHist[lit]++ + t.n++ + t.nLits++ +} + +// from https://stackoverflow.com/a/28730362 +func mFastLog2(val float32) float32 { + ux := int32(math.Float32bits(val)) + log2 := (float32)(((ux >> 23) & 255) - 128) + ux &= -0x7f800001 + ux += 127 << 23 + uval := math.Float32frombits(uint32(ux)) + log2 += ((-0.34484843)*uval+2.02466578)*uval - 0.67487759 + return log2 +} + +// EstimatedBits will return an minimum size estimated by an *optimal* +// compression of the block. +// The size of the block +func (t *tokens) EstimatedBits() int { + shannon := float32(0) + bits := int(0) + nMatches := 0 + if t.nLits > 0 { + invTotal := 1.0 / float32(t.nLits) + for _, v := range t.litHist[:] { + if v > 0 { + n := float32(v) + shannon += -mFastLog2(n*invTotal) * n + } + } + // Just add 15 for EOB + shannon += 15 + for i, v := range t.extraHist[1 : literalCount-256] { + if v > 0 { + n := float32(v) + shannon += -mFastLog2(n*invTotal) * n + bits += int(lengthExtraBits[i&31]) * int(v) + nMatches += int(v) + } + } + } + if nMatches > 0 { + invTotal := 1.0 / float32(nMatches) + for i, v := range t.offHist[:offsetCodeCount] { + if v > 0 { + n := float32(v) + shannon += -mFastLog2(n*invTotal) * n + bits += int(offsetExtraBits[i&31]) * int(v) + } + } + } + return int(shannon) + bits +} + +// AddMatch adds a match to the tokens. +// This function is very sensitive to inlining and right on the border. +func (t *tokens) AddMatch(xlength uint32, xoffset uint32) { + if debugDeflate { + if xlength >= maxMatchLength+baseMatchLength { + panic(fmt.Errorf("invalid length: %v", xlength)) + } + if xoffset >= maxMatchOffset+baseMatchOffset { + panic(fmt.Errorf("invalid offset: %v", xoffset)) + } + } + t.nLits++ + lengthCode := lengthCodes1[uint8(xlength)] & 31 + t.tokens[t.n] = token(matchType | xlength<= maxMatchOffset+baseMatchOffset { + panic(fmt.Errorf("invalid offset: %v", xoffset)) + } + } + oc := offsetCode(xoffset) & 31 + for xlength > 0 { + xl := xlength + if xl > 258 { + // We need to have at least baseMatchLength left over for next loop. + xl = 258 - baseMatchLength + } + xlength -= xl + xl -= 3 + t.nLits++ + lengthCode := lengthCodes1[uint8(xl)] & 31 + t.tokens[t.n] = token(matchType | uint32(xl)<> lengthShift) } + +// The code is never more than 8 bits, but is returned as uint32 for convenience. +func lengthCode(len uint8) uint32 { return uint32(lengthCodes[len]) } + +// Returns the offset code corresponding to a specific offset +func offsetCode(off uint32) uint32 { + if false { + if off < uint32(len(offsetCodes)) { + return offsetCodes[off&255] + } else if off>>7 < uint32(len(offsetCodes)) { + return offsetCodes[(off>>7)&255] + 14 + } else { + return offsetCodes[(off>>14)&255] + 28 + } + } + if off < uint32(len(offsetCodes)) { + return offsetCodes[uint8(off)] + } + return offsetCodes14[uint8(off>>7)] +} diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml deleted file mode 100644 index 7942c565..00000000 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) - diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md index e055952b..ca048371 100644 --- a/vendor/github.com/mattn/go-colorable/README.md +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -1,6 +1,6 @@ # go-colorable -[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) +[![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest) [![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) [![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go index 1f7806fe..416d1bbb 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go index 08cbd1e0..766d9460 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -1,5 +1,5 @@ -// +build !windows -// +build !appengine +//go:build !windows && !appengine +// +build !windows,!appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index 41215d7f..1846ad5a 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package colorable @@ -452,18 +452,22 @@ func (w *Writer) Write(data []byte) (n int, err error) { } else { er = bytes.NewReader(data) } - var bw [1]byte + var plaintext bytes.Buffer loop: for { c1, err := er.ReadByte() if err != nil { + plaintext.WriteTo(w.out) break loop } if c1 != 0x1b { - bw[0] = c1 - w.out.Write(bw[:]) + plaintext.WriteByte(c1) continue } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } c2, err := er.ReadByte() if err != nil { break loop diff --git a/vendor/github.com/mattn/go-colorable/go.mod b/vendor/github.com/mattn/go-colorable/go.mod index 1e590b81..27351c02 100644 --- a/vendor/github.com/mattn/go-colorable/go.mod +++ b/vendor/github.com/mattn/go-colorable/go.mod @@ -1,8 +1,8 @@ module github.com/mattn/go-colorable require ( - github.com/mattn/go-isatty v0.0.12 - golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect + github.com/mattn/go-isatty v0.0.14 + golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect ) go 1.13 diff --git a/vendor/github.com/mattn/go-colorable/go.sum b/vendor/github.com/mattn/go-colorable/go.sum index cf5b95d9..40c33b33 100644 --- a/vendor/github.com/mattn/go-colorable/go.sum +++ b/vendor/github.com/mattn/go-colorable/go.sum @@ -1,5 +1,5 @@ -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go index 95f2c6be..3df68f36 100644 --- a/vendor/github.com/mattn/go-colorable/noncolorable.go +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -18,18 +18,22 @@ func NewNonColorable(w io.Writer) io.Writer { // Write writes data on console func (w *NonColorable) Write(data []byte) (n int, err error) { er := bytes.NewReader(data) - var bw [1]byte + var plaintext bytes.Buffer loop: for { c1, err := er.ReadByte() if err != nil { + plaintext.WriteTo(w.out) break loop } if c1 != 0x1b { - bw[0] = c1 - w.out.Write(bw[:]) + plaintext.WriteByte(c1) continue } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } c2, err := er.ReadByte() if err != nil { break loop diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml deleted file mode 100644 index 604314dd..00000000 --- a/vendor/github.com/mattn/go-isatty/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/mattn/go-isatty/go.mod b/vendor/github.com/mattn/go-isatty/go.mod index 605c4c22..c9a20b7f 100644 --- a/vendor/github.com/mattn/go-isatty/go.mod +++ b/vendor/github.com/mattn/go-isatty/go.mod @@ -2,4 +2,4 @@ module github.com/mattn/go-isatty go 1.12 -require golang.org/x/sys v0.0.0-20200116001909-b77594299b42 +require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go index 711f2880..39bbcf00 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -1,3 +1,4 @@ +//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine // +build darwin freebsd openbsd netbsd dragonfly // +build !appengine diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go index ff714a37..31503226 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_others.go +++ b/vendor/github.com/mattn/go-isatty/isatty_others.go @@ -1,4 +1,5 @@ -// +build appengine js nacl +//go:build appengine || js || nacl || wasm +// +build appengine js nacl wasm package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go index c5b6e0c0..bae7f9bb 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_plan9.go +++ b/vendor/github.com/mattn/go-isatty/isatty_plan9.go @@ -1,3 +1,4 @@ +//go:build plan9 // +build plan9 package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go index bdd5c79a..0c3acf2d 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_solaris.go +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -1,5 +1,5 @@ -// +build solaris -// +build !appengine +//go:build solaris && !appengine +// +build solaris,!appengine package isatty @@ -8,10 +8,9 @@ import ( ) // IsTerminal returns true if the given file descriptor is a terminal. -// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +// see: https://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/isatty.c func IsTerminal(fd uintptr) bool { - var termio unix.Termio - err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + _, err := unix.IoctlGetTermio(int(fd), unix.TCGETA) return err == nil } diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go index 31a1ca97..67787657 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go @@ -1,4 +1,5 @@ -// +build linux aix +//go:build (linux || aix || zos) && !appengine +// +build linux aix zos // +build !appengine package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go index 1fa86915..8e3c9917 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_windows.go +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package isatty @@ -76,7 +76,7 @@ func isCygwinPipeName(name string) bool { } // getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler -// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion +// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion // guys are using Windows XP, this is a workaround for those guys, it will also work on system from // Windows vista to 10 // see https://stackoverflow.com/a/18792477 for details diff --git a/vendor/github.com/mattn/go-isatty/renovate.json b/vendor/github.com/mattn/go-isatty/renovate.json deleted file mode 100644 index 5ae9d96b..00000000 --- a/vendor/github.com/mattn/go-isatty/renovate.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": [ - "config:base" - ], - "postUpdateOptions": [ - "gomodTidy" - ] -} diff --git a/vendor/github.com/modern-go/reflect2/.travis.yml b/vendor/github.com/modern-go/reflect2/.travis.yml index fbb43744..b097728d 100644 --- a/vendor/github.com/modern-go/reflect2/.travis.yml +++ b/vendor/github.com/modern-go/reflect2/.travis.yml @@ -1,7 +1,7 @@ language: go go: - - 1.8.x + - 1.9.x - 1.x before_install: diff --git a/vendor/github.com/modern-go/reflect2/Gopkg.lock b/vendor/github.com/modern-go/reflect2/Gopkg.lock index 2a3a6989..10ef8111 100644 --- a/vendor/github.com/modern-go/reflect2/Gopkg.lock +++ b/vendor/github.com/modern-go/reflect2/Gopkg.lock @@ -1,15 +1,9 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. -[[projects]] - name = "github.com/modern-go/concurrent" - packages = ["."] - revision = "e0a39a4cb4216ea8db28e22a69f4ec25610d513a" - version = "1.0.0" - [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "daee8a88b3498b61c5640056665b8b9eea062006f5e596bbb6a3ed9119a11ec7" + input-imports = [] solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/modern-go/reflect2/Gopkg.toml b/vendor/github.com/modern-go/reflect2/Gopkg.toml index 2f4f4dbd..a9bc5061 100644 --- a/vendor/github.com/modern-go/reflect2/Gopkg.toml +++ b/vendor/github.com/modern-go/reflect2/Gopkg.toml @@ -26,10 +26,6 @@ ignored = [] -[[constraint]] - name = "github.com/modern-go/concurrent" - version = "1.0.0" - [prune] go-tests = true unused-packages = true diff --git a/vendor/github.com/modern-go/reflect2/go.mod b/vendor/github.com/modern-go/reflect2/go.mod new file mode 100644 index 00000000..9057e9b3 --- /dev/null +++ b/vendor/github.com/modern-go/reflect2/go.mod @@ -0,0 +1,3 @@ +module github.com/modern-go/reflect2 + +go 1.12 diff --git a/vendor/github.com/modern-go/reflect2/go_above_118.go b/vendor/github.com/modern-go/reflect2/go_above_118.go new file mode 100644 index 00000000..2b4116f6 --- /dev/null +++ b/vendor/github.com/modern-go/reflect2/go_above_118.go @@ -0,0 +1,23 @@ +//+build go1.18 + +package reflect2 + +import ( + "unsafe" +) + +// m escapes into the return value, but the caller of mapiterinit +// doesn't let the return value escape. +//go:noescape +//go:linkname mapiterinit reflect.mapiterinit +func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer, it *hiter) + +func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator { + var it hiter + mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj), &it) + return &UnsafeMapIterator{ + hiter: &it, + pKeyRType: type2.pKeyRType, + pElemRType: type2.pElemRType, + } +} \ No newline at end of file diff --git a/vendor/github.com/modern-go/reflect2/go_above_17.go b/vendor/github.com/modern-go/reflect2/go_above_17.go deleted file mode 100644 index 5c1cea86..00000000 --- a/vendor/github.com/modern-go/reflect2/go_above_17.go +++ /dev/null @@ -1,8 +0,0 @@ -//+build go1.7 - -package reflect2 - -import "unsafe" - -//go:linkname resolveTypeOff reflect.resolveTypeOff -func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer diff --git a/vendor/github.com/modern-go/reflect2/go_above_19.go b/vendor/github.com/modern-go/reflect2/go_above_19.go index c7e3b780..974f7685 100644 --- a/vendor/github.com/modern-go/reflect2/go_above_19.go +++ b/vendor/github.com/modern-go/reflect2/go_above_19.go @@ -6,6 +6,9 @@ import ( "unsafe" ) +//go:linkname resolveTypeOff reflect.resolveTypeOff +func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer + //go:linkname makemap reflect.makemap func makemap(rtype unsafe.Pointer, cap int) (m unsafe.Pointer) diff --git a/vendor/github.com/modern-go/reflect2/go_below_118.go b/vendor/github.com/modern-go/reflect2/go_below_118.go new file mode 100644 index 00000000..00003dbd --- /dev/null +++ b/vendor/github.com/modern-go/reflect2/go_below_118.go @@ -0,0 +1,21 @@ +//+build !go1.18 + +package reflect2 + +import ( + "unsafe" +) + +// m escapes into the return value, but the caller of mapiterinit +// doesn't let the return value escape. +//go:noescape +//go:linkname mapiterinit reflect.mapiterinit +func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) (val *hiter) + +func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator { + return &UnsafeMapIterator{ + hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)), + pKeyRType: type2.pKeyRType, + pElemRType: type2.pElemRType, + } +} \ No newline at end of file diff --git a/vendor/github.com/modern-go/reflect2/go_below_17.go b/vendor/github.com/modern-go/reflect2/go_below_17.go deleted file mode 100644 index 65a93c88..00000000 --- a/vendor/github.com/modern-go/reflect2/go_below_17.go +++ /dev/null @@ -1,9 +0,0 @@ -//+build !go1.7 - -package reflect2 - -import "unsafe" - -func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer { - return nil -} diff --git a/vendor/github.com/modern-go/reflect2/go_below_19.go b/vendor/github.com/modern-go/reflect2/go_below_19.go deleted file mode 100644 index b050ef70..00000000 --- a/vendor/github.com/modern-go/reflect2/go_below_19.go +++ /dev/null @@ -1,14 +0,0 @@ -//+build !go1.9 - -package reflect2 - -import ( - "unsafe" -) - -//go:linkname makemap reflect.makemap -func makemap(rtype unsafe.Pointer) (m unsafe.Pointer) - -func makeMapWithSize(rtype unsafe.Pointer, cap int) unsafe.Pointer { - return makemap(rtype) -} diff --git a/vendor/github.com/modern-go/reflect2/reflect2.go b/vendor/github.com/modern-go/reflect2/reflect2.go index 63b49c79..c43c8b9d 100644 --- a/vendor/github.com/modern-go/reflect2/reflect2.go +++ b/vendor/github.com/modern-go/reflect2/reflect2.go @@ -1,8 +1,9 @@ package reflect2 import ( - "github.com/modern-go/concurrent" "reflect" + "runtime" + "sync" "unsafe" ) @@ -130,13 +131,13 @@ var ConfigSafe = Config{UseSafeImplementation: true}.Froze() type frozenConfig struct { useSafeImplementation bool - cache *concurrent.Map + cache *sync.Map } func (cfg Config) Froze() *frozenConfig { return &frozenConfig{ useSafeImplementation: cfg.UseSafeImplementation, - cache: concurrent.NewMap(), + cache: new(sync.Map), } } @@ -288,11 +289,12 @@ func NoEscape(p unsafe.Pointer) unsafe.Pointer { } func UnsafeCastString(str string) []byte { + bytes := make([]byte, 0) stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&str)) - sliceHeader := &reflect.SliceHeader{ - Data: stringHeader.Data, - Cap: stringHeader.Len, - Len: stringHeader.Len, - } - return *(*[]byte)(unsafe.Pointer(sliceHeader)) + sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) + sliceHeader.Data = stringHeader.Data + sliceHeader.Cap = stringHeader.Len + sliceHeader.Len = stringHeader.Len + runtime.KeepAlive(str) + return bytes } diff --git a/vendor/github.com/modern-go/reflect2/test.sh b/vendor/github.com/modern-go/reflect2/test.sh deleted file mode 100644 index 3d2b9768..00000000 --- a/vendor/github.com/modern-go/reflect2/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list github.com/modern-go/reflect2-tests/... | grep -v vendor); do - go test -coverprofile=profile.out -coverpkg=github.com/modern-go/reflect2 $d - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/modern-go/reflect2/type_map.go b/vendor/github.com/modern-go/reflect2/type_map.go index 3acfb558..4b13c315 100644 --- a/vendor/github.com/modern-go/reflect2/type_map.go +++ b/vendor/github.com/modern-go/reflect2/type_map.go @@ -1,17 +1,13 @@ +// +build !gccgo + package reflect2 import ( "reflect" - "runtime" - "strings" "sync" "unsafe" ) -// typelinks1 for 1.5 ~ 1.6 -//go:linkname typelinks1 reflect.typelinks -func typelinks1() [][]unsafe.Pointer - // typelinks2 for 1.7 ~ //go:linkname typelinks2 reflect.typelinks func typelinks2() (sections []unsafe.Pointer, offset [][]int32) @@ -27,49 +23,10 @@ func discoverTypes() { types = make(map[string]reflect.Type) packages = make(map[string]map[string]reflect.Type) - ver := runtime.Version() - if ver == "go1.5" || strings.HasPrefix(ver, "go1.5.") { - loadGo15Types() - } else if ver == "go1.6" || strings.HasPrefix(ver, "go1.6.") { - loadGo15Types() - } else { - loadGo17Types() - } -} - -func loadGo15Types() { - var obj interface{} = reflect.TypeOf(0) - typePtrss := typelinks1() - for _, typePtrs := range typePtrss { - for _, typePtr := range typePtrs { - (*emptyInterface)(unsafe.Pointer(&obj)).word = typePtr - typ := obj.(reflect.Type) - if typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.Struct { - loadedType := typ.Elem() - pkgTypes := packages[loadedType.PkgPath()] - if pkgTypes == nil { - pkgTypes = map[string]reflect.Type{} - packages[loadedType.PkgPath()] = pkgTypes - } - types[loadedType.String()] = loadedType - pkgTypes[loadedType.Name()] = loadedType - } - if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Ptr && - typ.Elem().Elem().Kind() == reflect.Struct { - loadedType := typ.Elem().Elem() - pkgTypes := packages[loadedType.PkgPath()] - if pkgTypes == nil { - pkgTypes = map[string]reflect.Type{} - packages[loadedType.PkgPath()] = pkgTypes - } - types[loadedType.String()] = loadedType - pkgTypes[loadedType.Name()] = loadedType - } - } - } + loadGoTypes() } -func loadGo17Types() { +func loadGoTypes() { var obj interface{} = reflect.TypeOf(0) sections, offset := typelinks2() for i, offs := range offset { diff --git a/vendor/github.com/modern-go/reflect2/unsafe_link.go b/vendor/github.com/modern-go/reflect2/unsafe_link.go index 57229c8d..b49f614e 100644 --- a/vendor/github.com/modern-go/reflect2/unsafe_link.go +++ b/vendor/github.com/modern-go/reflect2/unsafe_link.go @@ -19,18 +19,12 @@ func typedslicecopy(elemType unsafe.Pointer, dst, src sliceHeader) int //go:linkname mapassign reflect.mapassign //go:noescape -func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key, val unsafe.Pointer) +func mapassign(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer, val unsafe.Pointer) //go:linkname mapaccess reflect.mapaccess //go:noescape func mapaccess(rtype unsafe.Pointer, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer) -// m escapes into the return value, but the caller of mapiterinit -// doesn't let the return value escape. -//go:noescape -//go:linkname mapiterinit reflect.mapiterinit -func mapiterinit(rtype unsafe.Pointer, m unsafe.Pointer) *hiter - //go:noescape //go:linkname mapiternext reflect.mapiternext func mapiternext(it *hiter) @@ -42,9 +36,21 @@ func ifaceE2I(rtype unsafe.Pointer, src interface{}, dst unsafe.Pointer) // If you modify hiter, also change cmd/internal/gc/reflect.go to indicate // the layout of this structure. type hiter struct { - key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/internal/gc/range.go). - value unsafe.Pointer // Must be in second position (see cmd/internal/gc/range.go). - // rest fields are ignored + key unsafe.Pointer + value unsafe.Pointer + t unsafe.Pointer + h unsafe.Pointer + buckets unsafe.Pointer + bptr unsafe.Pointer + overflow *[]unsafe.Pointer + oldoverflow *[]unsafe.Pointer + startBucket uintptr + offset uint8 + wrapped bool + B uint8 + i uint8 + bucket uintptr + checkBucket uintptr } // add returns p+x. diff --git a/vendor/github.com/modern-go/reflect2/unsafe_map.go b/vendor/github.com/modern-go/reflect2/unsafe_map.go index f2e76e6b..37872da8 100644 --- a/vendor/github.com/modern-go/reflect2/unsafe_map.go +++ b/vendor/github.com/modern-go/reflect2/unsafe_map.go @@ -107,14 +107,6 @@ func (type2 *UnsafeMapType) Iterate(obj interface{}) MapIterator { return type2.UnsafeIterate(objEFace.data) } -func (type2 *UnsafeMapType) UnsafeIterate(obj unsafe.Pointer) MapIterator { - return &UnsafeMapIterator{ - hiter: mapiterinit(type2.rtype, *(*unsafe.Pointer)(obj)), - pKeyRType: type2.pKeyRType, - pElemRType: type2.pElemRType, - } -} - type UnsafeMapIterator struct { *hiter pKeyRType unsafe.Pointer diff --git a/vendor/github.com/skycoin/dmsg/client.go b/vendor/github.com/skycoin/dmsg/client.go index 87cdc163..dd7b85be 100644 --- a/vendor/github.com/skycoin/dmsg/client.go +++ b/vendor/github.com/skycoin/dmsg/client.go @@ -181,7 +181,7 @@ func (ce *Client) Serve(ctx context.Context) { } } - if err := ce.ensureSession(cancellabelCtx, entry); err != nil { + if err := ce.EnsureSession(cancellabelCtx, entry); err != nil { ce.log.WithField("remote_pk", entry.Static).WithError(err).Warn("Failed to establish session.") if err == context.Canceled || err == context.DeadlineExceeded { return @@ -331,14 +331,15 @@ func (ce *Client) EnsureAndObtainSession(ctx context.Context, srvPK cipher.PubKe return ce.dialSession(ctx, srvEntry) } -// ensureSession ensures the existence of a session. +// EnsureSession ensures the existence of a session. // It returns an error if the session does not exist AND cannot be established. -func (ce *Client) ensureSession(ctx context.Context, entry *disc.Entry) error { +func (ce *Client) EnsureSession(ctx context.Context, entry *disc.Entry) error { ce.sesMx.Lock() defer ce.sesMx.Unlock() // If session with server of pk already exists, skip. if _, ok := ce.clientSession(ce.porter, entry.Static); ok { + ce.log.WithField("remote_pk", entry.Static).Info("Session already exists...") return nil } diff --git a/vendor/github.com/skycoin/dmsg/client_session.go b/vendor/github.com/skycoin/dmsg/client_session.go index 87477393..a5d7c096 100644 --- a/vendor/github.com/skycoin/dmsg/client_session.go +++ b/vendor/github.com/skycoin/dmsg/client_session.go @@ -1,11 +1,14 @@ package dmsg import ( + "errors" "net" "time" "github.com/skycoin/dmsg/cipher" "github.com/skycoin/dmsg/netutil" + + "github.com/skycoin/yamux" ) // ClientSession represents a session from the perspective of a dmsg client. @@ -82,6 +85,11 @@ func (cs *ClientSession) serve() error { Info("Failed to accept stream.") continue } + + if errors.Is(err, yamux.ErrSessionShutdown) { + cs.log.WithError(err).Info("Stopped accepting streams.") + return err + } cs.log.WithError(err).Warn("Stopped accepting streams.") return err } diff --git a/vendor/github.com/skycoin/dmsg/disc/client.go b/vendor/github.com/skycoin/dmsg/disc/client.go index f1e8582d..cb6f783c 100644 --- a/vendor/github.com/skycoin/dmsg/disc/client.go +++ b/vendor/github.com/skycoin/dmsg/disc/client.go @@ -16,8 +16,6 @@ import ( "github.com/skycoin/dmsg/cipher" ) -var log = logging.MustGetLogger("disc") - var json = jsoniter.ConfigFastest // APIClient implements dmsg discovery API client. @@ -32,26 +30,28 @@ type APIClient interface { // HTTPClient represents a client that communicates with a dmsg-discovery service through http, it // implements APIClient type httpClient struct { - client http.Client + client *http.Client address string updateMux sync.Mutex // for thread-safe sequence incrementing + log *logging.Logger } // NewHTTP constructs a new APIClient that communicates with discovery via http. -func NewHTTP(address string, client http.Client) APIClient { +func NewHTTP(address string, client *http.Client, log *logging.Logger) APIClient { log.WithField("func", "disc.NewHTTP"). WithField("addr", address). Debug("Created HTTP client.") return &httpClient{ client: client, address: address, + log: log, } } // Entry retrieves an entry associated with the given public key. func (c *httpClient) Entry(ctx context.Context, publicKey cipher.PubKey) (*Entry, error) { endpoint := fmt.Sprintf("%s/dmsg-discovery/entry/%s", c.address, publicKey) - log := log.WithField("endpoint", endpoint) + log := c.log.WithField("endpoint", endpoint) req, err := http.NewRequest(http.MethodGet, endpoint, nil) if err != nil { @@ -91,11 +91,11 @@ func (c *httpClient) Entry(ctx context.Context, publicKey cipher.PubKey) (*Entry } // PostEntry creates a new Entry. -func (c *httpClient) PostEntry(ctx context.Context, e *Entry) error { +func (c *httpClient) PostEntry(ctx context.Context, entry *Entry) error { endpoint := c.address + "/dmsg-discovery/entry/" - log := log.WithField("endpoint", endpoint) + log := c.log.WithField("endpoint", endpoint) - marshaledEntry, err := json.Marshal(e) + marshaledEntry, err := json.Marshal(entry) if err != nil { return err } @@ -145,11 +145,11 @@ func (c *httpClient) PostEntry(ctx context.Context, e *Entry) error { } // DelEntry deletes an Entry. -func (c *httpClient) DelEntry(ctx context.Context, e *Entry) error { +func (c *httpClient) DelEntry(ctx context.Context, entry *Entry) error { endpoint := c.address + "/dmsg-discovery/entry" - log := log.WithField("endpoint", endpoint) + log := c.log.WithField("endpoint", endpoint) - marshaledEntry, err := json.Marshal(e) + marshaledEntry, err := json.Marshal(entry) if err != nil { return err } @@ -246,7 +246,7 @@ func (c *httpClient) AvailableServers(ctx context.Context) ([]*Entry, error) { if resp != nil { defer func() { if err := resp.Body.Close(); err != nil { - log.WithError(err).Warn("Failed to close response body") + c.log.WithError(err).Warn("Failed to close response body") } }() } diff --git a/vendor/github.com/skycoin/dmsg/disc/entry.go b/vendor/github.com/skycoin/dmsg/disc/entry.go index ba1e4bc8..6705364d 100644 --- a/vendor/github.com/skycoin/dmsg/disc/entry.go +++ b/vendor/github.com/skycoin/dmsg/disc/entry.go @@ -270,12 +270,7 @@ func (e *Entry) Validate(validateTimestamp bool) error { latestAcceptable := now.Add(allowedEntryTimestampError) // in case when time on nodes mismatches a bit if ts.After(latestAcceptable) || ts.Before(earliestAcceptable) { - log.Warnf("Entry timestamp %v is not correct (now: %v)", ts, now) - // Skybian boards have issues with mismatching time because of https://github.com/skycoin/skybian/issues/47. - // This causes issues like https://github.com/SkycoinPro/skywire-services/issues/274. - // Therefore, the timestamp check needs to be temporarily disabled until the issue is resolved. - // - // return ErrValidationOutdatedTime + return ErrValidationOutdatedTime } } diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/cli.go b/vendor/github.com/skycoin/dmsg/dmsgpty/cli.go new file mode 100644 index 00000000..adcad548 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/cli.go @@ -0,0 +1,154 @@ +package dmsgpty + +import ( + "context" + "fmt" + "io" + "net" + "os" + "path/filepath" + "strings" + "syscall" + + "github.com/sirupsen/logrus" + "github.com/skycoin/skycoin/src/util/logging" + + "github.com/skycoin/dmsg/cipher" +) + +// CLI connects with and has ownership over a dmsgpty.Host. +type CLI struct { + Log logrus.FieldLogger `json:"-"` + Net string `json:"cli_network"` + Addr string `json:"cli_address"` +} + +// DefaultCLI returns a CLI with default values. +func DefaultCLI() CLI { + return CLI{ + Log: logging.MustGetLogger("dmsgpty-cli"), + Net: DefaultCLINet, + Addr: DefaultCLIAddr(), + } +} + +// WhitelistClient returns a client that interacts with the Host's whitelist. +func (cli *CLI) WhitelistClient() (*WhitelistClient, error) { + conn, err := cli.prepareConn() + if err != nil { + return nil, err + } + return NewWhitelistClient(conn) +} + +// StartLocalPty starts a pty on the host. +func (cli *CLI) StartLocalPty(ctx context.Context, cmd string, args ...string) error { + conn, err := cli.prepareConn() + if err != nil { + return err + } + + ptyC, err := NewPtyClient(conn) + if err != nil { + return err + } + + restore, err := cli.prepareStdin() + if err != nil { + return err + } + defer restore() + + return cli.servePty(ctx, ptyC, cmd, args) +} + +// StartRemotePty starts a pty on a remote host, proxied via the local pty. +func (cli *CLI) StartRemotePty(ctx context.Context, rPK cipher.PubKey, rPort uint16, cmd string, args ...string) error { + conn, err := cli.prepareConn() + if err != nil { + return err + } + + ptyC, err := NewProxyClient(conn, rPK, rPort) + if err != nil { + return err + } + + restore, err := cli.prepareStdin() + if err != nil { + return err + } + defer restore() + + return cli.servePty(ctx, ptyC, cmd, args) +} + +// prepareConn prepares a connection with the dmsgpty-host. +func (cli *CLI) prepareConn() (net.Conn, error) { + + // Set defaults. + if cli.Log == nil { + cli.Log = logging.MustGetLogger("dmsgpty-cli") + } + if cli.Net == "" { + cli.Net = DefaultCLINet + } + if cli.Addr == "" { + cli.Addr = DefaultCLIAddr() + } + + cli.Log. + WithField("address", fmt.Sprintf("%s://%s", cli.Net, cli.Addr)). + Infof("Requesting...") + + conn, err := net.Dial(cli.Net, cli.Addr) + if err != nil { + return nil, fmt.Errorf("failed to connect to dmsgpty-host: %v", err) + } + return conn, nil +} + +// servePty serves a pty connection via the dmsgpty-host. +func (cli *CLI) servePty(ctx context.Context, ptyC *PtyClient, cmd string, args []string) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + cli.Log. + WithField("cmd", fmt.Sprint(append([]string{cmd}, args...))). + Infof("Executing...") + + if err := ptyC.Start(cmd, args...); err != nil { + return fmt.Errorf("failed to start command on pty: %v", err) + } + + // Window resize loop. + go func() { + defer cancel() + if err := ptyResizeLoop(ctx, ptyC); err != nil { + cli.Log. + WithError(err). + Warn("Window resize loop closed with error.") + } + }() + + // Write loop. + go func() { + defer cancel() + _, _ = io.Copy(ptyC, os.Stdin) //nolint:errcheck + }() + + EioPtyErr := os.PathError{ + Op: "read", + Path: filepath.FromSlash("/dev/ptmx"), + Err: syscall.Errno(0x5), + } + + // Read loop. + if _, err := io.Copy(os.Stdout, ptyC); err != nil && strings.Compare(err.Error(), EioPtyErr.Error()) != 0 { + cli.Log. + WithError(err). + Error("Read loop closed with error.") + } + + return nil +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/cli_unix.go b/vendor/github.com/skycoin/dmsg/dmsgpty/cli_unix.go new file mode 100644 index 00000000..b9284d1d --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/cli_unix.go @@ -0,0 +1,64 @@ +//go:build !windows +// +build !windows + +package dmsgpty + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/creack/pty" + "golang.org/x/crypto/ssh/terminal" +) + +// ptyResizeLoop informs the remote of changes to the local CLI terminal window size. +func ptyResizeLoop(ctx context.Context, ptyC *PtyClient) error { + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGWINCH) + for { + select { + case <-ctx.Done(): + return nil + case <-ch: + winSize, err := getPtySize(os.Stdin) + if err != nil { + return fmt.Errorf("failed to obtain window size: %v", err) + } + ws, err := NewWinSize(winSize) + if err != nil { + return fmt.Errorf("failed to convert pty size to WinSize: %v", err) + } + if err := ptyC.SetPtySize(ws); err != nil { + return fmt.Errorf("failed to set remote window size: %v", err) + } + } + } +} + +// getPtySize obtains the size of the local terminal. +func getPtySize(t *os.File) (*pty.Winsize, error) { + return pty.GetsizeFull(t) +} + +// prepareStdin sets stdin to raw mode and provides a function to restore the original state. +func (cli *CLI) prepareStdin() (restore func(), err error) { + var oldState *terminal.State + if oldState, err = terminal.MakeRaw(int(os.Stdin.Fd())); err != nil { + cli.Log. + WithError(err). + Warn("Failed to set stdin to raw mode.") + return + } + restore = func() { + // Attempt to restore state. + if err = terminal.Restore(int(os.Stdin.Fd()), oldState); err != nil { + cli.Log. + WithError(err). + Error("Failed to restore original stdin state.") + } + } + return +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/cli_windows.go b/vendor/github.com/skycoin/dmsg/dmsgpty/cli_windows.go new file mode 100644 index 00000000..0a902240 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/cli_windows.go @@ -0,0 +1,45 @@ +//go:build windows +// +build windows + +package dmsgpty + +import ( + "context" + "sync" + "time" + + "github.com/ActiveState/termtest/conpty" +) + +// ptyResizeLoop informs the remote of changes to the local CLI terminal window size. +func ptyResizeLoop(ctx context.Context, ptyC *PtyClient) error { + t := time.NewTicker(1 * time.Second) + mu := sync.RWMutex{} + var initialSize *WinSize + for { + select { + case <-ctx.Done(): + t.Stop() + return nil + case <-t.C: + mu.Lock() + size, err := getSize() + if err == nil { + if initialSize == nil { + initialSize = size + } else if initialSize.X != size.X || initialSize.Y != size.Y { + initialSize = size + if err = ptyC.SetPtySize(initialSize); err != nil { + mu.Unlock() + return err + } + } + } + mu.Unlock() + } + } +} + +func (cli *CLI) prepareStdin() (restore func(), err error) { + return conpty.InitTerminal(true) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/conf.go b/vendor/github.com/skycoin/dmsg/dmsgpty/conf.go new file mode 100644 index 00000000..242315c6 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/conf.go @@ -0,0 +1,95 @@ +package dmsgpty + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + + "github.com/skycoin/dmsg" +) + +// Config struct is used to read the values from the config.json file +type Config struct { + DmsgDisc string `json:"dmsgdisc"` + DmsgSessions int `json:"dmsgsessions"` + DmsgPort uint16 `json:"dmsgport"` + CLINet string `json:"clinet"` + CLIAddr string `json:"cliaddr"` + SK string `json:"sk"` + PK string `json:"pk"` + WL []string `json:"wl"` +} + +// DefaultConfig is used to populate the config struct with its default values +func DefaultConfig() Config { + return Config{ + DmsgDisc: dmsg.DefaultDiscAddr, + DmsgSessions: dmsg.DefaultMinSessions, + DmsgPort: DefaultPort, + CLINet: DefaultCLINet, + CLIAddr: DefaultCLIAddr(), + } +} + +// WriteConfig write the config struct to the provided path +func WriteConfig(conf Config, path string) error { + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) //nolint:gosec + if err != nil { + return fmt.Errorf("failed to open config file: %w", err) + } + enc := json.NewEncoder(f) + enc.SetIndent("", " ") + if err = enc.Encode(&conf); err != nil { + return err + } + return f.Close() +} + +func findStringsEnclosedBy(str string, sep string, result []string, lastIndex int) ([]string, int) { + s := strings.Index(str, sep) + if s == -1 { + return result, lastIndex + } + newS := str[s+len(sep):] + e := strings.Index(newS, sep) + if e == -1 { + lastIndex += len(sep) + return result, lastIndex + } + res := newS[:e] + if res != "" { + result = append(result, res) + } + last := s + len(res) + len(sep) + if lastIndex == -1 { + lastIndex = last + } else { + lastIndex += last + } + str = str[last:] + return findStringsEnclosedBy(str, sep, result, lastIndex) +} + +// ParseWindowsEnv finds '%'-enclosed windows env in json string +func ParseWindowsEnv(cliAddr string) string { + if runtime.GOOS == "windows" { + var res []string + results, lastIndex := findStringsEnclosedBy(cliAddr, "%", res, -1) + if len(results) > 0 { + paths := make([]string, len(results)+1) + for i, s := range results { + pth := os.Getenv(strings.ToUpper(s)) + if pth != "" { + paths[i] = pth + } + } + paths[len(paths)-1] = strings.Replace(cliAddr[lastIndex:], string(filepath.Separator), "", 1) + cliAddr = filepath.Join(paths...) + _ = strings.ReplaceAll(cliAddr, `\`, `\\`) + return cliAddr + } + } + return cliAddr +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/const.go b/vendor/github.com/skycoin/dmsg/dmsgpty/const.go new file mode 100644 index 00000000..4497d753 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/const.go @@ -0,0 +1,14 @@ +package dmsgpty + +// Constants related to pty. +const ( + PtyRPCName = "pty" + PtyURI = "dmsgpty/pty" + PtyProxyURI = "dmsgpty/proxy" +) + +// Constants related to whitelist. +const ( + WhitelistRPCName = "whitelist" + WhitelistURI = "dmsgpty/whitelist" +) diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/const_unix.go b/vendor/github.com/skycoin/dmsg/dmsgpty/const_unix.go new file mode 100644 index 00000000..45b91d10 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/const_unix.go @@ -0,0 +1,26 @@ +//go:build !windows +// +build !windows + +package dmsgpty + +import ( + "os" + "path/filepath" +) + +// Constants related to CLI. +const ( + DefaultCLINet = "unix" +) + +// Constants related to dmsg. +const ( + DefaultPort = uint16(22) + DefaultCmd = "/bin/bash" + DefaultFlagExec = "-c" +) + +// DefaultCLIAddr gets the default cli address (temp address) +func DefaultCLIAddr() string { + return filepath.Join(os.TempDir(), "dmsgpty.sock") +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/const_windows.go b/vendor/github.com/skycoin/dmsg/dmsgpty/const_windows.go new file mode 100644 index 00000000..6b50532b --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/const_windows.go @@ -0,0 +1,30 @@ +//go:build windows +// +build windows + +package dmsgpty + +import ( + "os" + "path/filepath" +) + +const ( + // DefaultCLINet for windows + DefaultCLINet = "unix" +) + +// Constants related to dmsg. +const ( + DefaultPort = uint16(22) + DefaultCmd = `C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe` + DefaultFlagExec = "-Command" +) + +// DefaultCLIAddr gets the default cli address +func DefaultCLIAddr() string { + homedir, err := os.UserHomeDir() + if err != nil { + homedir = os.TempDir() + } + return filepath.Join(homedir, "dmsgpty.sock") +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/host.go b/vendor/github.com/skycoin/dmsg/dmsgpty/host.go new file mode 100644 index 00000000..7bf7fbca --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/host.go @@ -0,0 +1,260 @@ +package dmsgpty + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "net/rpc" + "net/url" + "strings" + "sync/atomic" + + "github.com/sirupsen/logrus" + "github.com/skycoin/skycoin/src/util/logging" + + "github.com/skycoin/dmsg" + "github.com/skycoin/dmsg/cipher" +) + +// Host represents the main instance of dmsgpty. +type Host struct { + dmsgC *dmsg.Client + wl Whitelist + + cliN int32 + connN int32 +} + +// NewHost creates a new dmsgpty.Host with a given dmsg.Client and whitelist. +func NewHost(dmsgC *dmsg.Client, wl Whitelist) *Host { + host := new(Host) + host.dmsgC = dmsgC + host.wl = wl + return host +} + +// ServeCLI listens for CLI connections via the provided listener. +func (h *Host) ServeCLI(ctx context.Context, lis net.Listener) error { + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + go func() { + <-ctx.Done() + _ = lis.Close() //nolint:errcheck + }() + + log := logging.MustGetLogger("dmsg_pty:cli-server") + masterLogger := h.dmsgC.MasterLogger() + if masterLogger != nil { + log = masterLogger.PackageLogger("dmsg_pty:cli-server") + } + + mux := cliEndpoints(h) + + for { + conn, err := lis.Accept() + if err != nil { + if err, ok := err.(net.Error); ok && err.Temporary() { + log.Warn("Failed to accept CLI connection with temporary error, continuing...") + continue + } + if err == io.ErrClosedPipe || strings.Contains(err.Error(), "use of closed network connection") { + log.Info("Cleanly stopped serving.") + return nil + } + log.Error("Failed to accept CLI connection with permanent error.") + return err + } + + log := log.WithField("cli_id", atomic.AddInt32(&h.cliN, 1)) + log.Info("CLI connection accepted.") + go func() { + h.serveConn(ctx, log, &mux, conn) + atomic.AddInt32(&h.cliN, -1) + }() + } +} + +// ListenAndServe serves the host over the dmsg network via the given dmsg port. +func (h *Host) ListenAndServe(ctx context.Context, port uint16) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + mux := dmsgEndpoints(h) + + lis, err := h.dmsgC.Listen(port) + if err != nil { + return err + } + + log := logging.MustGetLogger("dmsg_pty") + masterLogger := h.dmsgC.MasterLogger() + if masterLogger != nil { + log = masterLogger.PackageLogger("dmsg_pty") + } + + go func() { + <-ctx.Done() + log. + WithError(lis.Close()). + Info("Serve() ended.") + }() + + for { + stream, err := lis.AcceptStream() + if err != nil { + log := log.WithError(err) + if err, ok := err.(net.Error); ok && err.Temporary() { + log.Warn("Failed to accept dmsg.Stream with temporary error, continuing...") + continue + } + if err == io.ErrClosedPipe || err == dmsg.ErrEntityClosed || + strings.Contains(err.Error(), "use of closed network connection") { + log.Info("Cleanly stopped serving.") + return nil + } + log.Error("Failed to accept dmsg.Stream with permanent error.") + return err + } + + rPK := stream.RawRemoteAddr().PK + log := log.WithField("remote_pk", rPK.String()) + log.Info("Processing dmsg.Stream...") + + if !h.authorize(log, rPK) { + err := writeResponse(stream, + errors.New("dmsg stream rejected by whitelist")) + log.WithError(err).Warn() + + if err := stream.Close(); err != nil { + log.WithError(err).Warn("Stream closed with error.") + } + continue + } + + log = log.WithField("conn_id", atomic.AddInt32(&h.connN, 1)) + log.Info("dmsg.Stream accepted.") + log = stream.Logger().WithField("dmsgpty", "stream") + go func() { + h.serveConn(ctx, log, &mux, stream) + atomic.AddInt32(&h.connN, -1) + }() + } +} + +// serveConn serves a CLI connection or dmsg stream. +func (h *Host) serveConn(ctx context.Context, log logrus.FieldLogger, mux *hostMux, conn net.Conn) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + closeErr := make(chan error, 1) + go func() { + <-ctx.Done() + closeErr <- conn.Close() + close(closeErr) + }() + + log.WithError(mux.ServeConn(ctx, conn)). + WithField("error_close", <-closeErr). + WithField("remote_addr", conn.RemoteAddr()). + Info("Stopped serving connection.") +} + +// authorize returns true if the provided public key is whitelisted. +func (h *Host) authorize(log logrus.FieldLogger, rPK cipher.PubKey) bool { + ok, err := h.wl.Get(rPK) + if err != nil { + log.WithError(err).Panic("dmsgpty.Whitelist error.") + return false + } + if !ok { + log.Warn("Public key rejected by whitelist.") + return false + } + return true +} + +// log returns the logrus.FieldLogger that should be used for all log outputs. +func (h *Host) log() logrus.FieldLogger { + return h.dmsgC.Logger().WithField("dmsgpty", "host") +} + +/* + <<< ENDPOINTS >>> +*/ + +// cliEndpoints returns the endpoints served for CLI connections. +func cliEndpoints(h *Host) (mux hostMux) { + mux.Handle(WhitelistURI, handleWhitelist(h)) + mux.Handle(PtyURI, handlePty(h)) + mux.Handle(PtyProxyURI, handleProxy(h)) + return mux +} + +// dmsgEndpoints returns the endpoints served for remote dmsg connections. +func dmsgEndpoints(h *Host) (mux hostMux) { + mux.Handle(PtyURI, handlePty(h)) + return mux +} + +func handleWhitelist(h *Host) handleFunc { + return func(ctx context.Context, uri *url.URL, rpcS *rpc.Server) error { + return rpcS.RegisterName(WhitelistRPCName, NewWhitelistGateway(h.wl)) + } +} + +func handlePty(h *Host) handleFunc { + return func(ctx context.Context, uri *url.URL, rpcS *rpc.Server) error { + pty := NewPty() + go func() { + <-ctx.Done() + h.log(). + WithError(pty.Stop()). + Debug("PTY stopped.") + }() + return rpcS.RegisterName(PtyRPCName, NewPtyGateway(pty)) + } +} + +func handleProxy(h *Host) handleFunc { + return func(ctx context.Context, uri *url.URL, rpcS *rpc.Server) error { + q := uri.Query() + + // Get query values. + var pk cipher.PubKey + if err := pk.Set(q.Get("pk")); err != nil { + return fmt.Errorf("invalid query value 'pk': %v", err) + } + var port uint16 + if _, err := fmt.Sscan(q.Get("port"), &port); err != nil { + return fmt.Errorf("invalid query value 'port': %v", err) + } + + // Proxy request. + stream, err := h.dmsgC.DialStream(ctx, dmsg.Addr{PK: pk, Port: port}) + if err != nil { + return err + } + go func() { + <-ctx.Done() + h.log(). + WithError(stream.Close()). + Debug("Closed proxy dmsg stream.") + }() + + ptyC, err := NewPtyClient(stream) + if err != nil { + return err + } + go func() { + <-ctx.Done() + h.log(). + WithError(ptyC.Close()). + Debug("Closed proxy pty client.") + }() + return rpcS.RegisterName(PtyRPCName, NewProxyGateway(ptyC)) + } +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/host_mux.go b/vendor/github.com/skycoin/dmsg/dmsgpty/host_mux.go new file mode 100644 index 00000000..487d260d --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/host_mux.go @@ -0,0 +1,67 @@ +package dmsgpty + +import ( + "context" + "errors" + "net" + "net/rpc" + "net/url" + "path" + "strings" +) + +type muxEntry struct { + pat string + fn handleFunc +} + +type hostMux struct { + entries []muxEntry +} + +type handleFunc func(ctx context.Context, uri *url.URL, rpcS *rpc.Server) error + +func (h *hostMux) Handle(pattern string, fn handleFunc) { + pattern = strings.TrimPrefix(pattern, "/") + if _, err := path.Match(pattern, ""); err != nil { + panic(err) + } + h.entries = append(h.entries, muxEntry{ + pat: pattern, + fn: fn, + }) +} + +func (h *hostMux) ServeConn(ctx context.Context, conn net.Conn) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + go func() { + <-ctx.Done() + _ = conn.Close() //nolint:errcheck + }() + + uri, err := readRequest(conn) + if err != nil { + return writeResponse(conn, err) + } + for _, entry := range h.entries { + ok, err := path.Match(entry.pat, uri.EscapedPath()) + if err != nil { + panic(err) + } + if !ok { + continue + } + rpcS := rpc.NewServer() + if err := entry.fn(ctx, uri, rpcS); err != nil { + return err + } + if err := writeResponse(conn, nil); err != nil { + return err + } + rpcS.ServeConn(conn) + return nil + } + return writeResponse(conn, errors.New("invalid request")) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_client.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_client.go new file mode 100644 index 00000000..92deb1ab --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_client.go @@ -0,0 +1,124 @@ +package dmsgpty + +import ( + "fmt" + "io" + "net/rpc" + "sync" + + "github.com/sirupsen/logrus" + "github.com/skycoin/skycoin/src/util/logging" + + "github.com/skycoin/dmsg/cipher" +) + +// PtyClient represents the client end of a dmsgpty session. +type PtyClient struct { + log logrus.FieldLogger + rpcC *rpc.Client + done chan struct{} + once sync.Once +} + +// NewPtyClient creates a new pty client that interacts with a local pty. +func NewPtyClient(conn io.ReadWriteCloser) (*PtyClient, error) { + if err := writeRequest(conn, PtyURI); err != nil { + return nil, err + } + if err := readResponse(conn); err != nil { + return nil, err + } + return &PtyClient{ + log: logging.MustGetLogger("dmsgpty:pty-client"), + rpcC: rpc.NewClient(conn), + done: make(chan struct{}), + }, nil +} + +// NewProxyClient creates a new pty client that interacts with a remote pty hosted on the given dmsg pk and port. +// Interactions are proxied via the local dmsgpty.Host +func NewProxyClient(conn io.ReadWriteCloser, rPK cipher.PubKey, rPort uint16) (*PtyClient, error) { + uri := fmt.Sprintf("%s?pk=%s&port=%d", PtyProxyURI, rPK, rPort) + if err := writeRequest(conn, uri); err != nil { + return nil, err + } + if err := readResponse(conn); err != nil { + return nil, err + } + return &PtyClient{ + log: logging.MustGetLogger("dmsgpty:proxy-client"), + rpcC: rpc.NewClient(conn), + done: make(chan struct{}), + }, nil +} + +// Close closes the pty and closes the connection to the remote. +func (sc *PtyClient) Close() error { + if closed := sc.close(); !closed { + return nil + } + // No need to wait for reply. + _ = sc.Stop() //nolint:errcheck + return sc.rpcC.Close() +} + +func (sc *PtyClient) close() (closed bool) { + sc.once.Do(func() { + close(sc.done) + closed = true + }) + return closed +} + +// Stop stops the pty. +func (sc *PtyClient) Stop() error { + return sc.call("Stop", &empty, &empty) +} + +// Read reads from the pty. +func (sc *PtyClient) Read(b []byte) (int, error) { + reqN := len(b) + var respB []byte + err := sc.call("Read", &reqN, &respB) + return copy(b, respB), processRPCError(err) +} + +// Write writes to the pty. +func (sc *PtyClient) Write(b []byte) (int, error) { + var n int + err := sc.call("Write", &b, &n) + return n, processRPCError(err) +} + +func (*PtyClient) rpcMethod(m string) string { + return PtyRPCName + "." + m +} + +func (sc *PtyClient) call(method string, args, reply interface{}) error { + call := sc.rpcC.Go(sc.rpcMethod(method), args, reply, nil) + select { + case <-sc.done: + return io.ErrClosedPipe // TODO(evanlinjin): Is there a better error to use? + case <-call.Done: + return call.Error + } +} + +// Start starts the pty. +func (sc *PtyClient) Start(name string, arg ...string) error { + return sc.call("Start", &CommandReq{ + Name: name, + Arg: arg, + Size: nil, + }, &empty) +} + +// StartWithSize starts the pty with a specified size. +func (sc *PtyClient) StartWithSize(name string, arg []string, c *WinSize) error { + return sc.call("Start", &CommandReq{Name: name, Arg: arg, Size: c}, &empty) +} + +// SetPtySize sets the pty size. +func (sc *PtyClient) SetPtySize(size *WinSize) error { + return sc.call("SetPtySize", size, &empty) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_client_windows.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_client_windows.go new file mode 100644 index 00000000..c4a5e7cc --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_client_windows.go @@ -0,0 +1,32 @@ +//go:build windows +// +build windows + +package dmsgpty + +import ( + "errors" + + "golang.org/x/sys/windows" +) + +// getSize gets windows terminal size +func getSize() (*WinSize, error) { + var bufInfo windows.ConsoleScreenBufferInfo + c, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE) + if err != nil { + return nil, err + } + if err = windows.GetConsoleScreenBufferInfo(c, &bufInfo); err != nil { + if errors.Is(err, windows.ERROR_INVALID_HANDLE) { + return &WinSize{ + X: 80, + Y: 30, + }, nil + } + return nil, err + } + return NewWinSize(&windows.Coord{ + X: bufInfo.Window.Right - bufInfo.Window.Left + 1, + Y: bufInfo.Window.Bottom - bufInfo.Window.Top + 1, + }) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway.go new file mode 100644 index 00000000..cf6aab88 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway.go @@ -0,0 +1,105 @@ +package dmsgpty + +// WinSize wraps around pty.Winsize and *windows.Coord +type WinSize struct { + X uint16 + Y uint16 + Rows uint16 + Cols uint16 +} + +// PtyGateway represents a pty gateway, hosted by the pty.SessionServer +type PtyGateway interface { + Start(req *CommandReq, _ *struct{}) error + Stop(_, _ *struct{}) error + Read(reqN *int, respB *[]byte) error + Write(reqB *[]byte, respN *int) error + SetPtySize(size *WinSize, _ *struct{}) error +} + +// CommandReq represents a pty command. +type CommandReq struct { + Name string + Arg []string + Size *WinSize +} + +// LocalPtyGateway is the gateway to a local pty. +type LocalPtyGateway struct { + ses *Pty +} + +// NewPtyGateway creates a new gateway to a local pty. +func NewPtyGateway(ses *Pty) PtyGateway { + return &LocalPtyGateway{ses: ses} +} + +// Stop stops the local pty. +func (g *LocalPtyGateway) Stop(_, _ *struct{}) error { + return g.ses.Stop() +} + +// Read reads from the local pty. +func (g *LocalPtyGateway) Read(reqN *int, respB *[]byte) error { + b := make([]byte, *reqN) + n, err := g.ses.Read(b) + *respB = b[:n] + return err +} + +// Start starts the local pty. +func (g *LocalPtyGateway) Start(req *CommandReq, _ *struct{}) error { + return g.ses.Start(req.Name, req.Arg, req.Size) +} + +// Write writes to the local pty. +func (g *LocalPtyGateway) Write(wb *[]byte, n *int) error { + var err error + *n, err = g.ses.Write(*wb) + return err +} + +// SetPtySize sets the local pty's window size. +func (g *LocalPtyGateway) SetPtySize(size *WinSize, _ *struct{}) error { + return g.ses.SetPtySize(size) +} + +// SetPtySize sets the remote pty's window size. +func (g *ProxiedPtyGateway) SetPtySize(size *WinSize, _ *struct{}) error { + return g.ptyC.SetPtySize(size) +} + +// ProxiedPtyGateway is an RPC gateway for a remote pty. +type ProxiedPtyGateway struct { + ptyC *PtyClient +} + +// NewProxyGateway creates a new pty-proxy gateway +func NewProxyGateway(ptyC *PtyClient) PtyGateway { + return &ProxiedPtyGateway{ptyC: ptyC} +} + +// Start starts the remote pty. +func (g *ProxiedPtyGateway) Start(req *CommandReq, _ *struct{}) error { + return g.ptyC.Start(req.Name, req.Arg...) +} + +// Stop stops the remote pty. +func (g *ProxiedPtyGateway) Stop(_, _ *struct{}) error { + return g.ptyC.Stop() +} + +// Read reads from the remote pty. +func (g *ProxiedPtyGateway) Read(reqN *int, respB *[]byte) error { + b := make([]byte, *reqN) + n, err := g.ptyC.Read(b) + *respB = b[:n] + return err +} + +// Write writes to the remote pty. +func (g *ProxiedPtyGateway) Write(reqB *[]byte, respN *int) error { + var err error + *respN, err = g.ptyC.Write(*reqB) + return err +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway_unix.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway_unix.go new file mode 100644 index 00000000..125a216b --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway_unix.go @@ -0,0 +1,33 @@ +//go:build !windows +// +build !windows + +package dmsgpty + +import ( + "errors" + + "github.com/creack/pty" +) + +// NewWinSize creates a new WinSize wrapper object +func NewWinSize(w *pty.Winsize) (*WinSize, error) { + if w == nil { + return nil, errors.New("pty size cannot be nil") + } + return &WinSize{ + X: w.X, + Y: w.Y, + Rows: w.Rows, + Cols: w.Cols, + }, nil +} + +// PtySize returns *pty.Winsize +func (w *WinSize) PtySize() *pty.Winsize { + return &pty.Winsize{ + Rows: w.Rows, + Cols: w.Cols, + X: w.X, + Y: w.Y, + } +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway_windows.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway_windows.go new file mode 100644 index 00000000..73028387 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_gateway_windows.go @@ -0,0 +1,29 @@ +//go:build windows +// +build windows + +package dmsgpty + +import ( + "errors" + + "golang.org/x/sys/windows" +) + +// NewWinSize creates a new WinSize object +func NewWinSize(w *windows.Coord) (*WinSize, error) { + if w == nil { + return nil, errors.New("pty size is nil") + } + return &WinSize{ + X: uint16(w.X), + Y: uint16(w.Y), + }, nil +} + +// PtySize returns *windows.Coord object +func (w *WinSize) PtySize() *windows.Coord { + return &windows.Coord{ + X: int16(w.X), + Y: int16(w.Y), + } +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_unix.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_unix.go new file mode 100644 index 00000000..ad0696a9 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_unix.go @@ -0,0 +1,111 @@ +//go:build !windows +// +build !windows + +package dmsgpty + +import ( + "errors" + "os" + "os/exec" + "sync" + + "github.com/creack/pty" +) + +// Pty errors. +var ( + ErrPtyAlreadyRunning = errors.New("a pty session is already running") + ErrPtyNotRunning = errors.New("no active pty session") +) + +// Pty runs a local pty. +type Pty struct { + pty *os.File + mx sync.RWMutex +} + +// NewPty creates a new Pty. +func NewPty() *Pty { + return new(Pty) +} + +// Stop stops the running command and closes the pty. +func (s *Pty) Stop() error { + s.mx.Lock() + defer s.mx.Unlock() + + if s.pty == nil { + return ErrPtyNotRunning + } + + err := s.pty.Close() + s.pty = nil + return err +} + +// Read reads any stdout or stderr outputs from the pty. +func (s *Pty) Read(b []byte) (int, error) { + s.mx.RLock() + defer s.mx.RUnlock() + + if s.pty == nil { + return 0, ErrPtyNotRunning + } + + return s.pty.Read(b) +} + +// Write writes to the stdin of the pty. +func (s *Pty) Write(b []byte) (int, error) { + s.mx.RLock() + defer s.mx.RUnlock() + + if s.pty == nil { + return 0, ErrPtyNotRunning + } + + return s.pty.Write(b) +} + +// Start runs a command with the given command name, args and optional window size. +func (s *Pty) Start(name string, args []string, size *WinSize) error { + s.mx.Lock() + defer s.mx.Unlock() + + if s.pty != nil { + return ErrPtyAlreadyRunning + } + + cmd := exec.Command(name, args...) //nolint:gosec + cmd.Env = os.Environ() + var sz *pty.Winsize + var err error + + if size == nil { + sz = nil + } else { + sz = size.PtySize() + } + + f, err := pty.StartWithSize(cmd, sz) //nolint:gosec + if err != nil { + return err + } + + s.pty = f + return nil +} + +// SetPtySize sets the pty size. +func (s *Pty) SetPtySize(size *WinSize) error { + s.mx.RLock() + defer s.mx.RUnlock() + + if s.pty == nil { + return ErrPtyNotRunning + } + + sz := size.PtySize() + + return pty.Setsize(s.pty, sz) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/pty_windows.go b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_windows.go new file mode 100644 index 00000000..5c221216 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/pty_windows.go @@ -0,0 +1,122 @@ +//go:build windows +// +build windows + +package dmsgpty + +import ( + "errors" + "os" + "sync" + "syscall" + + "github.com/ActiveState/termtest/conpty" +) + +// Pty errors. +var ( + ErrPtyAlreadyRunning = errors.New("a pty session is already running") + ErrPtyNotRunning = errors.New("no active pty session") +) + +// Pty runs a local pty. +type Pty struct { + pty *conpty.ConPty + mx sync.RWMutex +} + +// NewPty creates a new Pty. +func NewPty() *Pty { + return new(Pty) +} + +// Stop stops the running command and closes the pty. +func (s *Pty) Stop() error { + s.mx.Lock() + defer s.mx.Unlock() + + if s.pty == nil { + return ErrPtyNotRunning + } + + err := s.pty.Close() + s.pty = nil + return err +} + +// Read reads any stdout or stderr outputs from the pty. +func (s *Pty) Read(b []byte) (int, error) { + s.mx.RLock() + defer s.mx.RUnlock() + + if s.pty == nil { + return 0, ErrPtyNotRunning + } + + return s.pty.OutPipe().Read(b) +} + +// Write writes to the stdin of the pty. +func (s *Pty) Write(b []byte) (int, error) { + s.mx.RLock() + defer s.mx.RUnlock() + + if s.pty == nil { + return 0, ErrPtyNotRunning + } + + res, err := s.pty.Write(b) + return int(res), err +} + +// Start runs a command with the given command name, args and optional window size. +func (s *Pty) Start(name string, args []string, size *WinSize) error { + s.mx.Lock() + defer s.mx.Unlock() + + if s.pty != nil { + return ErrPtyAlreadyRunning + } + + var err error + + if size == nil { + size, err = getSize() + if err != nil { + return err + } + + } + pty, err := conpty.New( + int16(size.X), int16(size.Y), + ) + if err != nil { + return err + } + + _, _, err = pty.Spawn( + name, + args, + &syscall.ProcAttr{ + Env: os.Environ(), + }, + ) + + if err != nil { + return err + } + + s.pty = pty + return nil +} + +// SetPtySize sets the pty size. +func (s *Pty) SetPtySize(size *WinSize) error { + s.mx.RLock() + defer s.mx.RUnlock() + + if s.pty == nil { + return ErrPtyNotRunning + } + + return s.pty.Resize(size.X, size.Y) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/rpc_util.go b/vendor/github.com/skycoin/dmsg/dmsgpty/rpc_util.go new file mode 100644 index 00000000..3f6c78b0 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/rpc_util.go @@ -0,0 +1,97 @@ +package dmsgpty + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "math" + "net/url" +) + +// empty is used for RPC calls. +var empty struct{} + +func processRPCError(err error) error { + if err != nil { + switch err.Error() { + case io.EOF.Error(): + return io.EOF + case io.ErrUnexpectedEOF.Error(): + return io.ErrUnexpectedEOF + case io.ErrClosedPipe.Error(): + return io.ErrClosedPipe + case io.ErrNoProgress.Error(): + return io.ErrNoProgress + case io.ErrShortBuffer.Error(): + return io.ErrShortBuffer + case io.ErrShortWrite.Error(): + return io.ErrShortWrite + default: + return err + } + } + return nil +} + +func writeRequest(rw io.ReadWriter, uri string) error { + l := len(uri) + if l > math.MaxUint8 { + return fmt.Errorf("request URI cannot be larger than %d bytes", math.MaxUint8) + } + bufW := bufio.NewWriter(rw) + if err := bufW.WriteByte(byte(l)); err != nil { + return err + } + if _, err := bufW.WriteString(uri); err != nil { + return err + } + return bufW.Flush() +} + +// readRequest reads the request. +// Each request must be smaller than 255 bytes. +func readRequest(r io.Reader) (*url.URL, error) { + prefix := make([]byte, 1) + if _, err := io.ReadFull(r, prefix); err != nil { + return nil, fmt.Errorf("failed to read prefix: %v", err) + } + + rawURI := make([]byte, prefix[0]) + if _, err := io.ReadFull(r, rawURI); err != nil { + return nil, fmt.Errorf("failed to read URI: %v", err) + } + rawURI = bytes.TrimPrefix(rawURI, []byte{'/'}) + + uri, err := url.Parse(string(rawURI)) + if err != nil { + return nil, fmt.Errorf("failed to parse URI: %v", err) + } + return uri, nil +} + +func writeResponse(w io.Writer, err error) error { + if err != nil { + // reject + _, _ = w.Write([]byte{1}) //nolint:errcheck + return fmt.Errorf("rejected request: %v", err) + } + + // accept + if _, err := w.Write([]byte{0}); err != nil { + return fmt.Errorf("failed to send response: %v", err) + } + return nil +} + +func readResponse(r io.Reader) error { + rawR := make([]byte, 1) + if _, err := io.ReadFull(r, rawR); err != nil { + return fmt.Errorf("failed to read response: %v", err) + } + if rawR[0] != 0 { + return errors.New("request rejected by remote dmsgpty-host") + } + return nil +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/ui.go b/vendor/github.com/skycoin/dmsg/dmsgpty/ui.go new file mode 100644 index 00000000..b75d52c4 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/ui.go @@ -0,0 +1,236 @@ +package dmsgpty + +import ( + "bytes" + "fmt" + "io" + "net" + "net/http" + "sync" + "sync/atomic" + "time" + + "github.com/sirupsen/logrus" + "github.com/skycoin/skycoin/src/util/logging" + "nhooyr.io/websocket" + + "github.com/skycoin/dmsg/httputil" +) + +const ( + wsCols = 100 + wsRows = 30 +) + +// UIConfig configures the dmsgpty-ui. +type UIConfig struct { + CmdName string + CmdArgs []string +} + +// DefaultUIConfig returns the default UI config. +func DefaultUIConfig() UIConfig { + return UIConfig{ + CmdName: DefaultCmd, + CmdArgs: nil, + } +} + +// UI connects to a dmsgpty-host and exposes a pty via a web UI. +type UI struct { + log logrus.FieldLogger + conf UIConfig + dialer UIDialer +} + +// NewUI creates a new dmsgpty-ui was a given dailer and config. +func NewUI(dialer UIDialer, conf UIConfig) *UI { + if dialer == nil { + panic("NewUI: dialer cannot be nil") + } + return &UI{ + log: logging.MustGetLogger("dmsgpty-ui"), + conf: conf, + dialer: dialer, + } +} + +// Logger returns the internal logger. +func (ui *UI) Logger() logrus.FieldLogger { + return ui.log +} + +// SetLogger sets the internal logger. +// This should be called before serving .Handler() +func (ui *UI) SetLogger(log logrus.FieldLogger) { + ui.log = log +} + +func (ui *UI) writeBanner(w io.Writer, uiAddr string, sID int32) error { + format := ` +██████╗ ███╗ ███╗███████╗ ██████╗ ██████╗ ████████╗██╗ ██╗ ██╗ ██╗██╗ +██╔══██╗████╗ ████║██╔════╝██╔════╝ ██╔══██╗╚══██╔══╝╚██╗ ██╔╝ ██║ ██║██║ +██║ ██║██╔████╔██║███████╗██║ ███╗██████╔╝ ██║ ╚████╔╝█████╗██║ ██║██║ +██║ ██║██║╚██╔╝██║╚════██║██║ ██║██╔═══╝ ██║ ╚██╔╝ ╚════╝██║ ██║██║ +██████╔╝██║ ╚═╝ ██║███████║╚██████╔╝██║ ██║ ██║ ╚██████╔╝██║ +╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ +╔═════════════════════════════════════════════════════════════════════════════╗ +║ PTY-HOST : %s +║ UI-URL : %s +║ UI-SID : %d +╚═════════════════════════════════════════════════════════════════════════════╝ +` + var b bytes.Buffer + if _, err := fmt.Fprintf(&b, format, ui.dialer.AddrString(), uiAddr, sID); err != nil { + panic(err) + } + for { + line, err := b.ReadBytes('\n') + if err != nil { + if err == io.EOF { + err = nil + } + return err + } + if _, err := w.Write(append(line, '\r')); err != nil { + return err + } + } +} + +// Handler returns a http handler that serves the dmsgpty-ui. +func (ui *UI) Handler() http.HandlerFunc { + var sc int32 // session counter + + return func(w http.ResponseWriter, r *http.Request) { + log := ui.log.WithField("remote_addr", r.RemoteAddr) + + // ensure http method is GET + if r.Method != http.MethodGet { + err := fmt.Errorf("http method %s is invalid for path %s", r.Method, r.URL.EscapedPath()) + writeError(log, w, r, err, http.StatusMethodNotAllowed) + return + } + + // serve web page + if !isWebsocket(r.Header) { + n, err := writeTermHTML(w) + logrus.WithError(err). + WithField("bytes", n). + Info("Served web page.") + return + } + + // serve terminal + sID := atomic.AddInt32(&sc, 1) + log = log.WithField("ui_sid", sID) + log.Info("Serving terminal websocket...") + defer func() { log.Infof("Terminal closed: %d terminals left open.", atomic.AddInt32(&sc, -1)+1) }() + + // open websocket + ws, err := websocket.Accept(w, r, nil) + if err != nil { + log.WithError(err).Warn("Failed to upgrade to websocket.") + return + } + defer func() { log.WithError(ws.Close(websocket.StatusNormalClosure, "closed")).Debug("Closed ws.") }() + + wsConn := websocket.NetConn(r.Context(), ws, websocket.MessageText) + + // open pty + logWS(wsConn, "Dialing...") + ptyConn, err := ui.dialer.Dial() + if err != nil { + writeWSError(log, wsConn, err) + return + } + defer func() { log.WithError(ptyConn.Close()).Debug("Closed ptyConn.") }() + + logWS(wsConn, "Opening pty...") + ptyC, err := NewPtyClient(ptyConn) + if err != nil { + writeWSError(log, wsConn, err) + return + } + defer func() { log.WithError(ptyC.Close()).Debug("Closed ptyC.") }() + + if err = ui.uiStartSize(ptyC); err != nil { + log.Print("xxxx") + + writeWSError(log, wsConn, err) + return + } + + uiAddr := fmt.Sprintf("(%s) %s%s", r.Proto, r.Host, r.URL.Path) + if err := ui.writeBanner(wsConn, uiAddr, sID); err != nil { + err := fmt.Errorf("failed to write banner: %w", err) + writeWSError(log, wsConn, err) + return + } + + // websocket keep alive + go func() { + for { + if _, err := wsConn.Write([]byte("\x00")); err != nil { + return + } + time.Sleep(10 * time.Second) + } + }() + + // io + done, once := make(chan struct{}), new(sync.Once) + closeDone := func() { once.Do(func() { close(done) }) } + go func() { + _, _ = io.Copy(wsConn, ptyC) //nolint:errcheck + closeDone() + }() + go func() { + _, _ = io.Copy(ptyC, wsConn) //nolint:errcheck + closeDone() + }() + <-done + } +} + +func isWebsocket(h http.Header) bool { + return h.Get("Upgrade") == "websocket" +} + +// ErrorJSON displays errors in JSON format. +type ErrorJSON struct { + ErrorCode int `json:"error_code"` + ErrorMsg string `json:"error_msg"` +} + +func logWS(conn net.Conn, msg string) { + _, _ = fmt.Fprintf(conn, "[dmsgpty-ui] Status: %s\r", msg) //nolint:errcheck +} + +func writeWSError(log logrus.FieldLogger, wsConn net.Conn, err error) { + log.WithError(err). + WithField("remote_addr", wsConn.RemoteAddr()). + Error() + errB := append([]byte("[dmsgpty-ui] Error: "+err.Error()), '\n', '\r') + if _, err := wsConn.Write(errB); err != nil { + log.WithError(err).Error("Failed to write error msg to ws conn.") + } + logWS(wsConn, "Stopped!") + for { + if _, err := wsConn.Write([]byte("\x00")); err != nil { + return + } + time.Sleep(10 * time.Second) + } +} + +func writeError(log logrus.FieldLogger, w http.ResponseWriter, r *http.Request, err error, code int) { + log.WithError(err). + WithField("http_status", code). + WithField("remote_addr", r.RemoteAddr). + Error() + httputil.WriteJSON(w, r, code, ErrorJSON{ + ErrorCode: code, + ErrorMsg: err.Error(), + }) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/ui_dialer.go b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_dialer.go new file mode 100644 index 00000000..975b01f2 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_dialer.go @@ -0,0 +1,50 @@ +package dmsgpty + +import ( + "context" + "net" + + "github.com/skycoin/dmsg" +) + +// UIDialer represents a dialer for dmsgpty-ui. +type UIDialer interface { + Dial() (net.Conn, error) + AddrString() string +} + +// DmsgUIDialer returns a UIDialer that dials with dmsg. +func DmsgUIDialer(dmsgC *dmsg.Client, rAddr dmsg.Addr) UIDialer { + return &dmsgUIDialer{dmsgC: dmsgC, rAddr: rAddr} +} + +// NetUIDialer returns a UIDialer that dials with stdlib net. +func NetUIDialer(network, address string) UIDialer { + return &netUIDialer{network: network, address: address} +} + +type dmsgUIDialer struct { + dmsgC *dmsg.Client + rAddr dmsg.Addr +} + +func (d *dmsgUIDialer) Dial() (net.Conn, error) { + return d.dmsgC.Dial(context.Background(), d.rAddr) +} + +func (d *dmsgUIDialer) AddrString() string { + return d.rAddr.String() +} + +type netUIDialer struct { + network string + address string +} + +func (d *netUIDialer) Dial() (net.Conn, error) { + return net.Dial(d.network, d.address) +} + +func (d *netUIDialer) AddrString() string { + return d.address +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/ui_html.go b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_html.go new file mode 100644 index 00000000..810489cf --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_html.go @@ -0,0 +1,2881 @@ +package dmsgpty + +import ( + "bytes" + "compress/gzip" + "io" +) + +// writeTermHTML returns raw, uncompressed file data. +// This is copied from https://github.com/progrium/termshare +func writeTermHTML(w io.Writer) (int64, error) { + gz, err := gzip.NewReader(bytes.NewBuffer([]byte{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x00, 0xff, 0xec, 0xfd, + 0xfb, 0x7f, 0x1b, 0x37, 0xae, 0x38, 0x80, 0xfe, 0xee, 0xbf, 0x82, 0xcd, + 0xee, 0xa9, 0xe4, 0x46, 0x92, 0x25, 0xf9, 0x11, 0x3f, 0xf2, 0x38, 0x8e, + 0xed, 0x34, 0xde, 0xfa, 0x75, 0x2c, 0x27, 0x6d, 0x8f, 0x37, 0xdb, 0x8e, + 0xa4, 0x91, 0x3d, 0x89, 0xa4, 0x51, 0x67, 0x46, 0xb6, 0xb5, 0x6d, 0xfa, + 0xb7, 0x5f, 0x00, 0x7c, 0x73, 0x38, 0xd2, 0xc8, 0x49, 0xf7, 0x7b, 0x3e, + 0xf7, 0x5e, 0xb7, 0xb1, 0x25, 0x3e, 0x40, 0x10, 0x04, 0x49, 0x10, 0x00, + 0xc1, 0xe7, 0xdf, 0xf4, 0xe3, 0x5e, 0x36, 0x9b, 0x84, 0xec, 0x36, 0x1b, + 0x0d, 0x5f, 0xae, 0x3c, 0x4f, 0xb3, 0xd9, 0x30, 0x7c, 0xb9, 0xc2, 0x58, + 0x37, 0xee, 0xcf, 0xd8, 0xef, 0xac, 0x1b, 0xf4, 0x3e, 0xdd, 0x24, 0xf1, + 0x74, 0xdc, 0xdf, 0x65, 0x7f, 0x6b, 0x36, 0x9b, 0x7b, 0xec, 0x33, 0x64, + 0x36, 0xb2, 0x30, 0x19, 0x45, 0xe3, 0x60, 0x08, 0x25, 0x06, 0xf1, 0x38, + 0xab, 0xa7, 0xd1, 0xbf, 0xc3, 0x5d, 0xd6, 0xda, 0x9a, 0x3c, 0x60, 0x81, + 0xe7, 0x6b, 0x02, 0xcc, 0xf3, 0xb4, 0x97, 0x44, 0x93, 0xec, 0xe5, 0xca, + 0x5e, 0x75, 0x30, 0x1d, 0xf7, 0xb2, 0x28, 0x1e, 0x57, 0x57, 0xd9, 0xef, + 0x00, 0xe1, 0x3e, 0x1a, 0xf7, 0xe3, 0xfb, 0x46, 0x3c, 0x1e, 0xc6, 0x41, + 0x9f, 0xbd, 0x60, 0x4e, 0x36, 0x63, 0x77, 0x41, 0xc2, 0x26, 0x49, 0x9c, + 0xc5, 0xbd, 0x78, 0x08, 0xf9, 0xd5, 0x61, 0xdc, 0x0b, 0xb0, 0x40, 0x43, + 0x27, 0xbe, 0x60, 0x4f, 0x6e, 0xb3, 0x6c, 0x92, 0xee, 0x3e, 0x59, 0x65, + 0xaf, 0xd8, 0x93, 0xfb, 0x34, 0x7d, 0xc2, 0x76, 0xf1, 0xef, 0x13, 0x05, + 0x21, 0x8d, 0x7b, 0x9f, 0xc2, 0x0c, 0xea, 0x8f, 0xc3, 0x7b, 0xf6, 0x63, + 0xd8, 0xed, 0xd0, 0xf7, 0xaa, 0x84, 0xf1, 0xf4, 0xc9, 0xee, 0xda, 0xda, + 0x93, 0xa7, 0x0a, 0xf6, 0x6d, 0x9c, 0x66, 0xfa, 0xdb, 0x24, 0xc8, 0x6e, + 0xc7, 0xc1, 0x28, 0x5c, 0xdd, 0x23, 0x78, 0x1c, 0x16, 0xa0, 0x1c, 0x4f, + 0xc2, 0xb1, 0x0f, 0x65, 0xde, 0x24, 0x92, 0x46, 0x34, 0x78, 0x25, 0xa8, + 0x54, 0x95, 0xf9, 0x8c, 0x41, 0xa3, 0x29, 0x10, 0xaa, 0xd9, 0xac, 0xa9, + 0xa4, 0x24, 0xbe, 0x87, 0xa4, 0x75, 0x23, 0x65, 0x9a, 0x86, 0x1d, 0x24, + 0xe0, 0x2e, 0xcb, 0x92, 0x69, 0xa8, 0xd3, 0x81, 0x9a, 0x61, 0x38, 0xfe, + 0x21, 0x9c, 0xa5, 0x3c, 0x47, 0x64, 0x7c, 0x16, 0x08, 0x32, 0x6a, 0x1b, + 0x10, 0xac, 0x56, 0xfa, 0x41, 0x16, 0x54, 0x6a, 0x1a, 0x45, 0xfc, 0x0e, + 0x68, 0xca, 0x3e, 0xa4, 0xe1, 0xb8, 0xcf, 0xd3, 0xf6, 0x72, 0xb5, 0xa1, + 0x73, 0x55, 0x60, 0x8a, 0xe9, 0x28, 0x1c, 0x67, 0x0d, 0xe4, 0x02, 0x95, + 0xaf, 0x08, 0x30, 0x0a, 0xd3, 0x34, 0xb8, 0x09, 0x4d, 0x1a, 0x84, 0x77, + 0x50, 0x1c, 0x5b, 0x20, 0x20, 0xf7, 0x49, 0x94, 0x85, 0x3c, 0xad, 0x21, + 0x9b, 0xc9, 0x41, 0xe9, 0x0d, 0xe3, 0x34, 0x74, 0xe8, 0xc8, 0xab, 0xf7, + 0xc3, 0x34, 0x4b, 0xe2, 0x59, 0x55, 0x57, 0x43, 0xa6, 0x83, 0x8f, 0x9f, + 0x57, 0x1b, 0xbd, 0x60, 0x38, 0xac, 0x66, 0xb7, 0x51, 0x0a, 0x68, 0x01, + 0x9f, 0x09, 0xfe, 0x52, 0x8c, 0xb6, 0xf6, 0xdd, 0x77, 0x2b, 0xec, 0x3b, + 0x0e, 0xe6, 0x63, 0xca, 0xea, 0x2c, 0x18, 0xb3, 0x07, 0x1a, 0x92, 0x70, + 0x34, 0x1d, 0x06, 0x59, 0x9c, 0x60, 0xf6, 0x41, 0x3c, 0x99, 0x25, 0xd1, + 0xcd, 0x6d, 0xc6, 0xaa, 0xbd, 0x55, 0xd6, 0x6e, 0xb6, 0xda, 0x75, 0xf8, + 0xb5, 0x5e, 0x63, 0x07, 0xb7, 0x49, 0x94, 0x66, 0xf1, 0xe4, 0x36, 0x4c, + 0xd8, 0x3f, 0xc2, 0xc1, 0x20, 0x09, 0x67, 0xac, 0x7a, 0x7a, 0x7c, 0xc5, + 0x4e, 0xa2, 0x5e, 0x38, 0x4e, 0xc3, 0x55, 0xac, 0xcd, 0x99, 0x6e, 0x6d, + 0xed, 0x26, 0xca, 0x6e, 0xa7, 0xdd, 0x46, 0x2f, 0x1e, 0xad, 0xf5, 0x6e, + 0x3f, 0x7e, 0x5c, 0x13, 0x8d, 0x42, 0x11, 0x2c, 0x75, 0x81, 0x83, 0x9f, + 0xa6, 0xd0, 0x31, 0x16, 0xa5, 0x0c, 0x00, 0x86, 0xdd, 0x19, 0xbb, 0x49, + 0x82, 0x71, 0x16, 0xf6, 0x61, 0x64, 0x60, 0x24, 0x59, 0x3c, 0x60, 0xbd, + 0xdb, 0x20, 0xb9, 0x09, 0x6b, 0x2c, 0x8b, 0x01, 0xd3, 0x19, 0x9b, 0x84, + 0x49, 0x0a, 0x15, 0xe2, 0x6e, 0x16, 0x44, 0xe3, 0x68, 0x7c, 0xc3, 0x02, + 0xe0, 0x98, 0xc9, 0x0c, 0xe1, 0x41, 0x61, 0xec, 0x36, 0xd0, 0x6f, 0x90, + 0xdd, 0x07, 0x49, 0x08, 0xe5, 0xfb, 0x2c, 0x48, 0x81, 0x9c, 0x51, 0x00, + 0x20, 0x99, 0x1c, 0x33, 0xe2, 0x5d, 0x36, 0x88, 0x86, 0x61, 0xca, 0x80, + 0x50, 0x21, 0x7b, 0xd2, 0x11, 0x35, 0x9e, 0xac, 0x52, 0x3b, 0xfd, 0x30, + 0x18, 0x22, 0xc0, 0x68, 0xcc, 0x30, 0x5b, 0xe6, 0xc2, 0x94, 0xcc, 0x6e, + 0xe3, 0x69, 0xc6, 0x12, 0xa4, 0x7e, 0x44, 0x43, 0x52, 0x83, 0x42, 0xbd, + 0xe1, 0xb4, 0x8f, 0x98, 0xc8, 0xec, 0x61, 0x34, 0x8a, 0x44, 0x23, 0x58, + 0x9d, 0xc8, 0x98, 0x12, 0xcd, 0x63, 0x64, 0xdc, 0x1a, 0x21, 0x5c, 0x63, + 0xa3, 0xb8, 0x1f, 0x0d, 0xf0, 0x6f, 0x48, 0xfd, 0x9b, 0x4c, 0xbb, 0xc3, + 0x28, 0xbd, 0xad, 0xb1, 0x7e, 0x84, 0xd0, 0xbb, 0xd3, 0x0c, 0x12, 0x53, + 0x4c, 0x24, 0xba, 0xd6, 0xb0, 0x37, 0x6b, 0x31, 0x4c, 0xd8, 0x70, 0x48, + 0xc8, 0x01, 0x90, 0x08, 0x3a, 0x40, 0x9d, 0xd6, 0x38, 0x52, 0x31, 0x6c, + 0x68, 0x82, 0xc4, 0xcd, 0x04, 0xb9, 0x52, 0x4c, 0xb9, 0xbf, 0x8d, 0x47, + 0x76, 0x7f, 0x22, 0xc2, 0x6a, 0x30, 0x4d, 0xc6, 0xd0, 0x70, 0x48, 0xd5, + 0xfa, 0x31, 0x90, 0x8f, 0xda, 0xfd, 0x18, 0xf6, 0x32, 0x4c, 0xc1, 0x1a, + 0x83, 0x78, 0x38, 0x8c, 0xef, 0xb1, 0x8f, 0xbd, 0x78, 0xdc, 0x8f, 0xb0, + 0x6b, 0xe9, 0xae, 0x18, 0xc5, 0x2b, 0xc8, 0x0f, 0xba, 0xf1, 0x5d, 0x48, + 0xdd, 0xe2, 0x3c, 0x33, 0x8e, 0x33, 0xc0, 0x9a, 0xa3, 0x82, 0x23, 0x32, + 0xd1, 0x23, 0x2d, 0xb2, 0xd2, 0x5b, 0xe0, 0x52, 0xd6, 0x0d, 0x05, 0xf9, + 0xa0, 0xf1, 0x68, 0x8c, 0xd0, 0x30, 0x55, 0xf6, 0x2c, 0x41, 0x34, 0xd2, + 0x0c, 0xf8, 0x21, 0x82, 0x75, 0x74, 0x12, 0x27, 0xd4, 0xae, 0xdb, 0xe3, + 0x86, 0xc4, 0xe3, 0xed, 0x11, 0xeb, 0x9c, 0xbf, 0xb9, 0xfa, 0x71, 0xff, + 0xf2, 0x88, 0x1d, 0x77, 0xd8, 0xc5, 0xe5, 0xf9, 0xfb, 0xe3, 0xc3, 0xa3, + 0x43, 0xf6, 0x64, 0xbf, 0x03, 0xdf, 0x9f, 0xd4, 0xd8, 0x8f, 0xc7, 0x57, + 0x6f, 0xcf, 0xdf, 0x5d, 0x31, 0x28, 0x71, 0xb9, 0x7f, 0x76, 0xf5, 0x33, + 0x3b, 0x7f, 0xc3, 0xf6, 0xcf, 0x7e, 0x66, 0x3f, 0x1c, 0x9f, 0x1d, 0xd6, + 0xd8, 0xd1, 0x4f, 0x17, 0x97, 0x47, 0x9d, 0x0e, 0x3b, 0xbf, 0x44, 0x68, + 0xc7, 0xa7, 0x17, 0x27, 0xc7, 0x47, 0x90, 0x7c, 0x7c, 0x76, 0x70, 0xf2, + 0xee, 0xf0, 0xf8, 0xec, 0x7b, 0xf6, 0x1a, 0xaa, 0x9e, 0x9d, 0x03, 0xa3, + 0x1f, 0x03, 0xbb, 0x03, 0xdc, 0xab, 0x73, 0x6a, 0x53, 0x40, 0x3b, 0x3e, + 0xea, 0x20, 0xbc, 0xd3, 0xa3, 0xcb, 0x83, 0xb7, 0xf0, 0x75, 0xff, 0xf5, + 0xf1, 0xc9, 0xf1, 0xd5, 0xcf, 0x35, 0x84, 0xf5, 0xe6, 0xf8, 0xea, 0x0c, + 0x21, 0xbf, 0x39, 0xbf, 0x64, 0xfb, 0xec, 0x62, 0xff, 0xf2, 0xea, 0xf8, + 0xe0, 0xdd, 0xc9, 0xfe, 0x25, 0xbb, 0x78, 0x77, 0x79, 0x71, 0xde, 0x39, + 0x02, 0x24, 0x0e, 0x01, 0xf2, 0xd9, 0xf1, 0xd9, 0x9b, 0x4b, 0x68, 0xe8, + 0xe8, 0xf4, 0xe8, 0xec, 0xaa, 0x01, 0x0d, 0x43, 0x1a, 0x3b, 0x7a, 0x0f, + 0x5f, 0x58, 0xe7, 0xed, 0xfe, 0xc9, 0x09, 0xb6, 0x86, 0xe0, 0xf6, 0xdf, + 0x41, 0x37, 0x2e, 0x11, 0x51, 0x76, 0x70, 0x7e, 0xf1, 0xf3, 0xe5, 0xf1, + 0xf7, 0x6f, 0xaf, 0xd8, 0xdb, 0xf3, 0x93, 0xc3, 0x23, 0x48, 0x7c, 0x7d, + 0x04, 0xf8, 0xed, 0xbf, 0x3e, 0x39, 0xe2, 0xad, 0x41, 0xef, 0x0e, 0x4e, + 0xf6, 0x8f, 0x4f, 0x6b, 0xec, 0x70, 0xff, 0x74, 0xff, 0xfb, 0x23, 0xaa, + 0x75, 0x0e, 0x80, 0xa8, 0x93, 0x58, 0x92, 0xa3, 0xc9, 0x7e, 0x7c, 0x7b, + 0x84, 0xa9, 0xd8, 0xea, 0x3e, 0xfc, 0x7f, 0x70, 0x75, 0x7c, 0x7e, 0x86, + 0xfd, 0x39, 0x38, 0x3f, 0xbb, 0xba, 0x84, 0xaf, 0x35, 0xe8, 0xee, 0xe5, + 0x95, 0xaa, 0xfd, 0xe3, 0x71, 0xe7, 0xa8, 0xc6, 0xf6, 0x2f, 0x8f, 0x3b, + 0x48, 0x99, 0x37, 0x97, 0xe7, 0xa7, 0xd4, 0x53, 0xa4, 0x2e, 0x54, 0x3a, + 0x27, 0x38, 0x50, 0xf5, 0xec, 0x88, 0x03, 0x42, 0xca, 0xdb, 0x03, 0x04, + 0x45, 0xf0, 0xfb, 0xbb, 0xce, 0x91, 0x82, 0xc9, 0x0e, 0x8f, 0xf6, 0x4f, + 0x00, 0x1c, 0x8c, 0xd6, 0x99, 0x3b, 0xa0, 0x72, 0x90, 0xcf, 0x81, 0xbf, + 0x70, 0xbf, 0x18, 0xce, 0x80, 0x27, 0x93, 0x4f, 0xc0, 0x36, 0x83, 0x04, + 0xb8, 0xba, 0x8a, 0x53, 0x8f, 0xb8, 0x22, 0x98, 0xc2, 0x1c, 0x4c, 0x2a, + 0x26, 0xcb, 0xad, 0x22, 0xa7, 0xc2, 0x0a, 0xf9, 0x26, 0xe8, 0x26, 0xc8, + 0x7a, 0xaf, 0x61, 0x02, 0x05, 0x49, 0x1f, 0xca, 0x7c, 0x0c, 0xee, 0x02, + 0xbe, 0x2c, 0xb2, 0xbb, 0x0c, 0x76, 0x1c, 0x84, 0xc9, 0x3e, 0xa6, 0xc3, + 0x68, 0x3c, 0x7d, 0x10, 0x95, 0x70, 0x25, 0x83, 0x85, 0xac, 0xcb, 0xeb, + 0x34, 0xe2, 0xe4, 0x66, 0x4d, 0x14, 0x58, 0xe3, 0x05, 0x72, 0x0b, 0x65, + 0xcb, 0x6d, 0x88, 0x97, 0xc3, 0x69, 0x12, 0x0b, 0xec, 0x61, 0x81, 0x49, + 0xa3, 0x9b, 0x31, 0xac, 0x23, 0x23, 0x58, 0xc4, 0xd2, 0x06, 0x65, 0x2a, + 0x81, 0x21, 0xca, 0x60, 0x8a, 0x0f, 0x44, 0xf3, 0x41, 0x0a, 0x93, 0x04, + 0x36, 0xd3, 0x10, 0x96, 0xe8, 0x71, 0x9f, 0xcf, 0x51, 0x31, 0x65, 0xc4, + 0xaa, 0x7d, 0xd0, 0x39, 0x86, 0x19, 0x03, 0x10, 0x61, 0xea, 0x8f, 0xe2, + 0xf1, 0x0d, 0xaf, 0x18, 0x67, 0xb8, 0x40, 0x0f, 0xc2, 0x20, 0x9b, 0xc2, + 0x6a, 0x85, 0xe4, 0x5b, 0x5b, 0x71, 0x65, 0x0c, 0xb9, 0x15, 0xc8, 0x4d, + 0x98, 0x1d, 0xd1, 0x06, 0x80, 0xb3, 0xf4, 0x32, 0x1c, 0xc0, 0x72, 0x3c, + 0xee, 0x85, 0xa9, 0x4d, 0x07, 0x22, 0x53, 0x63, 0x1c, 0x66, 0x6b, 0x56, + 0x72, 0x34, 0xbe, 0x8b, 0xd2, 0xa8, 0x3b, 0x0c, 0xeb, 0x51, 0x3a, 0x84, + 0x59, 0x4f, 0x25, 0x08, 0xbd, 0xb5, 0x5e, 0x36, 0x4c, 0xc3, 0xdf, 0x52, + 0xf9, 0xb7, 0x91, 0x3d, 0x64, 0x8f, 0xad, 0x8a, 0x02, 0xd8, 0xe2, 0xba, + 0x77, 0x59, 0x06, 0xcb, 0xb3, 0x8d, 0xdf, 0xfd, 0xfd, 0x7d, 0x23, 0x1a, + 0xdf, 0x07, 0x13, 0xda, 0x8a, 0x26, 0xfd, 0x49, 0xab, 0xb9, 0x16, 0x8c, + 0xd3, 0x08, 0xe9, 0x96, 0xc3, 0x88, 0x46, 0xb7, 0xd1, 0x8f, 0x42, 0x02, + 0x37, 0x0a, 0xc6, 0x6b, 0x1b, 0x6b, 0xb0, 0xec, 0xa5, 0xf1, 0x30, 0xfc, + 0x85, 0x08, 0xbd, 0xa0, 0xf4, 0xb3, 0xb5, 0x69, 0xf2, 0x70, 0x97, 0x71, + 0x92, 0x57, 0x60, 0xc1, 0x67, 0x7c, 0xb7, 0xa8, 0xec, 0x29, 0x8a, 0x77, + 0x60, 0x4f, 0x0b, 0xfb, 0xbc, 0x04, 0x4a, 0x44, 0x5c, 0xd6, 0x83, 0x9d, + 0x1e, 0x57, 0x4b, 0xd8, 0xc8, 0x6b, 0x6a, 0xaf, 0x12, 0x69, 0x0d, 0xf9, + 0x5d, 0xc3, 0x38, 0x42, 0xd9, 0xe1, 0x08, 0xd6, 0x78, 0xa0, 0x15, 0x87, + 0x24, 0x07, 0xd7, 0xca, 0x12, 0xb2, 0x17, 0x01, 0xf9, 0x85, 0xe4, 0x8d, + 0x54, 0xc2, 0x94, 0x5f, 0xff, 0xf8, 0x83, 0xfd, 0x8e, 0xa2, 0xc3, 0xca, + 0x8a, 0x59, 0x91, 0x8b, 0x91, 0x28, 0xf9, 0x36, 0x82, 0x7e, 0xff, 0x04, + 0x36, 0xa5, 0x70, 0x0c, 0x2c, 0x65, 0x48, 0x23, 0x98, 0x57, 0x83, 0xdd, + 0x8e, 0xe7, 0xe4, 0xdb, 0xb9, 0xc6, 0x02, 0x1f, 0x9c, 0xd6, 0x44, 0x22, + 0xb4, 0x79, 0xfd, 0x61, 0xcf, 0x5b, 0xa1, 0x31, 0x99, 0xa6, 0xb7, 0x55, + 0x05, 0x16, 0x10, 0xdb, 0x2b, 0xc4, 0x2c, 0x46, 0x31, 0x73, 0x31, 0xd6, + 0xc5, 0x00, 0x60, 0x0a, 0xc2, 0xd6, 0x55, 0xb6, 0x77, 0xd1, 0x80, 0x55, + 0xbf, 0xc9, 0x63, 0xbc, 0x0a, 0x33, 0x19, 0xe6, 0xd9, 0x18, 0x9a, 0xe1, + 0x12, 0x6e, 0xdc, 0xfd, 0xe8, 0xed, 0x36, 0x49, 0x6a, 0x20, 0x32, 0x40, + 0x26, 0x14, 0x69, 0x0c, 0xc3, 0xf1, 0x4d, 0x76, 0x4b, 0xb5, 0xee, 0x6f, + 0x41, 0x1c, 0x61, 0xd5, 0xa8, 0x5e, 0x97, 0xb2, 0x32, 0xb6, 0x05, 0x85, + 0xae, 0x23, 0xa0, 0x20, 0x08, 0xf2, 0x12, 0x11, 0xa4, 0x1c, 0x4f, 0x6e, + 0xa8, 0x24, 0x33, 0x5f, 0x8b, 0xda, 0xd8, 0x42, 0x3a, 0x41, 0xf1, 0xa1, + 0x1a, 0xd5, 0x58, 0x4b, 0x09, 0xa9, 0x12, 0x57, 0x25, 0x35, 0xce, 0x25, + 0xf0, 0x60, 0x50, 0x4c, 0x61, 0x9b, 0x78, 0x8b, 0x88, 0xbc, 0x3f, 0x1c, + 0xca, 0xa2, 0xa9, 0x4b, 0x68, 0x4d, 0x5e, 0x1f, 0x75, 0xfb, 0xe1, 0x30, + 0xcc, 0x42, 0x0f, 0x3d, 0x17, 0xf0, 0x46, 0x2f, 0x5c, 0x34, 0xa0, 0x6a, + 0xca, 0x38, 0xe7, 0x2a, 0x10, 0x39, 0x11, 0xc7, 0xfd, 0x24, 0x09, 0x66, + 0x06, 0xc8, 0x14, 0xa9, 0xc9, 0x05, 0x6c, 0x28, 0x41, 0x13, 0x32, 0x15, + 0x74, 0x25, 0xe4, 0x6c, 0x82, 0x88, 0x16, 0x61, 0x07, 0xe2, 0x45, 0x38, + 0xe1, 0x15, 0x06, 0x8d, 0x60, 0x32, 0x19, 0xce, 0xa8, 0xc3, 0x35, 0x6a, + 0x90, 0x8a, 0xe1, 0x88, 0xc0, 0xc9, 0x4a, 0x8f, 0xad, 0x2a, 0x8f, 0xb9, + 0x02, 0x04, 0x35, 0xa6, 0xba, 0x44, 0x0d, 0xcc, 0x21, 0x44, 0x88, 0x82, + 0x60, 0x21, 0xc1, 0xcb, 0xf0, 0xf3, 0x12, 0xe4, 0x40, 0x4e, 0x13, 0x6c, + 0xbe, 0x60, 0x16, 0x0c, 0xad, 0x59, 0x60, 0x4c, 0x8d, 0x26, 0xb5, 0x8b, + 0x7b, 0x71, 0x75, 0x0f, 0x12, 0x9e, 0xb3, 0x21, 0xfc, 0x79, 0xfa, 0x54, + 0x8e, 0x8f, 0xe0, 0xfe, 0x02, 0xea, 0xcd, 0xa1, 0xc3, 0x70, 0x3e, 0xf7, + 0x99, 0xb4, 0x2d, 0xbf, 0x82, 0x7d, 0x36, 0x56, 0x75, 0x10, 0xfa, 0x69, + 0x77, 0x10, 0xab, 0xfa, 0x38, 0x4e, 0x46, 0x01, 0xf6, 0xb2, 0x49, 0x4b, + 0x7a, 0x98, 0xf6, 0x82, 0x49, 0x88, 0x47, 0xf9, 0x16, 0x7d, 0xef, 0xa5, + 0xd8, 0xd9, 0x36, 0x7d, 0x8e, 0xd3, 0x1e, 0x7c, 0x5e, 0xe7, 0xe9, 0xb0, + 0x39, 0xa4, 0x74, 0x24, 0xdf, 0xe0, 0x5b, 0x41, 0x0f, 0x11, 0xde, 0xa4, + 0xcf, 0x20, 0x35, 0xc4, 0x09, 0x72, 0xf5, 0xd6, 0x5e, 0x6e, 0xfb, 0x76, + 0x36, 0x01, 0x75, 0xb4, 0x8e, 0x27, 0x24, 0x37, 0xf3, 0x4e, 0xd2, 0x91, + 0x1f, 0xc4, 0x0b, 0xd1, 0x27, 0xa2, 0x34, 0x71, 0x01, 0x51, 0x12, 0x44, + 0x0b, 0x94, 0xb7, 0x7b, 0x21, 0xc8, 0xd8, 0xb2, 0xfe, 0xaa, 0xa4, 0xbb, + 0xa0, 0x8f, 0x75, 0x6c, 0x57, 0xc3, 0x7e, 0xdd, 0xfc, 0x40, 0xc3, 0x20, + 0xbe, 0xb5, 0xac, 0x6f, 0xed, 0x0f, 0x62, 0x70, 0xe0, 0x97, 0x35, 0x36, + 0xe6, 0x51, 0x55, 0xce, 0x7f, 0x20, 0x2e, 0xb4, 0x2e, 0x90, 0xa6, 0xa5, + 0xad, 0x32, 0x9e, 0x8e, 0xba, 0x61, 0x52, 0x51, 0x0c, 0x20, 0xf3, 0xd4, + 0x52, 0xc7, 0x75, 0x06, 0x16, 0x32, 0x2b, 0xa6, 0xea, 0xc0, 0x42, 0x4c, + 0xe4, 0xdc, 0x82, 0xc0, 0x30, 0x0c, 0x93, 0x5d, 0x0b, 0x4f, 0xbe, 0x28, + 0x2a, 0x64, 0x75, 0x4b, 0xf2, 0x93, 0xd8, 0x2b, 0x21, 0x2f, 0x0c, 0x7a, + 0xb7, 0xd5, 0x4f, 0xe1, 0x2c, 0xad, 0x4a, 0x6a, 0xc0, 0xa9, 0x7c, 0x10, + 0x4c, 0x87, 0xb0, 0x24, 0x18, 0x7a, 0x05, 0x28, 0x61, 0xad, 0xe8, 0x1c, + 0xce, 0x35, 0x24, 0xe3, 0xba, 0xce, 0xc6, 0xd3, 0xe1, 0xd0, 0x58, 0xb2, + 0xad, 0x5c, 0x45, 0xe6, 0x86, 0x99, 0x2e, 0x97, 0xf1, 0xb5, 0x35, 0x76, + 0x12, 0xde, 0x04, 0xbd, 0xd9, 0xae, 0x48, 0x40, 0xf0, 0xb2, 0x06, 0x87, + 0xf0, 0xcd, 0x0b, 0x03, 0x86, 0x44, 0x8e, 0xb2, 0x74, 0x93, 0x85, 0x8d, + 0x5a, 0x8d, 0x7d, 0x5e, 0xd1, 0xbf, 0x91, 0x7d, 0x64, 0x61, 0x17, 0xb1, + 0xcf, 0x7a, 0x20, 0x45, 0x16, 0x48, 0x5c, 0xc3, 0x38, 0x49, 0xc5, 0x2c, + 0xa7, 0xf1, 0xdc, 0x76, 0x06, 0x52, 0x14, 0xd1, 0xe0, 0x64, 0x1d, 0x90, + 0xba, 0x7a, 0x41, 0xa6, 0xe9, 0xfb, 0x8b, 0x48, 0xa7, 0x75, 0xa7, 0xba, + 0xbd, 0xca, 0xb9, 0x8a, 0x85, 0x20, 0x1e, 0x2e, 0x68, 0xb2, 0xb5, 0xf5, + 0x75, 0xda, 0x04, 0x38, 0x4b, 0x34, 0xda, 0x2c, 0xdb, 0x28, 0x07, 0xde, + 0xac, 0xb1, 0x7a, 0x7b, 0x55, 0x62, 0x20, 0x28, 0x5f, 0xd4, 0x79, 0x2a, + 0x5b, 0xf3, 0x03, 0x82, 0x9c, 0x25, 0xb0, 0x5c, 0x76, 0x38, 0xe6, 0x23, + 0xd6, 0xda, 0x2a, 0x85, 0x99, 0x94, 0xfc, 0x0a, 0xda, 0x22, 0x2e, 0xe2, + 0xbb, 0x9c, 0x3b, 0x05, 0x29, 0x0b, 0x98, 0x5f, 0x54, 0x1f, 0x67, 0x70, + 0x34, 0xb2, 0xea, 0xf3, 0x14, 0x98, 0xa8, 0x5c, 0xaa, 0xde, 0x33, 0x8a, + 0x1b, 0x52, 0xb5, 0x2c, 0xaf, 0x92, 0xa0, 0x82, 0x16, 0xb2, 0x45, 0xe3, + 0x13, 0x10, 0xd3, 0xad, 0xd2, 0xa4, 0xf3, 0x45, 0x09, 0x4c, 0x7c, 0xe7, + 0x05, 0x88, 0x22, 0x90, 0xaa, 0xb4, 0x82, 0xec, 0x95, 0x82, 0xd5, 0xb8, + 0x09, 0xb3, 0xa3, 0x61, 0x48, 0x0b, 0xcc, 0xeb, 0xd9, 0x55, 0x70, 0x73, + 0x16, 0x8c, 0xc2, 0x6a, 0x05, 0x01, 0x55, 0x56, 0x61, 0xa1, 0x62, 0xbb, + 0x7c, 0x0d, 0xd0, 0x3d, 0xc6, 0xc5, 0xcc, 0x26, 0x48, 0x6a, 0x36, 0x79, + 0x13, 0xc6, 0xa3, 0x30, 0x4b, 0x66, 0x50, 0x57, 0xe1, 0x89, 0xab, 0x9c, + 0x51, 0x85, 0xbe, 0xfa, 0xaa, 0xb4, 0x3e, 0xe4, 0xa6, 0xa7, 0x58, 0x06, + 0x25, 0x0f, 0x48, 0xc9, 0x42, 0xea, 0x47, 0xdd, 0x62, 0x6a, 0x69, 0xa4, + 0x82, 0xb3, 0x6e, 0x40, 0x0a, 0xca, 0xa6, 0xc2, 0x64, 0xd6, 0x8f, 0xd2, + 0x89, 0x95, 0xf2, 0x60, 0xe7, 0x5b, 0xdf, 0x7a, 0xd3, 0x24, 0x8d, 0x13, + 0xda, 0x37, 0x3d, 0xe9, 0x6f, 0xa3, 0x7e, 0x9f, 0xeb, 0x91, 0x03, 0x60, + 0x63, 0x9d, 0x19, 0x8f, 0xef, 0xc2, 0x24, 0x3b, 0x8a, 0x87, 0x2a, 0x29, + 0xcd, 0x41, 0xf8, 0x6d, 0x1a, 0x4e, 0x31, 0xa5, 0x52, 0xd1, 0x85, 0x7a, + 0x49, 0x3c, 0x1c, 0x5e, 0xc5, 0x36, 0x7a, 0x3c, 0xf5, 0x75, 0x9c, 0x65, + 0xf1, 0x48, 0x6e, 0xf4, 0x44, 0xbf, 0x3a, 0x6b, 0x49, 0x56, 0x1b, 0xf1, + 0x53, 0x1f, 0xcf, 0x44, 0xb9, 0x23, 0xe2, 0xfa, 0xef, 0x1f, 0xc2, 0xd9, + 0x84, 0xeb, 0xe6, 0x2d, 0x04, 0x8d, 0x12, 0x07, 0xd4, 0x91, 0x5c, 0x09, + 0xae, 0x08, 0x38, 0x05, 0xb0, 0xb9, 0x2c, 0xd8, 0x81, 0xa1, 0x73, 0xde, + 0xac, 0xfb, 0x24, 0x00, 0x7e, 0x43, 0x4b, 0x83, 0x37, 0x5b, 0x89, 0x1b, + 0xc8, 0x4f, 0x12, 0x75, 0x58, 0xac, 0x51, 0x8f, 0x67, 0xf5, 0x60, 0x92, + 0x84, 0x83, 0xe8, 0xc1, 0x0b, 0x83, 0x17, 0xf7, 0x66, 0xc1, 0x51, 0x7b, + 0x1a, 0x0c, 0x0b, 0x6a, 0x05, 0x49, 0xef, 0x76, 0x4e, 0xd6, 0x61, 0x7c, + 0x3f, 0x56, 0x49, 0x30, 0x13, 0x92, 0x99, 0x3d, 0x34, 0x94, 0x74, 0x41, + 0x68, 0x61, 0x46, 0x87, 0x2a, 0xed, 0x32, 0x5d, 0xe0, 0x97, 0x24, 0x0c, + 0xf4, 0x70, 0xff, 0xc2, 0xd1, 0x0c, 0xfb, 0x3a, 0x05, 0xe7, 0x3c, 0xcc, + 0xc5, 0x40, 0xf6, 0x5b, 0x08, 0x51, 0x8a, 0x67, 0x94, 0x4c, 0xc5, 0x89, + 0x23, 0x92, 0x6f, 0x8a, 0xd2, 0x87, 0x20, 0xea, 0x0d, 0x6d, 0x96, 0xe4, + 0x25, 0x71, 0x9a, 0x5d, 0x63, 0xd9, 0x0f, 0x9a, 0x39, 0xf0, 0x88, 0x0f, + 0x52, 0xe6, 0x04, 0xc6, 0x2d, 0xd2, 0x54, 0xee, 0x87, 0xbd, 0x13, 0xb4, + 0x93, 0xc4, 0x89, 0x9e, 0x0a, 0xad, 0xe6, 0x29, 0x96, 0xd6, 0x34, 0xcd, + 0xda, 0xcd, 0x5c, 0xd2, 0xba, 0x9b, 0xc4, 0x07, 0xd6, 0x4e, 0xa3, 0x56, + 0x49, 0x96, 0x4a, 0x0d, 0x5a, 0x8f, 0xfb, 0x6f, 0x60, 0xd9, 0xd1, 0x29, + 0xd3, 0x6c, 0x60, 0x57, 0x4b, 0x6f, 0x12, 0x3b, 0x81, 0x54, 0x15, 0x22, + 0x49, 0xf4, 0x27, 0x4a, 0x7b, 0x6a, 0x5c, 0xf8, 0xc2, 0x65, 0x10, 0x21, + 0x1a, 0xf6, 0x61, 0xc5, 0xd3, 0x0b, 0x4f, 0x38, 0x48, 0xc2, 0xf4, 0x16, + 0x66, 0x70, 0x92, 0xb9, 0x89, 0x47, 0x63, 0x3d, 0x3e, 0x69, 0x70, 0x17, + 0xf6, 0x7f, 0xb2, 0xbf, 0xfe, 0x6c, 0x7f, 0x3d, 0x80, 0x75, 0x4e, 0x71, + 0x6d, 0x06, 0x43, 0x39, 0xd2, 0xf0, 0x82, 0x7e, 0xd0, 0x1d, 0x22, 0x73, + 0xa1, 0x4d, 0xc7, 0x98, 0x0f, 0x51, 0x66, 0xa5, 0x6b, 0xd2, 0x0f, 0xf6, + 0xb3, 0x0c, 0xa7, 0x5d, 0xb5, 0xc9, 0x9e, 0x3f, 0xa7, 0x2d, 0x0e, 0x56, + 0xe7, 0xf6, 0xe6, 0x33, 0xfc, 0xb6, 0x23, 0xbe, 0x6c, 0xe1, 0x97, 0xe6, + 0xaa, 0xb9, 0xe8, 0x88, 0x5a, 0x26, 0x10, 0x0d, 0x15, 0xe6, 0x5e, 0x30, + 0xa2, 0xf1, 0xff, 0x60, 0xd6, 0xc1, 0x0d, 0xe0, 0x02, 0xb3, 0x2c, 0x76, + 0x99, 0x28, 0x66, 0xd6, 0x4c, 0x3c, 0x89, 0xd3, 0x4c, 0x27, 0xca, 0xd4, + 0x61, 0x34, 0x0e, 0x35, 0x54, 0x94, 0xcf, 0x23, 0x73, 0x1d, 0xc2, 0xc4, + 0xbc, 0x72, 0x40, 0xd7, 0xe4, 0xda, 0x12, 0xfa, 0xde, 0x1d, 0x06, 0xe3, + 0x4f, 0x27, 0x90, 0x58, 0x5d, 0x75, 0xd6, 0x69, 0x20, 0x93, 0xc9, 0x26, + 0xd9, 0x74, 0xd2, 0xc9, 0xe2, 0x49, 0x5a, 0x5d, 0x25, 0xad, 0x4f, 0x34, + 0xbe, 0x0d, 0x81, 0x94, 0x5a, 0x90, 0xad, 0x59, 0x52, 0x3a, 0x6e, 0x4d, + 0x30, 0x26, 0x68, 0xe7, 0xe4, 0x5b, 0xfd, 0x2f, 0x61, 0x82, 0xcb, 0xbe, + 0x50, 0x2e, 0xd2, 0x41, 0x8d, 0x14, 0x76, 0x8d, 0x15, 0x25, 0x13, 0x18, + 0x87, 0x4f, 0x2c, 0x2b, 0xe8, 0xea, 0xd8, 0x03, 0x01, 0xa8, 0x3a, 0xf1, + 0x47, 0x69, 0xb5, 0xc2, 0x8d, 0x77, 0x95, 0xd5, 0x55, 0xeb, 0x28, 0xa6, + 0xc6, 0x41, 0x9d, 0x40, 0xaa, 0xd6, 0x20, 0x7f, 0xcb, 0xfe, 0x6c, 0x3e, + 0xb4, 0x06, 0x03, 0x1a, 0x55, 0x6b, 0x20, 0xbf, 0x65, 0x3c, 0xc3, 0x3a, + 0xa4, 0x1d, 0x90, 0x7c, 0xc1, 0xcf, 0x4a, 0x80, 0x00, 0xff, 0xca, 0x9a, + 0xf5, 0xd6, 0xa6, 0xc6, 0x1e, 0x8e, 0x40, 0x37, 0xf1, 0x81, 0x94, 0x4c, + 0xae, 0x39, 0xaa, 0xfd, 0x20, 0xf9, 0x84, 0xa2, 0x76, 0xe5, 0x6f, 0xed, + 0x70, 0x7d, 0x63, 0x7d, 0xab, 0x52, 0xa3, 0x2f, 0xbd, 0x5e, 0x13, 0x7e, + 0xc4, 0x97, 0x8d, 0x70, 0x27, 0x68, 0xaa, 0x9c, 0x8d, 0x40, 0xe7, 0xac, + 0x6f, 0x6c, 0x6d, 0x06, 0x1b, 0xe2, 0xcb, 0xb3, 0xcd, 0xcd, 0xe6, 0xb3, + 0xae, 0xf8, 0xd2, 0xdc, 0xda, 0xd9, 0xde, 0x09, 0xc4, 0x97, 0xfe, 0x7a, + 0xff, 0x59, 0x6f, 0x40, 0x5f, 0x90, 0xe4, 0xa4, 0x58, 0xe6, 0x8d, 0x6e, + 0x6e, 0x6e, 0x3e, 0xdb, 0x5c, 0x17, 0xc5, 0xc2, 0x41, 0x7b, 0xa7, 0xbd, + 0x23, 0xbe, 0x6c, 0x07, 0x61, 0x7b, 0x5d, 0x82, 0x1e, 0xf4, 0xc2, 0x9d, + 0x8d, 0x81, 0x6c, 0xa7, 0xbd, 0x33, 0xe8, 0xc9, 0x2f, 0x41, 0xff, 0xd9, + 0x20, 0xd8, 0x56, 0xe8, 0x84, 0xed, 0xb0, 0x2d, 0xa1, 0xe1, 0x4f, 0xaf, + 0xb2, 0x82, 0x4b, 0x9a, 0xa2, 0x01, 0x8d, 0x68, 0x31, 0x0d, 0x9a, 0x4d, + 0xde, 0x6d, 0x42, 0x73, 0x08, 0xac, 0xc1, 0xbb, 0xdc, 0xd7, 0xa9, 0x49, + 0xd8, 0x5f, 0x17, 0x45, 0x31, 0x99, 0x27, 0xde, 0xe0, 0x08, 0xaf, 0x8b, + 0xb2, 0x3a, 0x79, 0x16, 0xa2, 0x7d, 0x69, 0x5d, 0x41, 0x0e, 0x43, 0x09, + 0x79, 0x1a, 0xb6, 0x15, 0xe4, 0x5e, 0x9f, 0xa7, 0x8e, 0x82, 0x1b, 0xb4, + 0xe2, 0x69, 0xe8, 0x32, 0xa3, 0x37, 0x0b, 0x04, 0xf0, 0x70, 0x13, 0xff, + 0x93, 0x6d, 0x06, 0xb3, 0x9d, 0x66, 0x9e, 0xa2, 0xcf, 0x06, 0xf8, 0x9f, + 0x2e, 0xb3, 0xd9, 0xe4, 0x14, 0x1c, 0x58, 0x7d, 0x10, 0x8d, 0x60, 0xaa, + 0xd1, 0x05, 0x51, 0x52, 0xa7, 0xf2, 0x1e, 0xf0, 0x91, 0xea, 0x6d, 0xf6, + 0x06, 0x02, 0x6e, 0x72, 0xd3, 0xdd, 0xdd, 0xec, 0xad, 0xc1, 0xff, 0x83, + 0x81, 0x82, 0x2e, 0x33, 0x45, 0x3f, 0x54, 0x0b, 0x32, 0x1d, 0xbb, 0xa1, + 0x1a, 0x80, 0x44, 0xc2, 0x1c, 0xd6, 0x80, 0x2c, 0xa4, 0x21, 0xb2, 0xb9, + 0x96, 0x3d, 0x85, 0xc3, 0x4d, 0xbd, 0xbd, 0xb9, 0x89, 0xe9, 0xa7, 0xd3, + 0x1e, 0x9a, 0x41, 0x60, 0x19, 0x20, 0x8b, 0xdf, 0x55, 0x1c, 0x5f, 0xc1, + 0x09, 0xfb, 0x0c, 0x85, 0x23, 0x9c, 0xa5, 0xb8, 0x60, 0xa2, 0x11, 0x8f, + 0x66, 0x89, 0x1e, 0x6a, 0x25, 0x83, 0xbb, 0x2e, 0x08, 0xb8, 0x18, 0xa9, + 0x4c, 0xdf, 0xec, 0x10, 0x52, 0xbd, 0x54, 0xf8, 0xe0, 0x1c, 0xbf, 0x6e, + 0x3e, 0x34, 0xe1, 0x20, 0xd3, 0x7c, 0xd8, 0x1c, 0xe0, 0xef, 0xed, 0x67, + 0xf8, 0x3b, 0xa0, 0xcf, 0x7d, 0xfa, 0x3c, 0x18, 0x28, 0x35, 0xa8, 0x5c, + 0xee, 0xb1, 0x03, 0xeb, 0xa8, 0x14, 0x89, 0xe4, 0x1a, 0x6a, 0x28, 0x7f, + 0xda, 0xad, 0x2d, 0x5b, 0xfd, 0x33, 0xcd, 0xaa, 0xc9, 0x75, 0x35, 0x62, + 0x6b, 0x6c, 0x1d, 0x4e, 0x75, 0xff, 0xc5, 0xb6, 0x60, 0xe2, 0xa3, 0xf6, + 0x41, 0x24, 0x3a, 0x69, 0x11, 0x7e, 0x33, 0xf4, 0x0f, 0xd0, 0x5c, 0x7b, + 0xbd, 0x8d, 0x04, 0x63, 0x55, 0x18, 0xca, 0xd9, 0x6a, 0x51, 0xb3, 0x1b, + 0x56, 0xab, 0xd8, 0xb5, 0x6d, 0xa0, 0x75, 0x04, 0x4b, 0x48, 0xab, 0xb9, + 0xa7, 0x31, 0x81, 0x36, 0xe0, 0x7f, 0x0d, 0x5f, 0x6b, 0x14, 0x79, 0xee, + 0x4d, 0x8d, 0x75, 0x25, 0x10, 0x71, 0x14, 0xa2, 0x15, 0xbb, 0xf2, 0xb7, + 0x0a, 0x80, 0xbb, 0x0d, 0x1f, 0xaa, 0x20, 0x7b, 0xf3, 0x0f, 0x37, 0xf2, + 0x43, 0x77, 0xd5, 0x03, 0x0f, 0x33, 0x7a, 0x0a, 0x12, 0xa0, 0xd3, 0x6b, + 0x64, 0x71, 0x27, 0x4b, 0x60, 0x40, 0xf1, 0x58, 0x6a, 0xa9, 0x18, 0x7b, + 0xf2, 0x80, 0x07, 0xfd, 0x80, 0xb3, 0x48, 0xa5, 0x89, 0x6d, 0xf5, 0xe0, + 0xa8, 0xd1, 0x53, 0x70, 0x65, 0x49, 0x71, 0xdc, 0xfa, 0xbc, 0x5a, 0x15, + 0xeb, 0xfc, 0x21, 0xd7, 0x13, 0xb0, 0xd7, 0xdf, 0xaf, 0xbd, 0xf9, 0xde, + 0x65, 0x92, 0x6b, 0xd8, 0x36, 0xf1, 0xdc, 0xaf, 0x16, 0x80, 0x3d, 0x4f, + 0x89, 0x67, 0xbc, 0xc4, 0xa0, 0x89, 0xff, 0x55, 0xcc, 0x45, 0xe5, 0x97, + 0x3c, 0x37, 0x59, 0xc7, 0xc3, 0x55, 0xb3, 0xf0, 0xdd, 0x5c, 0xbe, 0x44, + 0x43, 0x3b, 0x6e, 0x9a, 0x82, 0x97, 0x8a, 0x00, 0xaf, 0x18, 0x6a, 0x45, + 0xb3, 0xa8, 0xab, 0x62, 0x84, 0x7e, 0x59, 0xe3, 0x4d, 0x85, 0xa0, 0xd2, + 0x04, 0xa5, 0xbe, 0xe3, 0x71, 0x56, 0x15, 0xbd, 0x8b, 0x3e, 0x34, 0xc8, + 0x28, 0xcd, 0xc9, 0x0e, 0xc7, 0x5c, 0x45, 0x7a, 0x40, 0x88, 0x8f, 0xec, + 0xf5, 0x0a, 0x3f, 0x20, 0xf3, 0x2a, 0xec, 0xe5, 0x4b, 0xd2, 0x3e, 0x7c, + 0x4b, 0xac, 0x5f, 0xcb, 0xe5, 0x6d, 0xbb, 0x59, 0x3c, 0x87, 0xa7, 0x51, + 0x92, 0xc1, 0xbc, 0x62, 0xd0, 0xa0, 0x29, 0x3d, 0x62, 0x7c, 0x5b, 0x3b, + 0xe7, 0xe7, 0x34, 0xbe, 0xaf, 0xe5, 0x74, 0x3e, 0x42, 0x55, 0xc6, 0xfb, + 0xb0, 0xeb, 0xd2, 0xa8, 0x46, 0x59, 0xf2, 0x50, 0xb5, 0xcb, 0x25, 0x78, + 0x4c, 0xc4, 0x2d, 0x00, 0x8f, 0xab, 0x20, 0x89, 0xd3, 0x76, 0x40, 0xfb, + 0x85, 0x3c, 0x4c, 0xee, 0xb2, 0xeb, 0x6d, 0x98, 0xe8, 0xed, 0x0d, 0xd2, + 0xa8, 0xf1, 0x13, 0xdb, 0x6b, 0x10, 0x49, 0x3e, 0x69, 0x9f, 0x1c, 0x7e, + 0x64, 0x40, 0x33, 0xa8, 0x01, 0x74, 0x12, 0x4f, 0xce, 0xc7, 0x4e, 0x1a, + 0x3f, 0x84, 0xa1, 0x84, 0x41, 0x9e, 0x3f, 0x4d, 0x91, 0xa6, 0x5c, 0x79, + 0x54, 0xc1, 0x7e, 0xd8, 0x9d, 0xde, 0x18, 0xdf, 0xb5, 0x1f, 0x10, 0x25, + 0xf1, 0xf9, 0x0d, 0xc2, 0x07, 0xac, 0xe7, 0xa3, 0x37, 0xc2, 0xf8, 0x69, + 0x14, 0x87, 0xcc, 0x01, 0x0a, 0xc8, 0x16, 0xd4, 0xcf, 0x26, 0xd3, 0x19, + 0xba, 0x45, 0x4c, 0x5f, 0x56, 0xc9, 0x67, 0xeb, 0xdf, 0x8a, 0xb4, 0x6f, + 0x7b, 0x46, 0xc9, 0x46, 0x91, 0xce, 0xcf, 0xa9, 0xf1, 0xd9, 0x18, 0x6c, + 0x12, 0xf2, 0xc3, 0xbe, 0xa3, 0xf9, 0x55, 0x35, 0xa9, 0x8b, 0xfa, 0x1c, + 0xe8, 0x11, 0xca, 0x64, 0x09, 0x67, 0x5e, 0x99, 0x1a, 0x44, 0x59, 0xe6, + 0x05, 0x97, 0x45, 0x2d, 0x93, 0x40, 0xbe, 0x9c, 0x9c, 0x36, 0x76, 0x2a, + 0x48, 0xa4, 0xd3, 0xa4, 0xaa, 0xd9, 0x57, 0x49, 0x7b, 0xea, 0xa4, 0xb2, + 0xaa, 0x4f, 0x2e, 0xd5, 0xca, 0x3f, 0x1f, 0x5a, 0xdd, 0xeb, 0xe3, 0x8a, + 0x96, 0xc8, 0xd3, 0xdb, 0xf8, 0x9e, 0x9f, 0xa0, 0xab, 0xab, 0x4a, 0xed, + 0x03, 0x67, 0x47, 0x21, 0x3c, 0xda, 0x87, 0x14, 0xde, 0x24, 0x6f, 0x0d, + 0x32, 0x3f, 0x33, 0x38, 0x7b, 0xc1, 0x6e, 0x58, 0x0d, 0x57, 0x75, 0x79, + 0x99, 0x67, 0xaa, 0x90, 0xd0, 0x3a, 0x52, 0xad, 0x50, 0xe5, 0x0a, 0x6f, + 0x25, 0x47, 0x48, 0xae, 0x29, 0xff, 0xec, 0xa7, 0x25, 0xf6, 0xb1, 0x14, + 0x29, 0xbf, 0xf1, 0x91, 0x72, 0xae, 0x1a, 0x44, 0x1c, 0xa4, 0x38, 0xcd, + 0x66, 0x35, 0xa1, 0x41, 0xa1, 0x1e, 0x96, 0x21, 0xe5, 0x79, 0xa5, 0x04, + 0xd5, 0xf4, 0x10, 0x2d, 0x4f, 0x34, 0xac, 0x5b, 0x44, 0x33, 0xce, 0x7c, + 0x86, 0xe0, 0x7d, 0x3c, 0x8e, 0xd0, 0x8f, 0x27, 0xfa, 0x77, 0xc8, 0x6e, + 0x86, 0x71, 0x37, 0x40, 0xef, 0x9f, 0xdb, 0xe0, 0x2e, 0x8a, 0x13, 0x87, + 0x7d, 0x35, 0x69, 0x23, 0xa8, 0xf2, 0x3d, 0x2f, 0x9b, 0x23, 0x30, 0xee, + 0x01, 0x73, 0x8c, 0xe4, 0xa6, 0x7e, 0xb2, 0x8b, 0x2a, 0x93, 0xc3, 0xb8, + 0x67, 0x6d, 0x0f, 0x46, 0xaa, 0xb2, 0x45, 0x23, 0x51, 0xff, 0x8c, 0xc6, + 0xfd, 0xf0, 0xe1, 0x7c, 0x50, 0xf5, 0x94, 0xd4, 0x66, 0x79, 0xc7, 0x28, + 0x22, 0x55, 0x9a, 0x9e, 0x3a, 0x7c, 0x4f, 0x50, 0xf5, 0x6c, 0xd4, 0xba, + 0xd0, 0xd8, 0x45, 0x90, 0x66, 0xe1, 0xbc, 0x02, 0xb8, 0x58, 0xcd, 0xcb, + 0x47, 0x0f, 0x14, 0x27, 0xdf, 0x38, 0x56, 0x1d, 0x4f, 0x82, 0x7e, 0x7e, + 0x76, 0x46, 0x0f, 0x98, 0x6e, 0xd6, 0x72, 0xa7, 0xa8, 0x5c, 0x59, 0x73, + 0x75, 0xb9, 0x82, 0x8a, 0xf2, 0x54, 0xfd, 0x9a, 0xa9, 0xcc, 0x25, 0x19, + 0xc1, 0x4d, 0x79, 0xf6, 0xc1, 0xb0, 0xcf, 0x09, 0x8e, 0x78, 0x1d, 0x09, + 0x57, 0x35, 0xa4, 0x00, 0x23, 0xe3, 0x9a, 0xc3, 0x0a, 0x8a, 0x3e, 0xe6, + 0xf8, 0x2b, 0xa4, 0x25, 0x8b, 0x5e, 0x91, 0xd3, 0x5f, 0x18, 0x8e, 0xb8, + 0x9b, 0x5b, 0x9c, 0x7c, 0x62, 0xf7, 0xb0, 0xbf, 0xd0, 0xf6, 0xde, 0xcb, + 0x92, 0x61, 0xfd, 0x3d, 0x79, 0xa2, 0x8d, 0xa2, 0x7e, 0x7f, 0x18, 0xd6, + 0x7b, 0x20, 0x69, 0x7c, 0x12, 0x9b, 0x01, 0xb6, 0xa9, 0xdc, 0xf6, 0xd0, + 0x7d, 0x88, 0xb4, 0xc7, 0x70, 0xf2, 0xed, 0x0b, 0xcd, 0x02, 0x02, 0xe3, + 0x2a, 0xb7, 0x86, 0xe0, 0x39, 0xe5, 0xaa, 0xa1, 0x14, 0xbc, 0x62, 0xa1, + 0x7e, 0x1f, 0x85, 0xa4, 0x6b, 0x06, 0x0c, 0x79, 0x99, 0x1a, 0xab, 0x50, + 0xcf, 0x4c, 0x2f, 0xd3, 0xf0, 0xce, 0xb4, 0x32, 0x0b, 0x47, 0x58, 0x7b, + 0xee, 0x70, 0x69, 0x82, 0x5b, 0x66, 0x21, 0x63, 0xd5, 0xb2, 0xd7, 0x63, + 0x72, 0x78, 0xd7, 0x80, 0x3e, 0x4c, 0xba, 0x71, 0x90, 0xf4, 0x0f, 0xb9, + 0xd7, 0xaa, 0x10, 0x1d, 0xe8, 0x10, 0x4e, 0x0b, 0x80, 0x5b, 0x06, 0xb5, + 0xd0, 0xf8, 0xb7, 0x5a, 0x41, 0x45, 0xd9, 0xda, 0x64, 0x18, 0x44, 0x78, + 0xd0, 0xe6, 0x40, 0x0d, 0x33, 0x01, 0x41, 0x10, 0x2a, 0xf4, 0xc5, 0xad, + 0x14, 0x97, 0xd6, 0xed, 0x5d, 0x41, 0x9e, 0x6e, 0x69, 0x45, 0x58, 0xae, + 0xce, 0xe2, 0x8c, 0x8d, 0xc3, 0x1e, 0x7a, 0xc9, 0x26, 0xb3, 0x06, 0x3b, + 0x8c, 0x59, 0x94, 0xa1, 0x7b, 0xe7, 0x7d, 0x40, 0x8e, 0x5d, 0xec, 0x26, + 0x8e, 0x61, 0xc0, 0xc2, 0x20, 0x9d, 0x92, 0x83, 0x9f, 0x6c, 0x55, 0x2e, + 0x5a, 0xee, 0x30, 0x81, 0xb8, 0x29, 0x94, 0x18, 0x15, 0x5b, 0x0e, 0x46, + 0x5b, 0xe6, 0x10, 0xa9, 0x2e, 0x8d, 0x53, 0x06, 0xfb, 0x89, 0x95, 0x85, + 0x2b, 0xd1, 0xa8, 0x55, 0xd8, 0x69, 0xb9, 0x59, 0x30, 0x22, 0x37, 0x2a, + 0x97, 0x13, 0x71, 0x22, 0xce, 0x65, 0xc4, 0x1f, 0xd1, 0xaf, 0x31, 0x9e, + 0x0e, 0xfb, 0xc0, 0x04, 0xc3, 0x19, 0x74, 0x90, 0xfb, 0x6b, 0xf5, 0x6e, + 0xc3, 0xde, 0x27, 0xf6, 0x6b, 0x86, 0x7e, 0xac, 0x19, 0xed, 0xa8, 0xa8, + 0xfd, 0xff, 0x15, 0xd6, 0x3f, 0x38, 0x32, 0xca, 0xa3, 0x3e, 0x30, 0xe0, + 0x7d, 0x88, 0x08, 0x8b, 0xe2, 0xc0, 0x9a, 0xc9, 0x0c, 0xe6, 0x10, 0x1c, + 0xd7, 0x7c, 0x04, 0x31, 0x9a, 0x07, 0x3e, 0x03, 0xc4, 0x81, 0xe1, 0xc6, + 0x7e, 0x4e, 0x23, 0x56, 0x72, 0xb7, 0x6b, 0x93, 0xa9, 0x88, 0x15, 0x05, + 0x72, 0xd0, 0x6e, 0x43, 0x7c, 0x86, 0x65, 0x11, 0xbe, 0xa4, 0x49, 0xef, + 0x48, 0x6b, 0x01, 0x25, 0x63, 0x52, 0x89, 0x3c, 0x6b, 0x1a, 0x5d, 0x74, + 0x24, 0x01, 0x31, 0x72, 0x2b, 0xd2, 0xe8, 0x08, 0xc0, 0x8b, 0x0b, 0x0b, + 0x96, 0x2a, 0x57, 0x58, 0x92, 0xa1, 0x5c, 0x69, 0xa4, 0xfc, 0xa2, 0x92, + 0x4a, 0x99, 0x5c, 0x0e, 0x24, 0xb7, 0x01, 0xe9, 0xf9, 0x21, 0x78, 0xcf, + 0x29, 0x05, 0x43, 0x84, 0x5a, 0x70, 0xc9, 0x8b, 0xc2, 0xf5, 0xa6, 0x46, + 0xb2, 0x32, 0x5f, 0xb4, 0x73, 0x43, 0x3a, 0x81, 0xcd, 0x3f, 0xfd, 0xff, + 0x8f, 0xe9, 0xff, 0xe9, 0x31, 0xbd, 0xc0, 0x31, 0x9a, 0x33, 0xa8, 0x30, + 0xb5, 0x8f, 0x07, 0x34, 0xb3, 0x71, 0xdb, 0x61, 0x29, 0x9c, 0x9d, 0xee, + 0xd1, 0xd3, 0x5d, 0x38, 0x68, 0xa2, 0xae, 0x86, 0x05, 0x42, 0xb0, 0x52, + 0xda, 0xd7, 0xe9, 0x98, 0x4b, 0x51, 0x99, 0xe1, 0x16, 0x9a, 0x9f, 0xf4, + 0x64, 0x02, 0x78, 0xe4, 0xb4, 0x57, 0x3c, 0x42, 0x56, 0x8e, 0x52, 0xfc, + 0x11, 0x0e, 0x9d, 0xea, 0xfd, 0x58, 0x91, 0x87, 0xb6, 0xa5, 0xe1, 0x1c, + 0x1e, 0xb1, 0xd9, 0xea, 0xb3, 0xd4, 0x68, 0xf3, 0xd6, 0x87, 0x82, 0xdc, + 0x67, 0x71, 0x5f, 0x50, 0x6d, 0xde, 0x41, 0xc2, 0x55, 0xe7, 0x4e, 0x66, + 0xac, 0x43, 0xe6, 0x20, 0x54, 0x92, 0xdc, 0xaf, 0xb1, 0x03, 0xdc, 0xf1, + 0x0f, 0x58, 0x95, 0x27, 0x32, 0xb4, 0x4a, 0xad, 0x7a, 0x16, 0x73, 0xaa, + 0x58, 0xb8, 0x98, 0x97, 0xd8, 0xe9, 0x57, 0x94, 0x02, 0xfb, 0x9b, 0x6a, + 0x25, 0x1e, 0x77, 0x43, 0x58, 0xa6, 0x43, 0x74, 0x81, 0xaf, 0xe0, 0xbd, + 0x01, 0x47, 0x50, 0x24, 0x41, 0x9a, 0x14, 0x77, 0xe4, 0xda, 0x0e, 0x9b, + 0xc2, 0x77, 0xb8, 0x45, 0x7c, 0xc7, 0x85, 0x0e, 0xb9, 0x73, 0x36, 0x64, + 0x49, 0x53, 0x86, 0x20, 0x90, 0x7a, 0x84, 0xd9, 0x40, 0x0f, 0x32, 0x95, + 0x5d, 0x20, 0x4a, 0x88, 0x32, 0x5e, 0x79, 0xc2, 0xcd, 0xd3, 0x86, 0x35, + 0x4f, 0x29, 0xde, 0x0a, 0xd9, 0xda, 0xa9, 0x2c, 0x1c, 0xb1, 0xbb, 0xb8, + 0xb9, 0x57, 0x75, 0x11, 0xb1, 0x4b, 0x2b, 0x28, 0x8d, 0x87, 0x56, 0x2d, + 0x97, 0xd4, 0xae, 0xcd, 0xa9, 0x30, 0xcb, 0x57, 0x98, 0xb5, 0x57, 0x0d, + 0x2c, 0xb8, 0x18, 0x40, 0xa7, 0x0f, 0x41, 0x18, 0xc4, 0xc9, 0x2c, 0x91, + 0x13, 0x7d, 0x52, 0x8f, 0xe8, 0xe3, 0x56, 0xfb, 0xac, 0x3f, 0x5a, 0x1d, + 0x97, 0x87, 0x1e, 0x3d, 0x6e, 0x93, 0x24, 0x1a, 0x81, 0xcc, 0x22, 0x0c, + 0xab, 0x38, 0x20, 0xdf, 0x81, 0xc4, 0xf0, 0x5d, 0x6e, 0x10, 0xcf, 0xce, + 0xaf, 0x8e, 0x76, 0xb9, 0x68, 0x3a, 0x02, 0xa1, 0x86, 0xa4, 0xd2, 0x6e, + 0x88, 0xf6, 0x14, 0x18, 0x5d, 0xd8, 0xe7, 0x27, 0x64, 0x3b, 0x99, 0xdc, + 0x06, 0x4a, 0x33, 0x01, 0xbb, 0xfc, 0x34, 0xe5, 0xea, 0xd9, 0x90, 0xfd, + 0xaa, 0xf9, 0xe9, 0x57, 0x2e, 0x1a, 0x37, 0x56, 0xe6, 0xf2, 0xc5, 0x57, + 0x11, 0x2d, 0xe7, 0x70, 0x81, 0x66, 0x00, 0x5c, 0x45, 0x15, 0x13, 0x84, + 0x19, 0x4e, 0xa4, 0x2b, 0x91, 0x5c, 0x5d, 0xb5, 0x8b, 0xfa, 0x78, 0x65, + 0x19, 0x36, 0x59, 0x8a, 0x43, 0xe6, 0x32, 0x07, 0x53, 0xa8, 0x9b, 0x7a, + 0x02, 0x23, 0x15, 0x3f, 0x1c, 0x70, 0xb1, 0x92, 0xb0, 0x7e, 0xc8, 0x9c, + 0x02, 0x77, 0xc1, 0x90, 0x3c, 0x0a, 0x3c, 0x59, 0xc0, 0x61, 0x6a, 0x09, + 0xba, 0x0c, 0xc6, 0x37, 0xe4, 0xca, 0x43, 0x42, 0x31, 0x57, 0xc3, 0xca, + 0xeb, 0x71, 0x61, 0x76, 0x15, 0x8d, 0x42, 0x54, 0x0c, 0x7b, 0x6e, 0xc6, + 0x59, 0x02, 0xae, 0x85, 0xa3, 0xc8, 0xb3, 0xd2, 0x3e, 0x4b, 0x8f, 0x5e, + 0x67, 0x3d, 0x7c, 0x13, 0x3d, 0xb0, 0xe8, 0x22, 0xe8, 0xb3, 0x3a, 0x1b, + 0x83, 0x50, 0xdd, 0x87, 0xa1, 0x8a, 0xc4, 0xb5, 0x28, 0x64, 0x41, 0x57, + 0x41, 0x28, 0x0e, 0x82, 0xf3, 0x17, 0x42, 0x63, 0xd0, 0xd5, 0x52, 0xd8, + 0x83, 0xef, 0x59, 0x28, 0x76, 0x09, 0x3e, 0xb5, 0xb0, 0x88, 0x50, 0xde, + 0x28, 0xc2, 0xe0, 0x29, 0x11, 0xed, 0x9e, 0x74, 0x65, 0x08, 0xc5, 0xf4, + 0xa0, 0x9b, 0xc6, 0xc3, 0x29, 0x1c, 0x8a, 0x3c, 0xe5, 0x86, 0xe1, 0x00, + 0x69, 0x5f, 0xa9, 0xaf, 0xb7, 0x9b, 0xcd, 0xe6, 0xe4, 0xc1, 0x57, 0x26, + 0x23, 0xf7, 0x8d, 0xb9, 0x45, 0xee, 0xa3, 0x3e, 0xba, 0x36, 0xb1, 0x4a, + 0x41, 0xfe, 0x6d, 0x48, 0xd7, 0x35, 0x8a, 0x0b, 0xc4, 0x93, 0xa0, 0x17, + 0x65, 0xe4, 0xa2, 0xd0, 0xf4, 0xe5, 0xeb, 0x1b, 0x9f, 0x07, 0x42, 0x4b, + 0x5c, 0xc9, 0x92, 0x60, 0x9c, 0xf2, 0x5d, 0xcc, 0x5b, 0x23, 0x4e, 0xfa, + 0x61, 0x42, 0x67, 0x66, 0x2c, 0x3d, 0x8e, 0xc7, 0x5e, 0x02, 0x00, 0x67, + 0xa0, 0x4d, 0xd7, 0x2d, 0xb7, 0xc2, 0x4a, 0x7b, 0x13, 0xa1, 0xef, 0x09, + 0x9c, 0xcc, 0x0e, 0xd0, 0x4e, 0x5f, 0x95, 0xd0, 0x1d, 0x9d, 0xc1, 0x2f, + 0xd6, 0x24, 0x36, 0xdc, 0x26, 0xe6, 0xf1, 0xa7, 0x6f, 0xf6, 0x20, 0x0f, + 0xc2, 0x28, 0xac, 0x3a, 0x6a, 0x1e, 0x54, 0x0f, 0xb0, 0x80, 0x89, 0xcd, + 0x92, 0x51, 0xd7, 0x1c, 0xb6, 0x33, 0x74, 0x08, 0x3e, 0xd6, 0xab, 0xb1, + 0xee, 0x0d, 0xac, 0x6c, 0x37, 0x86, 0xcb, 0xaa, 0x28, 0xea, 0xa1, 0xc3, + 0xeb, 0xd9, 0x71, 0x1f, 0x19, 0x30, 0x19, 0xd5, 0xa9, 0x54, 0x45, 0xe9, + 0xc7, 0x52, 0xae, 0xbf, 0x70, 0x7c, 0x99, 0x6f, 0x43, 0xe2, 0xf7, 0x05, + 0x14, 0xc5, 0x52, 0x44, 0x51, 0x09, 0xec, 0x1b, 0x4c, 0xc9, 0x01, 0xcb, + 0xe1, 0xe5, 0xcc, 0x0b, 0x03, 0x23, 0x3e, 0xc4, 0x51, 0x9f, 0xd8, 0x45, + 0x63, 0xab, 0x34, 0x74, 0xc6, 0xfa, 0xd3, 0x8f, 0xc3, 0x74, 0x5c, 0xc9, + 0x0c, 0x55, 0x06, 0xdd, 0x6f, 0x3a, 0x3e, 0xa2, 0xa3, 0xa0, 0xb8, 0x81, + 0xcc, 0xc4, 0x5a, 0x81, 0x97, 0x7b, 0x24, 0xf0, 0xf1, 0x38, 0x4c, 0xde, + 0x5e, 0x9d, 0x9e, 0x90, 0x8b, 0x01, 0x8d, 0xdb, 0x53, 0x56, 0x31, 0xae, + 0x22, 0xff, 0x73, 0xac, 0x52, 0x19, 0x1b, 0x0c, 0xe3, 0x20, 0xdb, 0x65, + 0x38, 0xeb, 0xf6, 0xac, 0x0c, 0xce, 0xad, 0xbb, 0x0c, 0x8d, 0x46, 0xdd, + 0x1b, 0x4a, 0x83, 0x49, 0x0b, 0x98, 0x6f, 0x4e, 0x1e, 0xec, 0x92, 0x74, + 0xb3, 0x79, 0x10, 0x8c, 0xa2, 0xe1, 0x6c, 0x97, 0x3d, 0x39, 0x0c, 0x3f, + 0x06, 0xef, 0xa7, 0xac, 0x03, 0x53, 0x01, 0xc4, 0xae, 0x71, 0xfc, 0xa4, + 0xc6, 0x9e, 0x9c, 0x44, 0xdd, 0x30, 0xe1, 0x77, 0x8a, 0x44, 0xd2, 0x08, + 0xfe, 0xc0, 0x54, 0xe9, 0x85, 0x1e, 0x50, 0xe2, 0x92, 0x74, 0xcb, 0x6d, + 0x87, 0xd4, 0x48, 0x1c, 0xa1, 0x01, 0x21, 0xe4, 0x20, 0x6c, 0x5c, 0xc1, + 0xd6, 0x48, 0x9b, 0x65, 0x3e, 0x1b, 0x9f, 0x8d, 0x8f, 0x8a, 0x34, 0x75, + 0xae, 0x82, 0x75, 0x28, 0x64, 0x34, 0x9b, 0x07, 0x99, 0x6f, 0x36, 0x8f, + 0x1a, 0x36, 0x2b, 0x07, 0x58, 0x1b, 0xad, 0xb8, 0x4b, 0x08, 0xaa, 0x9f, + 0xd0, 0xba, 0xe0, 0x1a, 0x63, 0xf4, 0x74, 0xa0, 0x84, 0x1a, 0x8b, 0x0c, + 0x61, 0x0f, 0x39, 0x31, 0x22, 0x39, 0xbb, 0xbd, 0xb9, 0x65, 0x09, 0x81, + 0x08, 0xfa, 0xe9, 0x0b, 0xec, 0x1d, 0x75, 0xaa, 0xde, 0xbd, 0xa9, 0x53, + 0xfd, 0xba, 0x9c, 0x87, 0xe6, 0x4d, 0xf5, 0xba, 0xd1, 0x33, 0x6e, 0x6f, + 0x42, 0xc4, 0xd9, 0xe7, 0x8a, 0x16, 0x88, 0x7c, 0x2d, 0x3e, 0x9b, 0xdb, + 0xe2, 0x20, 0xdf, 0x62, 0xf9, 0x66, 0x0a, 0xd1, 0xaf, 0x90, 0xd1, 0x15, + 0xe9, 0xbd, 0x5c, 0x07, 0x0a, 0xb1, 0x33, 0x01, 0x2e, 0x80, 0xa2, 0xa4, + 0x42, 0x77, 0x7a, 0x01, 0x60, 0x82, 0x4f, 0xcc, 0x44, 0x03, 0x8c, 0xab, + 0x83, 0x58, 0xd6, 0x5e, 0x93, 0xe4, 0xc6, 0x57, 0x9f, 0x1a, 0xcf, 0x18, + 0x44, 0x49, 0x9a, 0xd1, 0xa2, 0x6c, 0x2f, 0x96, 0xe7, 0x78, 0x4f, 0xbe, + 0xc0, 0x8a, 0x63, 0x5c, 0x64, 0x71, 0x6e, 0xd3, 0x9b, 0x87, 0x53, 0xc7, + 0x9f, 0x9f, 0x18, 0xcf, 0x36, 0x77, 0xf6, 0xa3, 0x3b, 0xcb, 0x87, 0x89, + 0x0b, 0x38, 0xe2, 0x03, 0x1e, 0x82, 0x75, 0xba, 0xbe, 0x0d, 0x60, 0x24, + 0x6a, 0x97, 0xa3, 0x04, 0x4e, 0x43, 0xe8, 0xfd, 0x7f, 0x94, 0x24, 0x71, + 0x82, 0x9a, 0x3d, 0xb1, 0xac, 0x24, 0xe1, 0x6f, 0xd3, 0x08, 0xce, 0xc1, + 0xb0, 0xe8, 0x0b, 0xb0, 0x52, 0x8c, 0xa9, 0x58, 0x76, 0xf7, 0xef, 0x41, + 0x0a, 0x94, 0xba, 0x7f, 0x73, 0xf1, 0x72, 0x3c, 0x79, 0x8d, 0xb6, 0x1b, + 0x70, 0xba, 0x0d, 0x93, 0xc3, 0x02, 0x4d, 0xab, 0xeb, 0xd2, 0x5b, 0x58, + 0x51, 0x15, 0x26, 0xf7, 0x5d, 0xc7, 0x58, 0xb0, 0x68, 0x4b, 0x95, 0xf3, + 0xf7, 0x02, 0x2d, 0xc1, 0x68, 0x70, 0x4c, 0xea, 0xe4, 0xb7, 0xc1, 0xb8, + 0x11, 0x98, 0x7a, 0xa0, 0xb4, 0xe6, 0x52, 0x19, 0x3a, 0x0e, 0xee, 0xa2, + 0x1b, 0xf4, 0xfd, 0x63, 0xdf, 0x7e, 0xcb, 0xfc, 0x39, 0xa8, 0x61, 0x4f, + 0xf6, 0x6f, 0x2c, 0x0a, 0x93, 0xc6, 0xfe, 0x34, 0x40, 0xeb, 0xfe, 0x37, + 0xdf, 0xfc, 0xb9, 0xa8, 0x5e, 0x43, 0x9a, 0x2a, 0x2a, 0x50, 0xa5, 0x62, + 0xde, 0x43, 0xe2, 0x6a, 0xff, 0x65, 0xa1, 0xa0, 0xdc, 0xe8, 0x80, 0x39, + 0xed, 0xc0, 0xa6, 0xb3, 0x2c, 0x32, 0x50, 0xc7, 0x1e, 0xf8, 0x03, 0xda, + 0x14, 0x61, 0xca, 0x24, 0x0c, 0x2f, 0xbc, 0xea, 0xab, 0xae, 0x92, 0x4f, + 0x56, 0x6c, 0xa3, 0x54, 0x6e, 0x88, 0x9c, 0x5d, 0x15, 0x58, 0xda, 0xb0, + 0x12, 0x2a, 0xa5, 0xf0, 0x30, 0x48, 0x53, 0x1c, 0x3c, 0xb9, 0xc3, 0x62, + 0x13, 0x95, 0x5c, 0x31, 0x4b, 0xd4, 0xb2, 0xa5, 0x31, 0xab, 0x58, 0x98, + 0xa1, 0x13, 0x19, 0xdd, 0xc3, 0x07, 0xf1, 0x22, 0xe8, 0x52, 0xff, 0xe0, + 0x48, 0xd1, 0xcc, 0xb7, 0x5c, 0x24, 0x16, 0xba, 0x46, 0x91, 0x82, 0x8a, + 0x3d, 0x6f, 0xf1, 0x67, 0x8a, 0xf3, 0x04, 0xf9, 0xf0, 0x58, 0xc8, 0x9d, + 0x05, 0x51, 0x0a, 0x40, 0x62, 0x9a, 0xba, 0x21, 0xcb, 0x3f, 0x53, 0xb9, + 0x13, 0x1a, 0x1e, 0x0e, 0xda, 0xa3, 0xd0, 0xf4, 0x73, 0x00, 0x52, 0x96, + 0xa6, 0xb6, 0x83, 0xbc, 0x29, 0x6a, 0x42, 0x19, 0xb3, 0x88, 0xc4, 0x43, + 0x18, 0xbf, 0x44, 0xe6, 0x67, 0x7b, 0x15, 0xb2, 0x65, 0x55, 0x03, 0xb2, + 0xd2, 0x9c, 0x1d, 0x26, 0xc1, 0x3d, 0x75, 0x9b, 0xfb, 0x02, 0xa8, 0x6e, + 0x4a, 0xbb, 0x68, 0xb3, 0x66, 0xfb, 0x6b, 0x6b, 0x95, 0x5b, 0xce, 0xd6, + 0x18, 0xf4, 0xb8, 0x5d, 0x3f, 0xbb, 0x0d, 0x32, 0x5e, 0x46, 0x6a, 0xe7, + 0xbb, 0x40, 0xd9, 0xe0, 0x53, 0x88, 0x57, 0x00, 0xa9, 0x2d, 0x45, 0x86, + 0x15, 0xe5, 0x91, 0x2d, 0xad, 0x90, 0xda, 0x0a, 0x7d, 0x34, 0x46, 0x45, + 0x3c, 0x96, 0xa7, 0x30, 0x0a, 0xb0, 0xf2, 0x39, 0x0a, 0x2b, 0x59, 0x59, + 0x89, 0xcb, 0xbc, 0x1e, 0x39, 0xca, 0xb2, 0x2e, 0xba, 0x49, 0xc8, 0x93, + 0x3e, 0x97, 0x3c, 0x54, 0x85, 0x14, 0x4b, 0x90, 0x1f, 0x85, 0xae, 0x25, + 0x0d, 0x65, 0x87, 0xe7, 0xa7, 0x4c, 0xdc, 0xd9, 0x4d, 0xc2, 0x21, 0xc6, + 0xb4, 0x10, 0xb2, 0x63, 0xcc, 0xdd, 0x1a, 0xc8, 0xcc, 0xc5, 0xad, 0x69, + 0xd2, 0xb6, 0x2a, 0xb4, 0x06, 0x26, 0x79, 0x6b, 0x4c, 0x58, 0xbb, 0x6b, + 0xf9, 0x00, 0x2d, 0xb8, 0x95, 0xd8, 0x07, 0x4d, 0x12, 0xa4, 0x31, 0xd5, + 0x36, 0x25, 0xfa, 0xce, 0x13, 0xce, 0x09, 0x75, 0x45, 0x5d, 0x07, 0x92, + 0x36, 0xba, 0x5e, 0x00, 0xcb, 0x45, 0xca, 0xd2, 0x21, 0x1e, 0xc0, 0xf0, + 0x0a, 0xff, 0x74, 0xfc, 0x69, 0x66, 0xa1, 0x8a, 0x6a, 0x90, 0x1c, 0xb6, + 0x64, 0x66, 0xce, 0x21, 0x4b, 0xbb, 0x3c, 0x61, 0x66, 0x9b, 0xb0, 0x95, + 0x32, 0xdd, 0x81, 0xe2, 0x55, 0x97, 0x16, 0xf5, 0x5b, 0x23, 0x7e, 0x80, + 0x7a, 0x5b, 0x32, 0x32, 0x71, 0xc2, 0x6a, 0x8b, 0x60, 0x4d, 0xa8, 0x6b, + 0x1c, 0x63, 0x54, 0xc3, 0xe8, 0x30, 0xec, 0xe1, 0x5d, 0x48, 0x9b, 0x09, + 0xb3, 0x90, 0x94, 0xe9, 0x85, 0xc2, 0xa7, 0xd1, 0x68, 0x90, 0xdd, 0x27, + 0xe2, 0x12, 0x7f, 0x03, 0x0e, 0xef, 0xc0, 0xd9, 0xf1, 0x03, 0x46, 0x2f, + 0xc0, 0xb6, 0x56, 0x94, 0x8d, 0x32, 0xd3, 0xe6, 0x4d, 0xb2, 0x2c, 0xd1, + 0xc1, 0x00, 0xe7, 0xb6, 0x24, 0x7d, 0xfa, 0xaa, 0x7c, 0x9f, 0x6d, 0x45, + 0x11, 0x20, 0x90, 0xd1, 0xd1, 0x3c, 0xbc, 0x6b, 0x88, 0xcf, 0xdf, 0x70, + 0xeb, 0xbd, 0x18, 0xe7, 0x57, 0xec, 0xa9, 0xca, 0x12, 0x49, 0xbb, 0x58, + 0xf8, 0xfe, 0x36, 0xea, 0xdd, 0x3a, 0x65, 0xb1, 0xb4, 0xca, 0xaa, 0xd3, + 0x3d, 0x47, 0x59, 0x43, 0x5d, 0x4a, 0xe0, 0x33, 0x1b, 0xfa, 0x0b, 0xe7, + 0x99, 0x1d, 0x54, 0x22, 0x23, 0xce, 0xaf, 0x5c, 0x5e, 0xc3, 0x4d, 0x44, + 0xf3, 0x9a, 0x42, 0x52, 0x7e, 0xc0, 0x7b, 0x4b, 0xd0, 0x56, 0x13, 0x00, + 0x1b, 0x49, 0x1b, 0x90, 0xd4, 0x52, 0x49, 0x92, 0x0d, 0x15, 0x68, 0xd5, + 0x3d, 0x90, 0x65, 0x1d, 0x5d, 0x36, 0xb5, 0x3a, 0xc7, 0xba, 0x88, 0x0a, + 0xfd, 0x4a, 0x19, 0x2d, 0xce, 0x22, 0x40, 0xca, 0x4c, 0x89, 0x54, 0xa8, + 0x90, 0x07, 0x52, 0xc5, 0xd5, 0xe8, 0x38, 0xf6, 0x03, 0x7e, 0x9d, 0x98, + 0x86, 0x9b, 0xdf, 0x35, 0x10, 0x4b, 0x00, 0x45, 0x57, 0x41, 0xbd, 0x03, + 0xae, 0x04, 0x62, 0x21, 0xb8, 0x0d, 0x47, 0x2c, 0x1a, 0x63, 0xd4, 0x16, + 0xb9, 0xc5, 0xaa, 0xeb, 0x09, 0x14, 0xce, 0x49, 0x2f, 0x4c, 0xb8, 0x9f, + 0x91, 0xdf, 0xbf, 0x5e, 0x66, 0xde, 0x44, 0x37, 0xb8, 0xa8, 0xa1, 0x64, + 0x7b, 0x7f, 0x1b, 0x92, 0x7d, 0xa2, 0x1b, 0x03, 0xd7, 0x86, 0x29, 0x34, + 0x36, 0x18, 0x84, 0x3d, 0x8c, 0x62, 0x23, 0x9a, 0xa1, 0x0b, 0x16, 0xb0, + 0xa8, 0x86, 0xa8, 0x27, 0x47, 0x7d, 0x4b, 0x3c, 0xd0, 0x27, 0x3b, 0x3a, + 0xcc, 0x29, 0xc1, 0x48, 0xab, 0xdd, 0x93, 0x18, 0xd6, 0xd9, 0xd7, 0x00, + 0xd2, 0xbd, 0xf9, 0xe8, 0x2d, 0x02, 0xeb, 0x2a, 0x7e, 0x78, 0x4d, 0x49, + 0x55, 0x6b, 0x8b, 0xb2, 0xa4, 0x0b, 0xc3, 0x21, 0x05, 0x25, 0xe5, 0x8a, + 0xbb, 0xe6, 0x8c, 0x71, 0x89, 0x87, 0x8e, 0x0e, 0xa6, 0xdc, 0x25, 0x00, + 0xe7, 0x16, 0xcc, 0x5b, 0x31, 0x09, 0x83, 0x94, 0x9f, 0xb0, 0x03, 0x6e, + 0x6e, 0x21, 0xdd, 0xd9, 0x20, 0x7a, 0x68, 0x2c, 0xd0, 0x87, 0x58, 0xe3, + 0x9c, 0xd3, 0x89, 0x48, 0x29, 0x7f, 0x8d, 0xfd, 0x84, 0x5d, 0xb3, 0xc6, + 0x0d, 0x53, 0x1f, 0x17, 0xfb, 0xe2, 0x6f, 0x34, 0x5e, 0xff, 0xd5, 0x6e, + 0x5e, 0x01, 0xe5, 0x71, 0xff, 0x40, 0x50, 0x57, 0xb1, 0x54, 0x2b, 0xc3, + 0x92, 0x14, 0x26, 0x78, 0x7d, 0x17, 0x83, 0xee, 0x84, 0x69, 0xb8, 0x22, + 0x46, 0x8a, 0x87, 0x09, 0xc1, 0xc8, 0x15, 0xb8, 0x53, 0xa1, 0x59, 0x19, + 0x0e, 0x25, 0xc3, 0x09, 0x90, 0x63, 0x17, 0x8b, 0x5c, 0x42, 0x2f, 0xee, + 0x02, 0x58, 0x62, 0x28, 0x20, 0x12, 0x25, 0xc9, 0x09, 0xd7, 0xe8, 0xf1, + 0xdb, 0xc8, 0xc0, 0x3d, 0x3d, 0xfc, 0x8c, 0x57, 0x43, 0x1a, 0x3d, 0xbb, + 0x92, 0x20, 0x0c, 0x5e, 0x1d, 0xe6, 0x2d, 0xad, 0xc9, 0xba, 0x02, 0xd4, + 0xeb, 0x6c, 0x7c, 0x00, 0x6d, 0xd7, 0x18, 0x5e, 0x27, 0x78, 0x4d, 0x79, + 0xe2, 0x3b, 0x4c, 0x8b, 0x38, 0xe1, 0x29, 0x35, 0xd6, 0x09, 0x05, 0x3f, + 0x5e, 0x08, 0x6d, 0xa1, 0xd7, 0xd7, 0x4a, 0x32, 0xad, 0xdf, 0x1f, 0x88, + 0xcc, 0x49, 0xe6, 0x12, 0x28, 0x8e, 0x40, 0xf9, 0x03, 0x12, 0x99, 0x56, + 0xe9, 0x2e, 0xf6, 0x7a, 0x5b, 0x29, 0x73, 0x80, 0xe9, 0xc3, 0x21, 0xb9, + 0x03, 0xe0, 0x4c, 0x8d, 0xc7, 0x34, 0x6a, 0x94, 0x58, 0xe1, 0xa1, 0xa0, + 0x22, 0xdb, 0x8c, 0xf9, 0x4a, 0x2c, 0xb0, 0xbc, 0xc8, 0x0a, 0x5f, 0xe7, + 0x2a, 0xb0, 0x49, 0x13, 0x8a, 0x1d, 0xf2, 0x69, 0xac, 0x58, 0xd7, 0x84, + 0xa6, 0x93, 0x1a, 0x53, 0x6b, 0xb2, 0xf8, 0x48, 0xb5, 0x79, 0x19, 0x52, + 0x80, 0x92, 0xa1, 0x70, 0x97, 0xfd, 0xeb, 0xfa, 0xfa, 0x94, 0xad, 0x3f, + 0xc7, 0x3f, 0x7f, 0x5b, 0x7f, 0x6e, 0xc0, 0xa0, 0xf2, 0x6c, 0x3a, 0xe1, + 0x45, 0x7e, 0x5d, 0xc7, 0x50, 0x74, 0xca, 0x38, 0x84, 0x6e, 0x19, 0x9c, + 0xa2, 0xde, 0x65, 0x5e, 0x2c, 0x52, 0xd0, 0xff, 0x38, 0xd5, 0x8b, 0x31, + 0x1a, 0xfe, 0x14, 0xa3, 0x70, 0xb5, 0x94, 0x59, 0x5e, 0x2d, 0xbe, 0x50, + 0x4e, 0xc3, 0xb6, 0xab, 0x73, 0x06, 0xef, 0xc5, 0x71, 0xd2, 0x87, 0x21, + 0xa3, 0x5b, 0xf0, 0x0c, 0x5d, 0x3d, 0x53, 0x5e, 0xed, 0x00, 0x33, 0x0c, + 0x33, 0x29, 0x9d, 0x31, 0x21, 0x37, 0xb7, 0x0a, 0x8f, 0xfb, 0x44, 0x7f, + 0xb1, 0x54, 0x13, 0x9e, 0xb2, 0xa5, 0xf4, 0x3e, 0xe2, 0xae, 0x69, 0x77, + 0x0d, 0x7d, 0x67, 0x1f, 0x7f, 0x7a, 0x78, 0x19, 0xc5, 0xd8, 0xea, 0x76, + 0xd5, 0xae, 0xa3, 0x47, 0xd9, 0xdc, 0x11, 0xa8, 0x4f, 0xb0, 0x67, 0x7e, + 0xda, 0xcb, 0x03, 0x98, 0x4e, 0x8c, 0xea, 0xd0, 0xb7, 0x4f, 0x61, 0x38, + 0x21, 0xd7, 0x14, 0x4e, 0x21, 0x1c, 0x20, 0x33, 0x5b, 0xa2, 0xf9, 0x71, + 0x9a, 0x66, 0xc8, 0x22, 0x08, 0xa9, 0xe1, 0x69, 0x1e, 0x99, 0xac, 0xb8, + 0x69, 0xcd, 0x77, 0x56, 0xdb, 0xe3, 0x98, 0xdc, 0x3f, 0x1a, 0xb0, 0x47, + 0x82, 0xe0, 0x60, 0xe6, 0xc0, 0x0a, 0x1f, 0x26, 0x18, 0xa0, 0x87, 0xf4, + 0x82, 0x66, 0xce, 0xaf, 0xa2, 0xcd, 0x5f, 0x1b, 0xbe, 0xf6, 0x3e, 0x1b, + 0xab, 0xe6, 0x28, 0x26, 0x86, 0x09, 0x1f, 0x82, 0xd1, 0x64, 0x48, 0x81, + 0xd6, 0x02, 0x93, 0xff, 0x78, 0x21, 0x83, 0x09, 0xff, 0x7b, 0x83, 0xff, + 0xd9, 0xe4, 0x7f, 0xb6, 0xf8, 0x9f, 0x67, 0x9c, 0x41, 0x9f, 0x3d, 0x77, + 0x99, 0xf0, 0x34, 0xbe, 0x0b, 0x8b, 0x24, 0x0d, 0x81, 0xa3, 0x87, 0x19, + 0x97, 0x65, 0x18, 0x35, 0x04, 0x68, 0x64, 0xa3, 0x70, 0x50, 0xb0, 0x8c, + 0xf3, 0x9e, 0xa5, 0xb2, 0x00, 0x05, 0x3a, 0x1b, 0xc3, 0x01, 0x02, 0x17, + 0x04, 0x28, 0xd1, 0x9d, 0xc1, 0x70, 0x98, 0x8c, 0xfd, 0x54, 0x2d, 0x02, + 0xc5, 0x1c, 0xa8, 0xe9, 0x16, 0x8e, 0x69, 0x25, 0x15, 0x75, 0x61, 0xb1, + 0xe5, 0xc9, 0xca, 0xc6, 0x41, 0xfe, 0x3e, 0x62, 0x6b, 0x4c, 0x4d, 0xaa, + 0xf0, 0x8a, 0x14, 0x53, 0x10, 0x57, 0x55, 0xcb, 0x4c, 0x4f, 0xbb, 0x89, + 0xbc, 0xac, 0xb7, 0x6a, 0x99, 0xd5, 0x7b, 0xb7, 0x42, 0xf9, 0xb6, 0xa9, + 0xae, 0x45, 0x21, 0x08, 0x7e, 0xb2, 0x6a, 0x2a, 0x0b, 0x91, 0x28, 0xfa, + 0x92, 0xb5, 0xda, 0xcf, 0x56, 0x19, 0x56, 0xc2, 0x4f, 0x32, 0x57, 0xd7, + 0xe8, 0xdd, 0xda, 0x4e, 0x5f, 0xbe, 0xa6, 0x9a, 0x1b, 0xcf, 0xca, 0xb4, + 0xf5, 0x9c, 0xb7, 0xf5, 0xbb, 0xe2, 0x34, 0x4f, 0x2b, 0xb9, 0x76, 0x0c, + 0x4c, 0x79, 0x3b, 0x84, 0x2a, 0x7e, 0xdc, 0xf3, 0xc0, 0x69, 0x3e, 0x1c, + 0x34, 0xf1, 0x5a, 0x17, 0x96, 0x7f, 0xc9, 0xb6, 0x56, 0x57, 0xfd, 0x85, + 0xb6, 0x65, 0x21, 0xf4, 0x9a, 0x5f, 0x7f, 0xa3, 0x8b, 0x7d, 0xce, 0xb1, + 0x3d, 0x0e, 0x30, 0x70, 0xba, 0xb1, 0x21, 0x0b, 0x56, 0x4f, 0xc2, 0x9b, + 0xe9, 0x30, 0x48, 0xd6, 0x60, 0x14, 0xb6, 0xc5, 0xea, 0x7b, 0xd0, 0x65, + 0x07, 0x0f, 0xec, 0x60, 0xc6, 0x0b, 0xd0, 0x4d, 0x49, 0xca, 0xc1, 0x8c, + 0x3d, 0xcc, 0x82, 0x5f, 0x33, 0x76, 0x2a, 0x00, 0xdf, 0x24, 0xbe, 0xcc, + 0xb5, 0x11, 0xcf, 0xa6, 0x6b, 0x9d, 0xbc, 0x40, 0x7b, 0xa3, 0xda, 0x5a, + 0x5b, 0x5f, 0xdb, 0x5c, 0xfd, 0x93, 0x5d, 0x63, 0xc1, 0x1a, 0x16, 0xfc, + 0xc0, 0xfe, 0x99, 0x88, 0x4d, 0x80, 0x5f, 0x1a, 0xdd, 0xa5, 0xc0, 0x5e, + 0x17, 0x2c, 0x04, 0x40, 0x17, 0xac, 0x4b, 0xbf, 0x13, 0xfa, 0xdd, 0xa3, + 0xdf, 0x13, 0xe8, 0xec, 0xbd, 0x3b, 0xeb, 0xf2, 0xac, 0x2b, 0x08, 0x4f, + 0x3d, 0x47, 0x89, 0x85, 0xc4, 0x24, 0xea, 0x3d, 0x1c, 0x09, 0x54, 0x1e, + 0x63, 0x0f, 0xbb, 0x58, 0xbc, 0xf1, 0x00, 0x52, 0xfb, 0xba, 0x30, 0xbd, + 0x52, 0xfa, 0xac, 0x20, 0x9d, 0xb7, 0xb1, 0x6b, 0xee, 0x13, 0xfa, 0xf0, + 0x65, 0x48, 0xf2, 0xfa, 0x3a, 0xab, 0xe6, 0x14, 0x65, 0x1d, 0x7f, 0x87, + 0xd1, 0x46, 0xc4, 0x91, 0x49, 0x64, 0x18, 0x01, 0xbb, 0x74, 0xac, 0x31, + 0x10, 0xfb, 0xd2, 0x35, 0x80, 0xf4, 0xf0, 0x50, 0xbf, 0x99, 0xac, 0xc1, + 0xf4, 0x9a, 0xc0, 0xe4, 0x6a, 0x6d, 0x8a, 0x80, 0x60, 0xcc, 0x98, 0xcb, + 0xdf, 0xc2, 0x5c, 0x96, 0x83, 0x2f, 0xf0, 0x36, 0x57, 0x5f, 0x4c, 0x9a, + 0xd9, 0x49, 0xe4, 0x47, 0x0c, 0xbc, 0x84, 0x5b, 0x3e, 0x79, 0x4d, 0xb7, + 0x37, 0x2a, 0x26, 0xa3, 0x1b, 0xc7, 0x8b, 0xe6, 0x2a, 0x2f, 0x89, 0x6a, + 0xe5, 0x96, 0x2a, 0xa4, 0x7c, 0x27, 0xcd, 0xb3, 0x89, 0x51, 0x72, 0x7d, + 0x6e, 0xc9, 0xb6, 0x51, 0x72, 0x73, 0x6e, 0xc9, 0x75, 0xdb, 0x1a, 0x2f, + 0x0a, 0xa9, 0xca, 0xcd, 0x8a, 0x39, 0xd9, 0x29, 0xe9, 0xcf, 0x6b, 0x54, + 0x6c, 0x73, 0x32, 0x3c, 0x65, 0x95, 0x9a, 0xfc, 0x36, 0xc3, 0x6f, 0x1f, + 0xfe, 0x99, 0xa8, 0x1a, 0x34, 0x52, 0x46, 0xc4, 0x53, 0x91, 0x6c, 0x07, + 0x8a, 0xb2, 0xc7, 0x55, 0xdf, 0x6e, 0x2e, 0x31, 0xae, 0x8f, 0x1e, 0x9c, + 0xfc, 0x00, 0xa8, 0x4d, 0xa4, 0xbd, 0x80, 0xfe, 0xaa, 0xe0, 0xc6, 0x02, + 0xf2, 0xab, 0x82, 0x5b, 0x0b, 0xa8, 0xaf, 0x0a, 0xae, 0xe7, 0xe9, 0xc6, + 0x59, 0xa7, 0xa2, 0x56, 0xa7, 0xa7, 0xb6, 0xc0, 0x45, 0xc6, 0xa0, 0x3d, + 0x33, 0xdb, 0x82, 0x0d, 0x92, 0xe4, 0x06, 0x88, 0x8e, 0xcd, 0xd5, 0xc2, + 0xe2, 0x44, 0x9b, 0xb9, 0xb9, 0x0f, 0xc5, 0x4d, 0x61, 0xf6, 0x04, 0xa3, + 0xd1, 0xfe, 0xf1, 0x87, 0xd3, 0xc6, 0xb7, 0xf7, 0x95, 0x52, 0xa3, 0xad, + 0x6f, 0x89, 0xeb, 0xd1, 0x2e, 0x37, 0x82, 0x54, 0xea, 0xe9, 0x53, 0xab, + 0x84, 0xfe, 0x9a, 0x23, 0xa0, 0x22, 0x1c, 0xef, 0x85, 0xc9, 0xbe, 0x7b, + 0x16, 0xfb, 0x9e, 0x96, 0x43, 0x5c, 0xde, 0x77, 0x5f, 0x16, 0x6d, 0x17, + 0xb1, 0xe7, 0x16, 0x41, 0xe5, 0xe0, 0x7d, 0x8b, 0x6c, 0x21, 0x47, 0x50, + 0xa5, 0xfd, 0xb9, 0xae, 0x54, 0x10, 0xf3, 0x07, 0xb4, 0x78, 0xc8, 0xdc, + 0xe1, 0xf6, 0xb7, 0x58, 0x19, 0x55, 0xf0, 0xc0, 0x71, 0x5a, 0x59, 0x9d, + 0x47, 0x0b, 0x63, 0x81, 0xbb, 0xfe, 0x20, 0x96, 0x67, 0x4b, 0x16, 0x11, + 0xa8, 0xee, 0xe5, 0x73, 0x08, 0xc9, 0xa2, 0x8c, 0xd9, 0xaa, 0xa9, 0x3b, + 0x31, 0x68, 0x75, 0x8a, 0x03, 0xc5, 0x2f, 0x26, 0x36, 0x30, 0x3a, 0xe7, + 0x01, 0x88, 0x43, 0x78, 0xe2, 0x13, 0x11, 0xbb, 0x78, 0x4e, 0x8d, 0x70, + 0xf2, 0xdd, 0x73, 0xb4, 0x4e, 0x19, 0xc5, 0x27, 0x98, 0xf4, 0x36, 0x52, + 0xb2, 0x38, 0xc6, 0xd0, 0xcd, 0x02, 0xf5, 0x05, 0x7d, 0xfe, 0x75, 0x4e, + 0xdc, 0xd7, 0xc2, 0x62, 0x76, 0x1f, 0xc3, 0xfe, 0x7a, 0xcf, 0xba, 0x51, + 0x96, 0xee, 0xca, 0xc4, 0x26, 0x50, 0x46, 0x09, 0xf6, 0x78, 0x1b, 0x15, + 0xbe, 0xf3, 0xbb, 0x02, 0x32, 0xa5, 0x0d, 0x29, 0x74, 0x71, 0x58, 0x26, + 0xac, 0x63, 0x02, 0x9c, 0x31, 0x83, 0x54, 0x95, 0x91, 0xc7, 0xb2, 0x35, + 0x3c, 0x83, 0x28, 0xd8, 0x2d, 0x1e, 0x8f, 0xb7, 0x0d, 0xdb, 0x27, 0x99, + 0xf0, 0xb7, 0x36, 0x58, 0xd0, 0xef, 0x0b, 0xd9, 0xf7, 0x11, 0x27, 0x9a, + 0x85, 0xda, 0x3a, 0xfc, 0xf1, 0x68, 0xec, 0xf0, 0x67, 0x8e, 0xd6, 0x8e, + 0xd7, 0xf2, 0x6a, 0xee, 0x78, 0x4d, 0x43, 0x7b, 0x87, 0x3f, 0x85, 0x8a, + 0x3a, 0x0b, 0xc7, 0xe5, 0x95, 0x75, 0x9c, 0x6d, 0x15, 0xa0, 0x32, 0x87, + 0xb4, 0xfc, 0xaa, 0xec, 0xad, 0xe8, 0x9c, 0xca, 0xfd, 0x14, 0xed, 0x03, + 0x17, 0x45, 0x43, 0x10, 0x6c, 0x9b, 0x16, 0x35, 0xb7, 0x36, 0x2c, 0x2a, + 0x6e, 0x6d, 0x2e, 0x3e, 0x47, 0x72, 0x95, 0x80, 0xbf, 0x15, 0xca, 0x3b, + 0x0c, 0x87, 0x59, 0xf0, 0x33, 0x48, 0xc1, 0x8f, 0x69, 0xea, 0xb3, 0x62, + 0xe8, 0x31, 0x9a, 0x4c, 0xb3, 0x5b, 0x0c, 0x95, 0x8d, 0x3c, 0x4d, 0x87, + 0x1d, 0x3c, 0xa8, 0x52, 0x6c, 0xe9, 0x08, 0x4e, 0x20, 0x8a, 0x13, 0x37, + 0xa0, 0x71, 0x9a, 0x33, 0x35, 0xb6, 0x8d, 0x0c, 0x1e, 0xe2, 0x3c, 0x6e, + 0x6d, 0xe1, 0x3d, 0xe2, 0x78, 0x9c, 0x01, 0x51, 0x38, 0x4b, 0x62, 0x09, + 0x8e, 0x26, 0x7d, 0xfc, 0x21, 0x9c, 0xc9, 0xcd, 0x89, 0x37, 0x8d, 0xf5, + 0x78, 0x3e, 0x7e, 0xe2, 0xd9, 0xdb, 0x3a, 0x1b, 0xa7, 0x1e, 0xcf, 0xc6, + 0x4f, 0x3c, 0x1b, 0x1a, 0xd1, 0xd5, 0xe3, 0xbe, 0xc4, 0x03, 0x44, 0x76, + 0x02, 0xf6, 0x07, 0x55, 0xd2, 0x73, 0x74, 0x1c, 0x63, 0xa9, 0xd4, 0x15, + 0x23, 0xdb, 0x3e, 0x31, 0x92, 0x9a, 0x43, 0x8d, 0xb8, 0x48, 0x42, 0xf0, + 0x20, 0x65, 0x70, 0x80, 0x44, 0x29, 0xbd, 0x99, 0xf3, 0x43, 0x96, 0x11, + 0x4b, 0x45, 0x43, 0xe2, 0x58, 0x35, 0x5d, 0xe2, 0xaa, 0x53, 0x23, 0x1e, + 0xea, 0x3a, 0x17, 0x2b, 0xd6, 0x40, 0x56, 0xd7, 0xdb, 0xb8, 0x30, 0x63, + 0xd5, 0xe7, 0xcf, 0x41, 0x8e, 0x58, 0x55, 0x5b, 0x97, 0xe8, 0x8a, 0x38, + 0x40, 0x69, 0xf6, 0xfe, 0x6c, 0x05, 0x8c, 0x31, 0x74, 0x25, 0xf2, 0x5e, + 0x47, 0x9f, 0x54, 0x08, 0xf1, 0x30, 0x5d, 0x43, 0x83, 0x96, 0xb3, 0x26, + 0xea, 0x13, 0xb1, 0xb1, 0x26, 0x3e, 0xd4, 0xd8, 0xac, 0xc6, 0xee, 0x6b, + 0xec, 0xb6, 0x06, 0x1d, 0xd5, 0x34, 0x14, 0x61, 0x02, 0xbb, 0x08, 0x07, + 0xe3, 0x1d, 0xca, 0x2b, 0x4e, 0x28, 0x05, 0xfc, 0x44, 0x4a, 0xd0, 0x31, + 0x05, 0x2b, 0x50, 0x17, 0x8a, 0x78, 0x86, 0xd2, 0xca, 0x5a, 0x87, 0xec, + 0x07, 0x3e, 0xa0, 0x54, 0x84, 0x93, 0x68, 0xa6, 0x53, 0x7e, 0x16, 0xbb, + 0x03, 0x8e, 0xba, 0xa9, 0x13, 0xd5, 0xb8, 0x88, 0x1b, 0x31, 0xca, 0x14, + 0xc2, 0xaf, 0xb7, 0xc4, 0x83, 0x41, 0x1a, 0x62, 0xdc, 0x14, 0xa9, 0xa5, + 0x13, 0x77, 0x60, 0xc8, 0x53, 0x11, 0x7d, 0x66, 0x11, 0x7f, 0x0c, 0xf9, + 0x8d, 0x72, 0x24, 0x15, 0xd0, 0x2e, 0xe3, 0xdf, 0x7e, 0x8b, 0xed, 0xa1, + 0x1a, 0x9f, 0x8b, 0xa2, 0xca, 0x3d, 0x40, 0x7c, 0x38, 0x92, 0x3e, 0xe7, + 0x72, 0x7c, 0x69, 0xbf, 0x0f, 0x87, 0x0d, 0xde, 0xe8, 0x09, 0x3a, 0x3c, + 0x89, 0x9c, 0x99, 0x95, 0x73, 0x15, 0x4f, 0xb4, 0x0c, 0x48, 0x3a, 0x40, + 0x03, 0x4b, 0xd2, 0x01, 0x86, 0x96, 0xa5, 0x43, 0xd6, 0x33, 0xba, 0xc1, + 0xe7, 0xad, 0xe5, 0xd2, 0xee, 0xb2, 0x95, 0xb8, 0x6a, 0x4d, 0x9a, 0x02, + 0x63, 0xb0, 0xa1, 0x87, 0x0e, 0x0d, 0xd1, 0x8f, 0x19, 0xfe, 0xfc, 0x88, + 0xfa, 0x75, 0x0e, 0xe4, 0xd6, 0x5f, 0xe2, 0x2d, 0x79, 0x34, 0xee, 0xa9, + 0xd1, 0x3a, 0x0d, 0xb2, 0xdb, 0x06, 0xd9, 0xa8, 0xaa, 0xd5, 0x07, 0x06, + 0x7b, 0xd3, 0x2a, 0xfb, 0x8e, 0xd7, 0xc3, 0x06, 0x57, 0xf5, 0x20, 0x9a, + 0x05, 0x67, 0x50, 0xf0, 0x56, 0x15, 0x44, 0xa4, 0x0c, 0x1d, 0x5f, 0x37, + 0x64, 0xdc, 0xe0, 0x19, 0xb3, 0xe0, 0x2e, 0x8e, 0xfa, 0x74, 0xda, 0xa4, + 0x5b, 0x52, 0x22, 0x3f, 0xe8, 0x2b, 0x15, 0x48, 0x2a, 0xa3, 0xc6, 0x8b, + 0x7b, 0xd8, 0x8a, 0xcf, 0x1e, 0x70, 0x65, 0x5d, 0x65, 0x0f, 0x7a, 0xae, + 0xf1, 0xd4, 0x97, 0x06, 0x6e, 0x94, 0xab, 0xbe, 0xea, 0x52, 0x33, 0x5e, + 0x77, 0x66, 0xd7, 0x9d, 0xc9, 0xba, 0x84, 0x2e, 0xe5, 0xaa, 0xaf, 0x1a, + 0x79, 0xae, 0x00, 0x47, 0x8c, 0x53, 0x86, 0x16, 0xe5, 0xee, 0x0c, 0x27, + 0x1d, 0x57, 0xdd, 0x08, 0xf7, 0x9e, 0x20, 0xc1, 0xc5, 0x33, 0x03, 0x09, + 0x90, 0x55, 0x3b, 0x17, 0xab, 0x34, 0x45, 0xd0, 0x3b, 0xab, 0x21, 0x68, + 0xfa, 0x54, 0x0b, 0x87, 0x33, 0x4b, 0x61, 0x24, 0x66, 0xb9, 0xe2, 0xb4, + 0x5d, 0x98, 0x93, 0x92, 0xb7, 0x76, 0x61, 0x72, 0x8a, 0xcf, 0xb8, 0xbf, + 0xd3, 0xfe, 0x4b, 0x2f, 0x89, 0xe0, 0xf6, 0xa7, 0x95, 0x7e, 0x06, 0x47, + 0xe5, 0xf4, 0xc9, 0x82, 0x9d, 0x78, 0x3d, 0xce, 0x47, 0x6a, 0x29, 0x41, + 0x09, 0x69, 0x58, 0xf2, 0x1e, 0x08, 0x51, 0xc5, 0x88, 0x19, 0x95, 0xd7, + 0xa3, 0x91, 0x62, 0x04, 0x47, 0xcd, 0x90, 0x1b, 0x6c, 0x6d, 0xb2, 0x2e, + 0x1b, 0x72, 0xeb, 0x37, 0x99, 0x3d, 0xb4, 0x08, 0x68, 0x9a, 0xba, 0xa9, + 0x18, 0xc6, 0x3a, 0x22, 0x57, 0x85, 0x7e, 0x1f, 0xa0, 0x4a, 0x5e, 0xf1, + 0xac, 0xe9, 0x38, 0xa3, 0x0b, 0x97, 0xe7, 0xb9, 0x7b, 0x80, 0x81, 0xe1, + 0xef, 0xec, 0x97, 0x5f, 0xc8, 0x52, 0xf0, 0xcb, 0x2f, 0x48, 0xb1, 0x9a, + 0xa0, 0xb9, 0x12, 0x19, 0x8c, 0x67, 0x3c, 0xbc, 0xb7, 0x03, 0xcd, 0x29, + 0x8a, 0x76, 0x06, 0x69, 0xae, 0xb1, 0x70, 0xb0, 0xf0, 0x83, 0x46, 0xad, + 0x05, 0x48, 0x8e, 0x05, 0xc6, 0x00, 0xae, 0xd4, 0x94, 0x1a, 0xd4, 0xa0, + 0xc8, 0x43, 0xab, 0x09, 0x73, 0x7e, 0x34, 0x09, 0xb2, 0xa8, 0x1b, 0x0d, + 0xd1, 0xc7, 0x18, 0x03, 0xb3, 0x21, 0x22, 0x95, 0x8c, 0x8f, 0x80, 0xd8, + 0x5f, 0x84, 0x70, 0x99, 0x3a, 0x23, 0x28, 0x03, 0x88, 0x19, 0x11, 0x43, + 0x0b, 0x70, 0x80, 0x0e, 0x1b, 0x77, 0x46, 0xa6, 0x13, 0x83, 0x21, 0x7c, + 0x23, 0x2b, 0xd3, 0x0b, 0x3a, 0x3a, 0x18, 0x94, 0xed, 0xa9, 0x04, 0x54, + 0x58, 0x85, 0x10, 0x9b, 0x4e, 0x8c, 0xa2, 0x05, 0xa3, 0xa1, 0x5f, 0x6d, + 0xf9, 0x6c, 0x4d, 0xb5, 0xfc, 0x9d, 0xce, 0x15, 0x8b, 0xad, 0x72, 0x2c, + 0x84, 0xfa, 0xaa, 0xf2, 0x43, 0x85, 0xe5, 0xcd, 0xe9, 0xa5, 0xe7, 0xe9, + 0x63, 0x66, 0x97, 0x45, 0x53, 0x39, 0x7a, 0xaa, 0xe7, 0x70, 0x1e, 0x77, + 0x94, 0x64, 0xb9, 0x2c, 0x53, 0xcf, 0x62, 0x02, 0xf5, 0x0d, 0xe0, 0x7c, + 0x02, 0xe1, 0xd3, 0x1a, 0x70, 0xf4, 0x31, 0x6c, 0x48, 0x3c, 0xea, 0x06, + 0xba, 0x30, 0xe0, 0xdb, 0x1b, 0xd2, 0xb0, 0x9b, 0xde, 0xca, 0xbb, 0xd3, + 0xc2, 0x36, 0xb0, 0x14, 0x2d, 0x4a, 0x92, 0x22, 0x17, 0x44, 0xd1, 0x7b, + 0xcd, 0x59, 0x2d, 0x96, 0xae, 0xf8, 0xee, 0xd8, 0xdb, 0x79, 0x47, 0x0e, + 0xa3, 0x14, 0xd9, 0xdc, 0x90, 0xe2, 0x61, 0x45, 0xad, 0x6f, 0xc2, 0xfa, + 0xb9, 0xe9, 0xd7, 0x79, 0x7b, 0xea, 0x3a, 0xb2, 0x79, 0x0e, 0xc0, 0x7c, + 0x3a, 0x1b, 0x9e, 0x9d, 0x87, 0xfc, 0x81, 0x9e, 0xc5, 0xce, 0x9d, 0xe2, + 0x25, 0x9f, 0xbc, 0x41, 0xd3, 0x0d, 0x7d, 0xe7, 0xc6, 0x82, 0x54, 0x3e, + 0x05, 0x76, 0x86, 0x8e, 0xf1, 0xff, 0xfb, 0x67, 0x95, 0x28, 0xa2, 0x77, + 0x3a, 0x8d, 0x7c, 0xb6, 0xa0, 0xb9, 0x36, 0x55, 0xca, 0x55, 0x8e, 0x8d, + 0x52, 0xe0, 0x30, 0x6e, 0xea, 0x99, 0x5e, 0x8b, 0xf9, 0x6c, 0x11, 0x0b, + 0xdd, 0xeb, 0xdd, 0x25, 0xfd, 0x7e, 0x0d, 0xcb, 0x3d, 0x3d, 0x75, 0x54, + 0xb1, 0x69, 0x78, 0x89, 0x2f, 0x5e, 0xa0, 0xb2, 0x80, 0x1d, 0x8d, 0x6f, + 0xa2, 0x71, 0xa8, 0x82, 0xb6, 0x1d, 0x8f, 0x0d, 0xaf, 0x30, 0x58, 0x32, + 0x07, 0x83, 0x30, 0xa9, 0xd1, 0x7e, 0xad, 0x6d, 0x2f, 0x58, 0x0e, 0xc3, + 0x02, 0xc0, 0xcc, 0xe1, 0x66, 0xa1, 0x00, 0x1f, 0x3a, 0x0a, 0x30, 0x82, + 0x39, 0x3f, 0x8a, 0x07, 0x76, 0x59, 0x7a, 0x2b, 0x08, 0xf6, 0xf5, 0x3a, + 0x9c, 0xa3, 0xc8, 0xc0, 0x76, 0x13, 0x26, 0x8d, 0x15, 0xf2, 0x8a, 0x48, + 0xd2, 0x8c, 0xd1, 0xed, 0x9f, 0x5d, 0x28, 0x31, 0xcd, 0x06, 0x75, 0x38, + 0xd1, 0xa8, 0xba, 0x54, 0xa6, 0x13, 0xe2, 0xbb, 0x38, 0xa2, 0x10, 0x26, + 0x9c, 0xe1, 0xb9, 0x6c, 0x87, 0xeb, 0x19, 0x0c, 0xb7, 0x65, 0xe1, 0x65, + 0x5c, 0x6d, 0xd6, 0x37, 0x5b, 0xad, 0xd5, 0x46, 0xae, 0x24, 0x3a, 0x0e, + 0xcf, 0x2f, 0xd9, 0xda, 0x10, 0x45, 0x03, 0x36, 0x0a, 0x52, 0xee, 0x04, + 0x44, 0x66, 0x79, 0x36, 0x18, 0x06, 0x37, 0xd2, 0x7c, 0xdf, 0x7a, 0x81, + 0x8e, 0x1b, 0x35, 0xd6, 0x7e, 0x41, 0x4e, 0x01, 0xe8, 0x35, 0x58, 0x63, + 0x1b, 0x2f, 0xc8, 0xef, 0x0c, 0xce, 0x7f, 0x2f, 0x22, 0x94, 0x40, 0xf1, + 0x4d, 0xa1, 0xd6, 0xd6, 0x0b, 0xe5, 0x84, 0xe0, 0x65, 0x4f, 0xe1, 0x6a, + 0x67, 0xf2, 0x06, 0x49, 0x4b, 0x40, 0xee, 0x71, 0x5f, 0x5b, 0xde, 0xb9, + 0x2a, 0x0b, 0x4e, 0x23, 0xe2, 0x6f, 0x24, 0xfe, 0x0e, 0x69, 0xd8, 0xe8, + 0x23, 0x9c, 0x3f, 0xc4, 0xa7, 0x9e, 0x0c, 0xf6, 0x4e, 0x9e, 0x23, 0xe2, + 0x33, 0xaa, 0x83, 0xc4, 0xc7, 0x20, 0xcb, 0x12, 0xf1, 0xb1, 0x7b, 0x23, + 0x3e, 0x0c, 0xd4, 0x07, 0xec, 0xa6, 0xf8, 0x9c, 0x88, 0x43, 0x4c, 0x8d, + 0x39, 0xfe, 0xcb, 0xb8, 0x93, 0xd6, 0xb9, 0x58, 0xc7, 0x5e, 0x9a, 0x41, + 0x5d, 0xd7, 0x50, 0xe3, 0xcb, 0xf9, 0x56, 0xb9, 0x42, 0x17, 0x30, 0xb0, + 0x5e, 0x89, 0xa4, 0x1f, 0xb4, 0x70, 0x5b, 0x5c, 0xc0, 0xd8, 0x2b, 0x8c, + 0xc9, 0x1b, 0x48, 0xd2, 0xa1, 0x93, 0xe4, 0x58, 0x12, 0x4e, 0x79, 0x9c, + 0x4c, 0x03, 0x4b, 0x89, 0x1d, 0x8f, 0xe5, 0x28, 0xae, 0x8b, 0x59, 0x41, + 0x1e, 0xe3, 0x9b, 0x6a, 0xe5, 0x57, 0x28, 0xfa, 0x2b, 0xb2, 0x73, 0x16, + 0xc7, 0x6c, 0x88, 0x57, 0x75, 0x1b, 0xec, 0x34, 0x4e, 0xf1, 0xa9, 0xa9, + 0x4f, 0x21, 0x9c, 0xa9, 0x02, 0x12, 0xc0, 0x0f, 0x3a, 0x97, 0x8d, 0x8a, + 0x52, 0xd7, 0xf5, 0x99, 0x07, 0x34, 0x8f, 0x6a, 0x2b, 0x55, 0x6e, 0xdc, + 0x39, 0x14, 0x44, 0xeb, 0x17, 0x58, 0x1e, 0x3e, 0x19, 0xf1, 0xce, 0xe8, + 0xe6, 0x2b, 0xaa, 0x5a, 0x79, 0xd0, 0x19, 0x0c, 0xeb, 0x2b, 0xe4, 0x18, + 0xe1, 0x37, 0xab, 0x61, 0x5f, 0x43, 0x61, 0x11, 0x29, 0x5c, 0x5f, 0x70, + 0x30, 0x64, 0x74, 0x19, 0x43, 0xc8, 0x50, 0x69, 0x2a, 0xaf, 0x68, 0x1d, + 0xf9, 0xc6, 0xcc, 0xab, 0xea, 0x46, 0x8d, 0xda, 0x14, 0x6c, 0x58, 0x7a, + 0xac, 0xeb, 0x48, 0xb5, 0xab, 0x66, 0xcd, 0x6f, 0x0c, 0xb0, 0x3c, 0x7e, + 0xb0, 0x79, 0x0c, 0x14, 0x90, 0x1e, 0xbc, 0xdb, 0x01, 0x66, 0xd7, 0x5b, + 0x96, 0xc8, 0x11, 0xf8, 0xe2, 0x81, 0x52, 0xc7, 0x98, 0x7c, 0xa6, 0xc0, + 0xf2, 0xb1, 0xa5, 0x81, 0xb7, 0xfc, 0x6b, 0x99, 0xd4, 0xbd, 0x22, 0xa5, + 0xae, 0xa3, 0x0f, 0xe2, 0x46, 0x11, 0xfe, 0x90, 0xe5, 0x53, 0x26, 0xb7, + 0x3e, 0x28, 0xf5, 0x9a, 0xbe, 0x71, 0xf1, 0xb0, 0x2a, 0x6b, 0xd7, 0x5b, + 0x56, 0x36, 0xa5, 0xe2, 0x01, 0x18, 0x11, 0x5c, 0x75, 0x8c, 0xab, 0x84, + 0xb4, 0x0c, 0x36, 0x24, 0xd1, 0xb6, 0x55, 0x74, 0xf2, 0x72, 0xc4, 0xf3, + 0xb5, 0x74, 0x12, 0x8c, 0x5f, 0x56, 0x7c, 0xda, 0x37, 0xab, 0x9d, 0x62, + 0x50, 0xaa, 0x18, 0x22, 0x5c, 0x6f, 0xd9, 0x99, 0x46, 0x4b, 0xd8, 0x10, + 0x23, 0x17, 0xed, 0x17, 0x4f, 0x92, 0x90, 0x96, 0x9f, 0xfa, 0x5d, 0xd4, + 0x0f, 0xb5, 0xab, 0x9a, 0xb8, 0x83, 0xf3, 0xc4, 0x44, 0xc7, 0x63, 0x3f, + 0xce, 0x43, 0x25, 0x8f, 0x95, 0x17, 0x4f, 0x2a, 0x86, 0x82, 0x12, 0x7f, + 0xba, 0x37, 0x78, 0x31, 0x0b, 0x51, 0x13, 0x81, 0x40, 0xf7, 0xac, 0xec, + 0x01, 0x66, 0x73, 0xd4, 0x5f, 0xbe, 0xc4, 0xa0, 0xb0, 0xfe, 0x52, 0xb8, + 0xdc, 0x48, 0x38, 0x18, 0xca, 0x6d, 0xdb, 0x69, 0x05, 0x4f, 0x0b, 0xb0, + 0xd6, 0x5a, 0x69, 0x48, 0x13, 0x5e, 0xf1, 0x5b, 0x96, 0xa3, 0x88, 0x7b, + 0x33, 0x5f, 0xbb, 0xbc, 0xe5, 0x4b, 0xea, 0x9e, 0xd2, 0xf5, 0xa8, 0x7b, + 0x3a, 0xe7, 0xef, 0x62, 0x7b, 0x7b, 0x95, 0x3d, 0xa7, 0xec, 0x67, 0xe7, + 0x3b, 0x6d, 0x4b, 0xb0, 0x65, 0x91, 0x07, 0xda, 0x77, 0x58, 0xe7, 0x40, + 0x47, 0xc4, 0x73, 0x70, 0xbd, 0x01, 0xde, 0xdd, 0x5e, 0xa5, 0x0b, 0x4c, + 0x2f, 0xd8, 0xb6, 0x0d, 0xf9, 0x73, 0xae, 0xbf, 0x6a, 0x4f, 0x29, 0xec, + 0x74, 0x3b, 0xdf, 0x15, 0xd9, 0x11, 0xf4, 0x9e, 0xaa, 0x83, 0x54, 0x1b, + 0xf3, 0x5b, 0x61, 0xbb, 0x0a, 0x98, 0xdb, 0xa3, 0x7c, 0xbb, 0xb4, 0x7d, + 0x15, 0xb6, 0xb9, 0xe1, 0x27, 0xf4, 0x1c, 0x94, 0xe4, 0x72, 0x85, 0x91, + 0xfb, 0x74, 0x04, 0xfe, 0xd6, 0xaa, 0x4b, 0x59, 0x8d, 0x3c, 0x47, 0xc1, + 0x43, 0x7b, 0x1f, 0x93, 0xce, 0xeb, 0x75, 0x11, 0x9c, 0x05, 0x14, 0x10, + 0xfb, 0x76, 0x21, 0x0d, 0xb6, 0xf3, 0x9d, 0xec, 0x96, 0x62, 0x73, 0x31, + 0x1d, 0x8a, 0x67, 0x0b, 0xe7, 0x27, 0xae, 0xca, 0x13, 0x58, 0x70, 0xaf, + 0xa7, 0x2e, 0xfa, 0x9a, 0xa3, 0xdc, 0x82, 0x22, 0x59, 0xbe, 0x0a, 0x7f, + 0x19, 0x50, 0x73, 0x1f, 0x0b, 0xc9, 0x91, 0x94, 0x1e, 0x1a, 0x01, 0xd9, + 0xf6, 0x95, 0x67, 0xc4, 0xcc, 0xa9, 0x03, 0x2b, 0xfa, 0x92, 0xcc, 0xa9, + 0xc5, 0x99, 0x22, 0x22, 0xe9, 0xb7, 0x20, 0xf4, 0x8f, 0x1c, 0x27, 0xaa, + 0x4b, 0x27, 0xf3, 0xdd, 0x5b, 0xda, 0x3d, 0x16, 0x73, 0xa5, 0xac, 0xfa, + 0x44, 0xae, 0x6e, 0x15, 0xb7, 0x04, 0xd9, 0xf7, 0xf2, 0xb7, 0xda, 0x84, + 0x6c, 0xe3, 0x16, 0x64, 0x73, 0xea, 0x5b, 0x97, 0xd8, 0x06, 0xfe, 0xfa, + 0xb4, 0x7e, 0xe6, 0x3a, 0x0f, 0x6c, 0xf0, 0x8d, 0x79, 0x6b, 0xd0, 0xd7, + 0xf9, 0xdc, 0xf5, 0xba, 0x4a, 0x8e, 0x9f, 0x9f, 0x5a, 0x97, 0x54, 0xba, + 0x37, 0x1f, 0x3c, 0x25, 0x2a, 0x0b, 0x68, 0x26, 0x56, 0x9c, 0x6f, 0xcc, + 0x2b, 0x85, 0x3e, 0x74, 0xca, 0xe1, 0x30, 0x78, 0x14, 0x0e, 0x6a, 0xd0, + 0x9c, 0xcd, 0x26, 0xb7, 0x0f, 0xaa, 0x7a, 0xd2, 0x58, 0xa7, 0x3d, 0xb7, + 0xf0, 0x87, 0x9b, 0x7c, 0xbe, 0x35, 0x2c, 0x3d, 0x1a, 0xf6, 0xb7, 0x70, + 0x7a, 0xb6, 0xd1, 0xb0, 0xac, 0x45, 0xb2, 0xf2, 0x73, 0x7f, 0xe5, 0x61, + 0x56, 0xa2, 0xee, 0x4b, 0x7f, 0xdd, 0x9b, 0xf9, 0x75, 0xc5, 0x35, 0xba, + 0x5d, 0x67, 0x17, 0x47, 0x97, 0x2e, 0x5c, 0xe3, 0x2a, 0x45, 0x7b, 0xf8, + 0xb7, 0xe3, 0x6e, 0xea, 0xf4, 0xc8, 0xbb, 0xf0, 0x91, 0x00, 0x93, 0xfe, + 0x08, 0x9b, 0x3b, 0x52, 0x6b, 0x15, 0xc5, 0xa1, 0x3d, 0x1f, 0xc0, 0xde, + 0xad, 0x9f, 0xf6, 0x0e, 0xc2, 0x6a, 0x08, 0x84, 0x34, 0x86, 0x8b, 0x94, + 0x25, 0xa5, 0x95, 0x10, 0x7a, 0xfc, 0x02, 0x8f, 0xa8, 0x6f, 0x5d, 0x59, + 0xba, 0x9e, 0x7d, 0xb0, 0xee, 0x51, 0x53, 0xac, 0x55, 0x23, 0x38, 0x9e, + 0x73, 0x18, 0x98, 0x73, 0x87, 0xa9, 0x20, 0x5e, 0xe4, 0x2f, 0x46, 0xa8, + 0xd4, 0xfc, 0xa9, 0xbf, 0x54, 0xdc, 0x48, 0x4f, 0xd8, 0xc8, 0x7f, 0xbd, + 0xe0, 0x82, 0xfd, 0xfc, 0xb8, 0x91, 0x05, 0x28, 0xe9, 0x38, 0x9b, 0x7e, + 0x84, 0xbe, 0x71, 0x9b, 0xb3, 0x4e, 0x28, 0x76, 0xf4, 0x4a, 0x21, 0x40, + 0x2f, 0x8a, 0x5f, 0x69, 0x31, 0x0e, 0xba, 0xb1, 0x87, 0xa3, 0x09, 0x6c, + 0x8e, 0x49, 0x04, 0xa7, 0x19, 0x10, 0xfb, 0x51, 0xb5, 0xd1, 0x57, 0xb6, + 0x4b, 0x13, 0x98, 0xba, 0x1a, 0x25, 0x83, 0x09, 0xfa, 0xfa, 0xa3, 0xee, + 0x50, 0x2d, 0xee, 0x0f, 0x15, 0x33, 0x49, 0x9b, 0x7b, 0x21, 0x4b, 0x2a, + 0x56, 0x68, 0xcf, 0xce, 0x29, 0x51, 0x08, 0x47, 0xd2, 0x24, 0x99, 0x03, + 0x2b, 0x10, 0x74, 0x2a, 0x93, 0x79, 0x22, 0x3b, 0x46, 0xef, 0xdd, 0xbb, + 0x60, 0x58, 0xb5, 0xc0, 0xd6, 0xd8, 0xa6, 0xba, 0x37, 0x50, 0x7c, 0x0e, + 0x7f, 0x6c, 0xa7, 0x7a, 0xc3, 0x30, 0x48, 0x7c, 0x0d, 0xaf, 0x7e, 0x3d, + 0x14, 0xb9, 0x26, 0xcd, 0xef, 0x99, 0x9f, 0xc4, 0xf7, 0xea, 0xd8, 0xfb, + 0xf4, 0xa9, 0x71, 0x9c, 0x53, 0xa7, 0x3b, 0x1d, 0x02, 0xd8, 0x62, 0x2e, + 0xf9, 0xc2, 0x8c, 0xf1, 0x05, 0xfd, 0x31, 0xfe, 0x90, 0x56, 0x20, 0x7d, + 0x0a, 0xb5, 0x8f, 0xbb, 0xe2, 0xb9, 0xa1, 0xaa, 0x51, 0xef, 0xa9, 0xd6, + 0x03, 0xa0, 0xb1, 0xb6, 0xa5, 0xcf, 0xeb, 0xe6, 0x69, 0xd3, 0x68, 0x49, + 0x2a, 0x4e, 0x61, 0x5b, 0xcf, 0xa4, 0x26, 0x23, 0x51, 0xcf, 0x74, 0xe6, + 0xa1, 0x9a, 0x4f, 0xc6, 0xa4, 0xd3, 0x6e, 0x86, 0x0a, 0x22, 0x6e, 0x52, + 0xe1, 0xaf, 0xcb, 0x08, 0x02, 0x25, 0xe1, 0x4d, 0x44, 0x06, 0x16, 0x84, + 0x55, 0x77, 0x9e, 0x9c, 0x81, 0x7f, 0x06, 0x39, 0xf8, 0xb3, 0x34, 0x8a, + 0x72, 0xd4, 0xf8, 0x8b, 0x39, 0x1a, 0x03, 0x72, 0x44, 0xc6, 0x2b, 0x47, + 0xf8, 0x60, 0x32, 0x06, 0x16, 0x1e, 0x45, 0xff, 0xe6, 0x02, 0xa7, 0xca, + 0x9e, 0xa6, 0x14, 0x53, 0x30, 0x4a, 0xd9, 0x00, 0xef, 0x98, 0x89, 0x10, + 0x64, 0xf4, 0x4e, 0xa4, 0x61, 0xcf, 0xbb, 0xbf, 0x0d, 0x49, 0xc7, 0x36, + 0xc3, 0x37, 0x65, 0xa7, 0x63, 0xf5, 0x10, 0x74, 0x1a, 0x8c, 0x94, 0xc7, + 0x8b, 0x79, 0x6f, 0xaf, 0xec, 0x8b, 0x14, 0xce, 0xac, 0x0f, 0xfa, 0x7d, + 0xba, 0xc8, 0x8a, 0xb7, 0xca, 0xd5, 0x81, 0xc2, 0x1c, 0x45, 0xfe, 0x7c, + 0x65, 0x82, 0x01, 0x8f, 0xe4, 0x65, 0x4f, 0xef, 0x2b, 0x17, 0x3a, 0x1c, + 0xae, 0x7a, 0xe4, 0xe7, 0x1b, 0xee, 0x30, 0xa8, 0x55, 0xd3, 0xc6, 0xa0, + 0x59, 0x79, 0x26, 0xa7, 0xd5, 0xeb, 0x7b, 0x56, 0x9a, 0x87, 0x27, 0xf4, + 0x5e, 0x95, 0x47, 0x34, 0xcf, 0x17, 0x0a, 0x9f, 0x9a, 0xc9, 0x70, 0x72, + 0x4d, 0x1b, 0x05, 0x0f, 0x3c, 0x5e, 0x90, 0x9e, 0x86, 0xd3, 0x09, 0xec, + 0x6f, 0x21, 0x4f, 0xb5, 0x21, 0x2c, 0x2c, 0xc3, 0xb9, 0x65, 0xd1, 0x04, + 0x3d, 0xe4, 0x5d, 0xd2, 0x41, 0x57, 0xe0, 0xbb, 0xa1, 0x71, 0xe6, 0x5d, + 0x86, 0xbd, 0x52, 0x69, 0x7c, 0x34, 0xed, 0x28, 0xeb, 0xa5, 0x41, 0x0d, + 0x7b, 0xaa, 0x7a, 0x89, 0x65, 0x06, 0x17, 0xd5, 0xa5, 0x9e, 0x6b, 0xf2, + 0x5b, 0x75, 0x9b, 0xf6, 0x9c, 0x9c, 0x73, 0xd1, 0xb7, 0xa0, 0x8f, 0x39, + 0x4d, 0x76, 0x5f, 0xc5, 0x2e, 0xc5, 0x75, 0x68, 0x28, 0xe4, 0x07, 0xcf, + 0xa3, 0x93, 0xe2, 0xf3, 0x47, 0xf1, 0xb7, 0x27, 0x95, 0x8c, 0xbd, 0xdb, + 0x3d, 0x17, 0x1f, 0x7e, 0x8b, 0x57, 0xf6, 0xd4, 0xdd, 0x76, 0x8f, 0xb4, + 0xea, 0x6d, 0xe6, 0x10, 0x50, 0x31, 0x9f, 0xee, 0x74, 0x09, 0x12, 0x32, + 0x1f, 0xb3, 0x58, 0x7c, 0x84, 0x4a, 0xc2, 0x7f, 0x74, 0xce, 0xcf, 0x1a, + 0x3c, 0x26, 0x41, 0x34, 0x98, 0x51, 0xbf, 0x01, 0xa3, 0xc9, 0x30, 0x00, + 0xbe, 0x5c, 0x43, 0xc7, 0xbc, 0xb5, 0x9b, 0x1a, 0xab, 0xfc, 0xeb, 0xba, + 0xb2, 0xba, 0xba, 0xea, 0x46, 0xbf, 0xb7, 0x1f, 0xd8, 0x24, 0xc5, 0x14, + 0xd6, 0xbf, 0x8e, 0x84, 0xb2, 0x4a, 0x0a, 0xbf, 0xf2, 0x86, 0x72, 0xe6, + 0x3a, 0xab, 0x71, 0xa3, 0x9b, 0x96, 0x28, 0xfd, 0xd2, 0x32, 0x21, 0x5c, + 0xf9, 0x67, 0xb3, 0x62, 0xa7, 0x70, 0x59, 0x16, 0x92, 0x77, 0xbd, 0xe9, + 0xed, 0x66, 0x2e, 0x47, 0x49, 0x88, 0x2e, 0xe8, 0xc0, 0x04, 0x2d, 0xea, + 0x3f, 0x34, 0x9f, 0x59, 0xf5, 0xe5, 0x05, 0xc8, 0x70, 0x38, 0xac, 0x3a, + 0x67, 0xfd, 0x02, 0xa8, 0x68, 0x59, 0xaf, 0xfc, 0xf3, 0x8e, 0x7e, 0x0f, + 0x3c, 0x2d, 0x8c, 0x2d, 0xf8, 0xaa, 0xd9, 0xae, 0x3f, 0xb9, 0xe7, 0x60, + 0x63, 0x06, 0x8f, 0x10, 0x31, 0xf8, 0xf3, 0x87, 0x22, 0xae, 0xb7, 0xd4, + 0xde, 0x0f, 0xf2, 0xc7, 0xd6, 0x18, 0xa0, 0x20, 0x75, 0x7e, 0x78, 0xbe, + 0xcb, 0x8e, 0xd1, 0x70, 0x47, 0xae, 0x4b, 0x61, 0x90, 0xfd, 0x02, 0xcb, + 0x2b, 0x2e, 0x53, 0xbf, 0xdc, 0x0c, 0x71, 0x54, 0x1a, 0x6e, 0x15, 0x85, + 0x00, 0x3e, 0xb2, 0xf5, 0x93, 0x52, 0x49, 0x73, 0x7f, 0x0c, 0xe7, 0xec, + 0x20, 0xaa, 0x18, 0xc5, 0x73, 0x28, 0x71, 0xe6, 0x75, 0x65, 0x7e, 0x3d, + 0x09, 0xe4, 0x0a, 0x62, 0x2d, 0x5a, 0xfe, 0x0e, 0xcf, 0xf4, 0x7a, 0x6c, + 0xa5, 0xf3, 0xaa, 0xee, 0xe8, 0x7d, 0x2e, 0x33, 0x96, 0x89, 0x67, 0xfc, + 0x12, 0x1f, 0x7f, 0x78, 0x88, 0x5d, 0x00, 0xb2, 0xeb, 0x65, 0xba, 0xed, + 0xa2, 0x61, 0x46, 0x87, 0x97, 0x66, 0xd1, 0x08, 0xbb, 0x1d, 0x2e, 0xd5, + 0xa7, 0xcc, 0x83, 0x40, 0x56, 0xd4, 0x27, 0xfa, 0x80, 0x7e, 0x83, 0xf8, + 0x04, 0x54, 0xa9, 0x09, 0xc0, 0xdd, 0xf5, 0xa4, 0xfd, 0xc6, 0xe9, 0x66, + 0xe8, 0x6b, 0x07, 0x44, 0xc8, 0x9b, 0x13, 0x7c, 0x42, 0xad, 0xea, 0x6a, + 0xd3, 0xe6, 0x34, 0x10, 0x8d, 0x7d, 0xf0, 0x07, 0xf3, 0xe1, 0x37, 0xcb, + 0xcd, 0xe0, 0xd0, 0x37, 0x44, 0xad, 0xae, 0x17, 0xb6, 0x38, 0xc8, 0x88, + 0xe7, 0x7a, 0x17, 0x81, 0xf7, 0x1c, 0xa6, 0x79, 0x9b, 0x8e, 0x1e, 0x47, + 0x5e, 0x7b, 0xf2, 0x9e, 0xb0, 0xcd, 0x45, 0x40, 0xbc, 0x48, 0xa7, 0x2c, + 0x24, 0xfc, 0xfb, 0x75, 0xef, 0xf6, 0x83, 0x4f, 0x83, 0xd9, 0xd3, 0x76, + 0x26, 0x5d, 0x30, 0xaf, 0x56, 0x2c, 0x6a, 0xed, 0xc1, 0x99, 0xed, 0xf9, + 0x06, 0x8a, 0xe6, 0x82, 0xca, 0xcb, 0xcd, 0x74, 0xab, 0x81, 0x92, 0xb3, + 0x5d, 0x43, 0xcb, 0xcf, 0x78, 0x95, 0xe7, 0x9f, 0xf5, 0xbc, 0x83, 0x0b, + 0x3a, 0x6c, 0x18, 0xab, 0x04, 0x5a, 0x4f, 0x8d, 0x4d, 0xf6, 0x03, 0x4f, + 0x7c, 0xc0, 0xf7, 0x37, 0xae, 0xe5, 0x31, 0x0a, 0x15, 0x08, 0xb8, 0xfb, + 0xe7, 0xa8, 0xc9, 0xcb, 0xe6, 0x7b, 0xed, 0x17, 0xcd, 0x94, 0x9b, 0xbc, + 0x4d, 0x1c, 0x53, 0x3f, 0x92, 0x27, 0x86, 0x7a, 0x37, 0xdb, 0xc6, 0x73, + 0x0e, 0x9d, 0xe9, 0x95, 0x50, 0x7c, 0xed, 0x47, 0xda, 0xc7, 0x16, 0x8f, + 0xac, 0x45, 0x95, 0x8f, 0x92, 0x06, 0x28, 0x5e, 0x79, 0xe8, 0x00, 0x4c, + 0x9b, 0x23, 0x04, 0xfe, 0x78, 0xb6, 0x07, 0x3e, 0x00, 0x65, 0xda, 0x2a, + 0xdd, 0x4e, 0x11, 0xc9, 0x5d, 0x7d, 0xf9, 0x1c, 0xcc, 0xe6, 0xb9, 0x95, + 0x8b, 0xa9, 0x5e, 0x4a, 0x7c, 0x39, 0xea, 0x1c, 0xe0, 0xb5, 0x3d, 0xee, + 0x33, 0xcd, 0x3a, 0xe1, 0x6f, 0xd3, 0x10, 0xdf, 0x99, 0x3f, 0xc6, 0xef, + 0xfd, 0x69, 0x0f, 0x0e, 0x54, 0x55, 0xba, 0xb9, 0x07, 0x07, 0xac, 0xe6, + 0xc3, 0x4e, 0x77, 0xb5, 0x91, 0x5b, 0x78, 0xae, 0x7d, 0xab, 0x8e, 0xf3, + 0xb8, 0xa0, 0x93, 0xeb, 0x7b, 0x66, 0xd0, 0x29, 0x22, 0x97, 0xad, 0x5e, + 0x1a, 0x95, 0x58, 0x11, 0xb1, 0x17, 0x1f, 0x30, 0xfc, 0x18, 0xda, 0x23, + 0xe0, 0x38, 0xd8, 0x99, 0xc1, 0x59, 0x70, 0x04, 0xdd, 0x1a, 0x8d, 0xd0, + 0x11, 0xa2, 0xca, 0xce, 0xa1, 0x00, 0xef, 0x42, 0xdf, 0xd3, 0x85, 0x0f, + 0x7f, 0x69, 0x17, 0xe2, 0xb4, 0x57, 0xb2, 0x0b, 0x17, 0xec, 0x30, 0xbc, + 0x83, 0x83, 0x97, 0x1e, 0x0f, 0x92, 0x7f, 0x01, 0xff, 0xc3, 0x83, 0x8e, + 0xc0, 0xbf, 0xe9, 0xc1, 0xff, 0xe2, 0x2f, 0xc5, 0xbf, 0xdf, 0x4b, 0x4b, + 0xe2, 0xff, 0x0b, 0xdb, 0xd7, 0x8e, 0x50, 0xec, 0x82, 0xfb, 0xcb, 0x1a, + 0xa3, 0xb0, 0x7f, 0x21, 0x47, 0x61, 0xe0, 0xe9, 0xc5, 0x2f, 0xf3, 0xb6, + 0x2f, 0xee, 0x02, 0x5e, 0x12, 0x8f, 0x7f, 0x41, 0xdb, 0xd1, 0x5d, 0xd0, + 0x9b, 0xb1, 0x53, 0x7c, 0x92, 0xe1, 0x26, 0x84, 0xb6, 0x2f, 0x4e, 0x45, + 0xd3, 0xa1, 0xa7, 0xe9, 0x7f, 0x7d, 0xb5, 0xa6, 0x7b, 0xec, 0xcd, 0x74, + 0x38, 0x64, 0x97, 0x21, 0x6e, 0x7a, 0xd5, 0xcb, 0xe3, 0x8e, 0xa7, 0x35, + 0x57, 0x62, 0x16, 0xd2, 0x27, 0xd4, 0x28, 0x25, 0xbf, 0x60, 0x33, 0x47, + 0xdc, 0x7d, 0x06, 0xf5, 0x06, 0xd0, 0xb7, 0xb3, 0xa3, 0x13, 0xde, 0xb9, + 0xed, 0x4d, 0xab, 0x39, 0x51, 0xf8, 0x10, 0xa6, 0x73, 0x3f, 0x7c, 0x80, + 0x82, 0xc7, 0x67, 0x87, 0xa2, 0xe0, 0x86, 0x07, 0xaf, 0xa3, 0x92, 0x72, + 0xe3, 0x5e, 0xae, 0xe6, 0xa1, 0xaf, 0x26, 0x45, 0x18, 0x2b, 0xdd, 0xa3, + 0x53, 0xa0, 0x19, 0xb7, 0xc3, 0x49, 0x64, 0x2f, 0xc5, 0xaa, 0xb3, 0xed, + 0x9b, 0xb2, 0xa7, 0x7e, 0x1a, 0x12, 0x84, 0xe3, 0xa5, 0x1a, 0xfe, 0x2f, + 0x11, 0x6f, 0x5d, 0x8a, 0x3e, 0x78, 0x65, 0xba, 0xbe, 0x6d, 0x04, 0x84, + 0x81, 0x71, 0x71, 0x88, 0xfa, 0xdf, 0x38, 0x2b, 0x78, 0xe9, 0x1a, 0xfb, + 0x1e, 0xbe, 0x50, 0x95, 0x1c, 0x8e, 0xff, 0x55, 0x71, 0xc5, 0x28, 0x4b, + 0x24, 0xd2, 0x8f, 0xf4, 0x3a, 0xdd, 0x28, 0x16, 0x07, 0x55, 0xf6, 0x01, + 0x87, 0x81, 0x9a, 0x04, 0x1d, 0x70, 0x53, 0x3c, 0xe9, 0xdb, 0x78, 0xd7, + 0xf1, 0x56, 0x13, 0xec, 0xcc, 0xcf, 0xb6, 0xce, 0x69, 0xc6, 0xdd, 0x8b, + 0x0a, 0xa9, 0x55, 0xad, 0xad, 0xd6, 0xbe, 0xab, 0x3d, 0xad, 0xd5, 0x6b, + 0x0d, 0x74, 0x0a, 0x84, 0xb9, 0x81, 0x50, 0xbf, 0x6f, 0xd6, 0xbf, 0x6f, + 0xb3, 0x03, 0x45, 0xb2, 0x8e, 0x4d, 0x32, 0x4e, 0x8e, 0x6a, 0x65, 0x17, + 0xa1, 0x3c, 0xaf, 0x73, 0x9d, 0xa0, 0x8e, 0x01, 0x85, 0x11, 0x37, 0x02, + 0x98, 0x34, 0xa8, 0x91, 0x0b, 0x32, 0xd2, 0xf7, 0xc5, 0x79, 0xe1, 0x79, + 0xd5, 0x73, 0xfc, 0xfc, 0xce, 0x93, 0xf6, 0xd4, 0x93, 0x56, 0xf7, 0xa4, + 0x35, 0x9c, 0xd1, 0x29, 0xda, 0x24, 0xad, 0x0e, 0xf8, 0xb7, 0x72, 0xe3, + 0xdd, 0x65, 0x8f, 0x58, 0xe9, 0x95, 0x29, 0x7c, 0x7d, 0xf2, 0x43, 0x6c, + 0x2d, 0x05, 0xf1, 0xbb, 0x12, 0x10, 0xdb, 0x4b, 0x41, 0x7c, 0x5a, 0x02, + 0xe2, 0xfa, 0x52, 0x10, 0xeb, 0x5f, 0xbd, 0xd7, 0xee, 0x58, 0x3e, 0xbe, + 0xd7, 0x9f, 0xe7, 0x88, 0x22, 0x1c, 0x54, 0x89, 0x89, 0x62, 0x4c, 0x8c, + 0x75, 0x7b, 0x56, 0xb0, 0xea, 0xfb, 0xab, 0xf5, 0x66, 0xd3, 0x5d, 0xa5, + 0xf7, 0x01, 0xfc, 0x71, 0xe7, 0x9c, 0x9d, 0xa0, 0xf8, 0x52, 0x6f, 0xb1, + 0xce, 0x74, 0x22, 0x14, 0x1e, 0x3c, 0x1a, 0xa2, 0x51, 0x14, 0x9f, 0x1a, + 0x8a, 0xa4, 0x3a, 0x24, 0xec, 0xe7, 0xa7, 0xd9, 0x9a, 0x6f, 0x65, 0x2c, + 0x1e, 0xab, 0xc5, 0x5d, 0x8c, 0xdc, 0x33, 0x4c, 0xe1, 0xe2, 0x70, 0x66, + 0x27, 0x75, 0x40, 0x76, 0x19, 0x86, 0xac, 0x43, 0xc7, 0x61, 0xb1, 0xc8, + 0xc6, 0x03, 0xe6, 0xae, 0x14, 0x76, 0xa5, 0x2a, 0xeb, 0x74, 0xda, 0x62, + 0xe1, 0x87, 0xad, 0x9a, 0x47, 0xbd, 0x12, 0xe1, 0xba, 0xf8, 0xfd, 0x40, + 0xbd, 0x32, 0xe3, 0x55, 0xb9, 0x3c, 0x01, 0xce, 0x1c, 0x02, 0xe4, 0x46, + 0x59, 0x60, 0x7b, 0x5e, 0x0e, 0xdb, 0xf5, 0x45, 0xd8, 0xae, 0x0b, 0x6c, + 0x07, 0x8f, 0xc2, 0xf6, 0xbc, 0x24, 0xb6, 0x63, 0x3b, 0xe9, 0x78, 0x7c, + 0x17, 0x7f, 0xe2, 0x97, 0x23, 0x5d, 0x7a, 0xa2, 0x77, 0xf0, 0xf7, 0x27, + 0xac, 0x7a, 0xd2, 0x69, 0x7b, 0x36, 0xce, 0xf1, 0x7c, 0x05, 0x44, 0xdb, + 0xbf, 0x6d, 0xe6, 0xd0, 0x89, 0x8b, 0xd1, 0x71, 0x59, 0x5e, 0xa1, 0xb3, + 0xee, 0x41, 0x27, 0x9e, 0x8f, 0xce, 0x7a, 0x49, 0x74, 0xfe, 0x58, 0x0e, + 0x9d, 0x4b, 0x42, 0xe7, 0xd2, 0x83, 0xcf, 0x1f, 0x5f, 0x07, 0x9f, 0xcf, + 0xcb, 0x8d, 0x16, 0xe1, 0xd3, 0xf6, 0xe1, 0xf3, 0xf9, 0xeb, 0x0c, 0xd7, + 0x9f, 0xc5, 0xf8, 0xb4, 0x8a, 0xf0, 0x69, 0xf9, 0xf0, 0xf9, 0xf3, 0x2b, + 0xe8, 0xc7, 0x10, 0xa1, 0x67, 0xac, 0x13, 0xdc, 0xc1, 0x41, 0x87, 0x9b, + 0xe9, 0xab, 0x87, 0x47, 0x07, 0x9d, 0x03, 0x4f, 0x73, 0x5e, 0x55, 0x37, + 0xbe, 0xaf, 0xaf, 0xdf, 0xd1, 0xcc, 0x67, 0xcf, 0x11, 0x74, 0x0a, 0xf1, + 0xd9, 0x46, 0x91, 0x1d, 0x9d, 0xeb, 0x4d, 0x94, 0x2e, 0x7d, 0x28, 0xb9, + 0x8a, 0x50, 0x29, 0xbd, 0x63, 0xe5, 0xaf, 0x8d, 0xd5, 0xdf, 0xd8, 0x3a, + 0x03, 0x3c, 0xb8, 0x8f, 0x32, 0x7f, 0xe8, 0x61, 0x4d, 0x7b, 0x99, 0x9b, + 0x58, 0xfd, 0x6d, 0xde, 0x09, 0xe6, 0xcb, 0x44, 0xbe, 0xb7, 0xec, 0x2a, + 0xe8, 0xf2, 0xcd, 0xeb, 0xed, 0x95, 0x38, 0x86, 0x6e, 0x6f, 0x7b, 0x28, + 0xf3, 0xd6, 0x87, 0x43, 0x16, 0x74, 0x3b, 0x4b, 0x1c, 0x6c, 0x5e, 0x58, + 0x47, 0x48, 0x7e, 0x99, 0x86, 0xc6, 0xe2, 0x62, 0xff, 0xd4, 0xd3, 0xe4, + 0x0b, 0x5f, 0x93, 0xe4, 0x63, 0xde, 0x09, 0x13, 0xb4, 0x1a, 0xe3, 0x9d, + 0x5b, 0x8a, 0xe8, 0x0d, 0x03, 0x84, 0x17, 0x27, 0x0c, 0xe0, 0x9f, 0x08, + 0x78, 0xa3, 0xe2, 0x1b, 0xad, 0xdc, 0x85, 0x1e, 0xd4, 0x60, 0x25, 0xd3, + 0xf0, 0x6b, 0x0d, 0xec, 0x4b, 0xd8, 0xc7, 0xb1, 0xb8, 0xd5, 0xc3, 0x33, + 0x5f, 0x0f, 0x5f, 0x16, 0xf7, 0x90, 0x04, 0x56, 0xd4, 0x0f, 0xa0, 0x9b, + 0x01, 0x0a, 0xd2, 0x1c, 0x85, 0xa5, 0x3b, 0xa6, 0x6e, 0xdc, 0x7c, 0x51, + 0xcf, 0xbc, 0x9a, 0xe3, 0x85, 0x70, 0xa8, 0x40, 0xc8, 0x23, 0xb0, 0xbf, + 0x1b, 0x7f, 0x1a, 0xc7, 0xf7, 0x63, 0x7e, 0x8e, 0xe6, 0x1a, 0x90, 0x5d, + 0xf6, 0x5f, 0x69, 0xa3, 0x42, 0x01, 0xc6, 0xe6, 0x2e, 0x74, 0x39, 0x75, + 0xd8, 0x8a, 0x41, 0x43, 0x21, 0xd5, 0x2c, 0xd6, 0x87, 0x71, 0x8a, 0x37, + 0xf9, 0x39, 0x05, 0xe7, 0x5d, 0x67, 0x12, 0xf6, 0x90, 0x8b, 0xf4, 0x0a, + 0x89, 0x8a, 0x0c, 0x3a, 0x75, 0x63, 0x30, 0x67, 0x52, 0x35, 0xd9, 0x47, + 0x1d, 0x00, 0x62, 0x3f, 0xdb, 0x2d, 0x0f, 0x65, 0x9d, 0x83, 0x93, 0xc3, + 0x05, 0x6b, 0x35, 0x6f, 0x7e, 0x9f, 0x37, 0xff, 0xee, 0x87, 0x32, 0x50, + 0xdf, 0xfd, 0x50, 0x0a, 0xe6, 0x6b, 0x01, 0x73, 0x1c, 0xe1, 0x24, 0x20, + 0xdf, 0xa6, 0x94, 0x55, 0xdf, 0x75, 0xf6, 0x3b, 0x07, 0xc7, 0xc7, 0xab, + 0xa5, 0xf0, 0x7f, 0xd7, 0x29, 0xd5, 0xd2, 0x86, 0x20, 0xde, 0x34, 0xeb, + 0xdd, 0x96, 0x01, 0x4b, 0x05, 0x4b, 0x41, 0x3e, 0xe0, 0x90, 0xdf, 0x44, + 0xe3, 0x71, 0x94, 0xe6, 0x17, 0xc0, 0x4d, 0x67, 0x9e, 0x14, 0xb4, 0x27, + 0xaa, 0x97, 0x6a, 0xf1, 0x52, 0xb4, 0x98, 0x84, 0xe3, 0x72, 0x9d, 0xe1, + 0x25, 0x4b, 0xc1, 0xfe, 0x1f, 0x13, 0xf6, 0x41, 0x30, 0x0e, 0xfa, 0x51, + 0x30, 0x2e, 0xdf, 0x86, 0xac, 0x51, 0xaa, 0xad, 0x1f, 0x78, 0x5b, 0xdf, + 0x03, 0xac, 0x72, 0x6d, 0xf0, 0x92, 0xa5, 0x60, 0xff, 0xcc, 0x61, 0x1f, + 0xc3, 0x41, 0xa5, 0x64, 0x07, 0x44, 0xd1, 0x52, 0xd0, 0x8f, 0x38, 0x74, + 0x58, 0x2b, 0xef, 0xc3, 0x1b, 0xa8, 0x74, 0x18, 0x78, 0xc7, 0x7e, 0xab, + 0xdc, 0xd8, 0x3b, 0x60, 0x4a, 0x61, 0xf0, 0xbf, 0x1c, 0x83, 0xce, 0xc4, + 0x6d, 0xb9, 0x78, 0xa2, 0x4f, 0xca, 0x43, 0x7f, 0x2b, 0xa0, 0xdf, 0x87, + 0x7d, 0x5f, 0xbf, 0x5c, 0xe9, 0xa7, 0xa8, 0x45, 0x5e, 0xbd, 0x54, 0x8b, + 0x2f, 0x64, 0x8b, 0x51, 0x9a, 0x96, 0x83, 0x0d, 0x05, 0x4b, 0x41, 0x5e, + 0x13, 0x9c, 0xd0, 0x39, 0xa7, 0x53, 0x2c, 0xab, 0xc2, 0x82, 0x39, 0x0d, + 0x86, 0xc3, 0x19, 0x5b, 0xdb, 0x5f, 0x2d, 0xc5, 0x18, 0xa2, 0x66, 0x39, + 0x39, 0x45, 0x27, 0xc8, 0x8d, 0x87, 0x9f, 0xbc, 0xe9, 0xf3, 0x57, 0x58, + 0xd0, 0xf4, 0x8e, 0x92, 0x53, 0xba, 0x59, 0x27, 0x6a, 0x74, 0xad, 0x31, + 0xf6, 0x26, 0xf7, 0xb4, 0x6d, 0xab, 0xf8, 0xe6, 0x6e, 0x87, 0x9e, 0x9d, + 0x2b, 0x4e, 0x7b, 0x56, 0x0c, 0x55, 0x34, 0x63, 0x5c, 0xa4, 0x18, 0x30, + 0x11, 0x8e, 0xa8, 0x57, 0x45, 0x39, 0xaf, 0x8f, 0x4e, 0xcc, 0x2c, 0x46, + 0xb2, 0x1b, 0xbe, 0x57, 0xc7, 0x48, 0xdd, 0x1f, 0x62, 0x28, 0x4f, 0xbd, + 0xe6, 0x1b, 0xa1, 0x32, 0xb9, 0x11, 0x19, 0x6d, 0x6e, 0x3a, 0xa1, 0xf9, + 0xac, 0x92, 0xbf, 0x21, 0x65, 0x95, 0x17, 0x1e, 0xd1, 0x46, 0x11, 0xc3, + 0xfe, 0x60, 0x78, 0xcf, 0x99, 0x26, 0x07, 0xdb, 0x8a, 0x68, 0xf9, 0xe3, + 0xf0, 0x7a, 0xd7, 0xcd, 0x9c, 0x7d, 0x98, 0x28, 0xd2, 0xdc, 0xcd, 0xa7, + 0xb5, 0x3c, 0x69, 0x6d, 0x57, 0x21, 0xa4, 0x4c, 0x8b, 0x02, 0x7e, 0xcb, + 0x6b, 0x7f, 0xe6, 0x22, 0x6b, 0x94, 0x0d, 0x95, 0x93, 0xa6, 0x2a, 0x5e, + 0x60, 0xc6, 0xe3, 0x77, 0x91, 0xaf, 0xb0, 0x4a, 0x55, 0xd7, 0xce, 0x19, + 0x75, 0x5d, 0x0b, 0xa2, 0x47, 0xf5, 0x44, 0x78, 0xaf, 0xbb, 0x78, 0x53, + 0x2c, 0x8b, 0x8c, 0xfd, 0x84, 0xe1, 0x47, 0x26, 0x61, 0x92, 0xcd, 0x4a, + 0x02, 0xda, 0xf0, 0x10, 0x65, 0xd3, 0x03, 0x1c, 0x58, 0x75, 0x7c, 0x13, + 0xb2, 0xfe, 0x6c, 0x1c, 0x8c, 0xa2, 0x1e, 0xbf, 0xa7, 0xeb, 0x5e, 0xaa, + 0x2a, 0x6a, 0xa3, 0xe5, 0x1d, 0x0d, 0xdf, 0x70, 0xb4, 0xda, 0xbe, 0xc4, + 0x75, 0x5f, 0xa2, 0x0f, 0xf1, 0xd6, 0xa6, 0x2f, 0x71, 0xcb, 0x97, 0xf8, + 0xcc, 0x97, 0xb8, 0xed, 0x4b, 0xdc, 0x59, 0x4c, 0x8d, 0x69, 0xb4, 0x1c, + 0x41, 0x36, 0xb6, 0x8a, 0x61, 0x82, 0xcc, 0x4e, 0x31, 0xc9, 0x4b, 0x82, + 0xda, 0x6c, 0x7a, 0x40, 0x49, 0xbc, 0xf0, 0xfa, 0x5c, 0x59, 0x38, 0x2d, + 0x0f, 0x9c, 0x70, 0x14, 0xc0, 0xaa, 0x48, 0xa1, 0x11, 0xca, 0x82, 0xc9, + 0x4d, 0x28, 0x0c, 0xfd, 0x04, 0x3b, 0xdd, 0x64, 0x8a, 0xf1, 0xfa, 0x8d, + 0xf7, 0x43, 0xd5, 0xcd, 0xe7, 0xc5, 0x40, 0x5b, 0x4d, 0xef, 0x60, 0x37, + 0xbd, 0xa3, 0x5d, 0xc0, 0x6c, 0x5e, 0x6e, 0xf3, 0xb3, 0x9b, 0x9f, 0xdf, + 0xfc, 0x0c, 0xe7, 0xe7, 0x38, 0x3f, 0xcb, 0xf9, 0x79, 0xce, 0x65, 0x3a, + 0xa2, 0x18, 0x59, 0xf9, 0x4a, 0xf2, 0xd4, 0xe7, 0x82, 0x25, 0x35, 0x67, + 0xd2, 0x5d, 0x68, 0xd0, 0x9d, 0xbb, 0xed, 0x78, 0xee, 0xbc, 0x58, 0x6f, + 0x66, 0xe1, 0x22, 0x6e, 0xbb, 0x65, 0x9b, 0xc5, 0x84, 0x0f, 0x50, 0xb3, + 0x82, 0x1e, 0x3e, 0xe2, 0xca, 0xcd, 0x8e, 0xc7, 0x21, 0xc8, 0x83, 0xa3, + 0x7f, 0x3d, 0xb5, 0xca, 0x7c, 0x07, 0xcc, 0x80, 0x8f, 0x99, 0xdd, 0xd2, + 0xb6, 0x8d, 0x51, 0x17, 0xf7, 0xb3, 0x6a, 0x73, 0x95, 0xd5, 0xd9, 0x86, + 0x7b, 0x73, 0x4e, 0xfb, 0xe5, 0xca, 0xcd, 0x69, 0xaf, 0x08, 0x8d, 0x45, + 0x3b, 0xd3, 0x42, 0xcc, 0xc5, 0x93, 0x77, 0xe6, 0x50, 0xe5, 0x30, 0xb1, + 0x5b, 0xce, 0x03, 0x99, 0x73, 0x61, 0x68, 0xfe, 0x61, 0x36, 0x8d, 0x2c, + 0x91, 0xa0, 0xf2, 0x0a, 0xfd, 0x38, 0x5f, 0xe2, 0xaf, 0x6f, 0x2a, 0xde, + 0x4d, 0xfd, 0x95, 0xb5, 0xa3, 0xbf, 0xb4, 0xbe, 0x7d, 0xe3, 0xd0, 0x88, + 0xd3, 0x27, 0x09, 0x31, 0xd6, 0x91, 0x8b, 0x60, 0x4e, 0x40, 0x32, 0xd1, + 0x68, 0xc2, 0x98, 0xec, 0xb8, 0xcd, 0x2f, 0xe4, 0x0c, 0x1f, 0x6d, 0x1f, + 0xcf, 0x05, 0x73, 0x11, 0xac, 0xfc, 0x1d, 0x49, 0xf4, 0xa4, 0x42, 0x3e, + 0x39, 0xe8, 0xf9, 0x5a, 0xf1, 0x53, 0xeb, 0xef, 0x16, 0x7d, 0x9e, 0x58, + 0xdf, 0x98, 0x2d, 0x1b, 0x55, 0xbc, 0xc4, 0x8b, 0xd3, 0x6c, 0x39, 0xea, + 0x2d, 0xc5, 0x93, 0x05, 0x73, 0xdd, 0xea, 0xe9, 0x9e, 0xbf, 0x67, 0x38, + 0x1f, 0x5c, 0xb5, 0x8d, 0x77, 0x65, 0x50, 0xb9, 0x73, 0xfc, 0x86, 0x28, + 0x9a, 0x77, 0xca, 0xf6, 0x9d, 0x54, 0xae, 0x3b, 0x7d, 0x37, 0xc1, 0x3c, + 0x7c, 0x6c, 0x24, 0x65, 0x55, 0xf9, 0x7c, 0x22, 0x85, 0x31, 0xae, 0x1e, + 0xbc, 0x7b, 0xe7, 0x51, 0x72, 0xed, 0xfb, 0x94, 0x5c, 0xfc, 0xee, 0xcf, + 0xbb, 0x89, 0x29, 0xb6, 0x95, 0x51, 0x23, 0x0a, 0xd4, 0x5e, 0x7b, 0x51, + 0x3b, 0x44, 0x05, 0x53, 0x31, 0x72, 0x87, 0x1e, 0xe4, 0x5e, 0x17, 0x23, + 0x87, 0xd0, 0x1e, 0x89, 0xde, 0x81, 0x17, 0xbd, 0x37, 0x70, 0x44, 0x0d, + 0x92, 0xfe, 0x1c, 0x0c, 0xdf, 0x78, 0x30, 0x3c, 0x28, 0xc6, 0x50, 0x00, + 0x7c, 0x24, 0x92, 0x87, 0x5e, 0x24, 0x5f, 0x07, 0xbd, 0x4f, 0x0b, 0xb0, + 0x7c, 0xed, 0xc1, 0xd2, 0xeb, 0x24, 0x22, 0x2e, 0x78, 0x09, 0x88, 0x8f, + 0x44, 0x73, 0x0f, 0x7f, 0xbd, 0xf5, 0xe2, 0x2a, 0x9f, 0x5f, 0x61, 0x18, + 0xd5, 0x63, 0x0f, 0x36, 0xde, 0xe9, 0x68, 0xfc, 0xc1, 0xc4, 0xf7, 0xba, + 0x55, 0xc3, 0xa3, 0x00, 0xe0, 0x7c, 0x51, 0x56, 0xa5, 0xcd, 0x71, 0x06, + 0xc8, 0x8f, 0x44, 0xf7, 0x1f, 0x8c, 0x1d, 0x25, 0x08, 0x1e, 0x4e, 0xc9, + 0x78, 0x7d, 0x65, 0x18, 0xcc, 0x58, 0xf5, 0xc8, 0xc7, 0x7a, 0xff, 0xf0, + 0x35, 0x1f, 0x62, 0xdd, 0xe3, 0xb1, 0xa8, 0xf9, 0x48, 0x1c, 0x7e, 0x30, + 0x70, 0xe0, 0x5e, 0x44, 0x47, 0x27, 0x1e, 0x04, 0x7e, 0x98, 0x83, 0x00, + 0x5d, 0x5a, 0x7a, 0x4c, 0xeb, 0x23, 0x36, 0x62, 0x86, 0x4a, 0x55, 0xbd, + 0x4b, 0x08, 0x7c, 0xd4, 0xf9, 0xde, 0x67, 0x74, 0x1a, 0x79, 0x7c, 0xcf, + 0xbf, 0x31, 0xb6, 0xaa, 0x22, 0x71, 0x03, 0x9a, 0xd0, 0xc0, 0xe7, 0xa0, + 0x5a, 0xc2, 0x2b, 0x5d, 0x90, 0x6d, 0xcc, 0xa4, 0x8b, 0x1e, 0x2a, 0x51, + 0xa7, 0x29, 0xbb, 0x0c, 0xc9, 0xc2, 0x50, 0x3d, 0xec, 0xf8, 0x10, 0x77, + 0x8d, 0xad, 0x25, 0x11, 0xef, 0x53, 0x13, 0xbc, 0x85, 0x2f, 0x41, 0x1b, + 0xe3, 0x4e, 0xe9, 0x9f, 0xef, 0xd8, 0x7e, 0xbf, 0x1f, 0xe9, 0xc7, 0x44, + 0x64, 0xf2, 0x9a, 0xbf, 0xab, 0xff, 0x6d, 0xa7, 0x8a, 0x87, 0xb0, 0x21, + 0xa3, 0xfa, 0x1a, 0xaf, 0xac, 0xad, 0xea, 0x11, 0xac, 0xa6, 0xab, 0xee, + 0x0a, 0x70, 0x7c, 0xf0, 0xd6, 0x43, 0x8e, 0xff, 0xf6, 0xbb, 0x89, 0x21, + 0x60, 0xd2, 0xad, 0x3c, 0x92, 0x97, 0x8f, 0xbc, 0x33, 0x5f, 0x3b, 0xc8, + 0x15, 0x2e, 0x53, 0x67, 0x3e, 0x96, 0xf7, 0x7a, 0xc1, 0xf1, 0x29, 0x8f, + 0x20, 0x1f, 0xcd, 0xf5, 0x29, 0x7b, 0xe3, 0x5f, 0xa1, 0x92, 0xb0, 0x17, + 0x62, 0xf0, 0xd1, 0xc7, 0x20, 0xfb, 0x66, 0xce, 0xfa, 0x24, 0xe1, 0x7e, + 0x01, 0xc6, 0xdf, 0x7b, 0x31, 0x36, 0xa6, 0xae, 0x78, 0xfe, 0x9e, 0xb1, + 0x6b, 0xdf, 0xd2, 0x8a, 0x17, 0x1d, 0xf9, 0xe2, 0xfa, 0x76, 0xdf, 0x83, + 0xfc, 0xf7, 0xc5, 0xc8, 0x63, 0x13, 0x12, 0xf8, 0x23, 0x71, 0x3f, 0x29, + 0xe2, 0x5f, 0xa2, 0x87, 0x87, 0x65, 0x7d, 0xf4, 0x3d, 0x29, 0xe6, 0x58, + 0x04, 0xf3, 0x58, 0x8e, 0x3d, 0xb5, 0x53, 0x0f, 0xe1, 0xf0, 0x9c, 0x85, + 0x73, 0x70, 0x3b, 0xf4, 0xe1, 0xe6, 0x75, 0x81, 0xec, 0x13, 0xa8, 0x2f, + 0xc1, 0xed, 0xa2, 0x08, 0xb7, 0x79, 0xf3, 0xfd, 0xd0, 0x3b, 0xdf, 0xbd, + 0x7e, 0xc9, 0x1c, 0xc3, 0x2f, 0x99, 0xef, 0x3f, 0xd9, 0xa9, 0x7c, 0x1f, + 0x5b, 0x80, 0xe0, 0x91, 0x17, 0xc1, 0x9f, 0x0a, 0xb7, 0xb7, 0xc7, 0xe3, + 0x37, 0x62, 0xbf, 0x9a, 0xbb, 0x9b, 0x12, 0x40, 0x24, 0x3b, 0xdb, 0x55, + 0x16, 0xcd, 0x9c, 0xb7, 0x17, 0xbe, 0x99, 0xf3, 0xab, 0x77, 0xe6, 0x40, + 0x9b, 0xd0, 0xda, 0x63, 0xa7, 0x4d, 0x6b, 0xa3, 0xc5, 0xb6, 0x5a, 0x2c, + 0x80, 0x7d, 0xe2, 0xed, 0xc5, 0x25, 0xab, 0xdb, 0xb9, 0x6f, 0xe3, 0x24, + 0xfa, 0x77, 0x8c, 0xfe, 0x68, 0xba, 0x47, 0x97, 0xf8, 0x68, 0x6b, 0x74, + 0x17, 0xe6, 0xd0, 0x0b, 0x7c, 0xe8, 0xbd, 0x95, 0xf5, 0x64, 0xb5, 0x47, + 0x51, 0x97, 0xa5, 0xac, 0x67, 0x27, 0xe3, 0x4b, 0x7b, 0x72, 0x53, 0x36, + 0x45, 0x89, 0x8b, 0x24, 0x1a, 0x05, 0xc9, 0x8c, 0x1d, 0xee, 0xbb, 0xde, + 0x76, 0x08, 0xe8, 0xe5, 0x32, 0xa0, 0x78, 0x3c, 0x44, 0x01, 0x2c, 0xd7, + 0x5b, 0xaf, 0x3b, 0x37, 0x06, 0x34, 0xe5, 0x90, 0x4a, 0x49, 0x20, 0xf3, + 0xd8, 0xa9, 0x6f, 0xa7, 0xf2, 0x5d, 0xc2, 0xe5, 0x2a, 0x46, 0x3c, 0xe3, + 0x4a, 0xb6, 0x82, 0xb5, 0x80, 0x8f, 0xde, 0x7b, 0xf9, 0xa8, 0xef, 0x75, + 0x2e, 0x80, 0x06, 0xbe, 0x88, 0x8f, 0x36, 0xd9, 0xd6, 0x26, 0x0b, 0x81, + 0x8f, 0xde, 0x23, 0x1f, 0xb1, 0xf7, 0xb0, 0x58, 0x46, 0xbd, 0x52, 0x8c, + 0xe3, 0xbd, 0x7d, 0xf7, 0xfe, 0xab, 0x30, 0x8e, 0x38, 0x25, 0x0c, 0xdc, + 0xe9, 0x67, 0x30, 0x36, 0xda, 0xf6, 0xf3, 0xc8, 0x16, 0x1c, 0x1c, 0x72, + 0xd3, 0x58, 0x9c, 0x23, 0xde, 0xbe, 0xf7, 0x9d, 0x23, 0xbc, 0xd7, 0xfe, + 0xde, 0xaa, 0x9e, 0x3d, 0x92, 0x33, 0x6e, 0xb9, 0x69, 0x07, 0xa3, 0x06, + 0x02, 0x93, 0x9e, 0xfa, 0xf8, 0xfc, 0x15, 0x2f, 0x57, 0x97, 0x4f, 0x84, + 0xd1, 0xd5, 0x20, 0x7a, 0x3d, 0x33, 0xad, 0x89, 0xb7, 0x9a, 0xad, 0xc4, + 0x1c, 0xe6, 0xb7, 0x05, 0x0e, 0x5f, 0xd8, 0xe8, 0x23, 0xd1, 0x1e, 0x32, + 0x71, 0x3f, 0x82, 0x23, 0x7e, 0x59, 0x8c, 0xf8, 0x30, 0x87, 0xce, 0xb0, + 0xf0, 0xee, 0xc4, 0xa3, 0x11, 0x12, 0x9c, 0x91, 0xb8, 0x23, 0x8a, 0xa4, + 0xed, 0xa8, 0x98, 0xc2, 0x97, 0x14, 0xe6, 0x82, 0x5d, 0x67, 0xf1, 0x64, + 0x8f, 0x07, 0xc0, 0xb0, 0x26, 0xdb, 0x00, 0x6f, 0x7d, 0xa4, 0xf8, 0x42, + 0x77, 0x3c, 0x60, 0xf7, 0xd1, 0xb8, 0xee, 0x42, 0xeb, 0xc7, 0xf7, 0xab, + 0xdc, 0xcf, 0xed, 0xea, 0x75, 0x71, 0x87, 0x93, 0x5c, 0x87, 0xbd, 0x97, + 0x79, 0xa1, 0xbb, 0x1c, 0x33, 0x8e, 0xd5, 0x63, 0xba, 0x9d, 0xe6, 0xba, + 0x8b, 0xfe, 0x78, 0x82, 0x23, 0xaa, 0xfb, 0x67, 0x9d, 0xe3, 0x46, 0xe7, + 0x67, 0xdf, 0xed, 0x95, 0x74, 0x81, 0x4b, 0xde, 0x23, 0x70, 0x99, 0xba, + 0xb8, 0x48, 0x5f, 0xbc, 0x12, 0xe8, 0x4c, 0x17, 0xbb, 0xe3, 0x2d, 0x85, + 0x91, 0x7b, 0x66, 0x3a, 0xc1, 0xc7, 0x1d, 0x13, 0xf6, 0x4e, 0xbf, 0xf0, + 0xc8, 0x33, 0x0a, 0x4e, 0x4d, 0xc7, 0x5e, 0x89, 0x59, 0xaa, 0x75, 0xae, + 0x82, 0x2e, 0x9a, 0x4b, 0xe8, 0x76, 0x54, 0xca, 0xb2, 0xa0, 0x8b, 0x01, + 0x7d, 0x27, 0x79, 0x59, 0xff, 0xed, 0x95, 0xa7, 0xa7, 0xc7, 0x0b, 0xb5, + 0x3c, 0x00, 0xfe, 0x91, 0x33, 0xa0, 0xc3, 0x04, 0xab, 0xb3, 0x29, 0xe9, + 0xee, 0x78, 0x08, 0x1a, 0x07, 0xad, 0x8e, 0x4f, 0x75, 0xd7, 0xf1, 0xb2, + 0x03, 0xc1, 0x7a, 0xb4, 0xea, 0xee, 0x4a, 0x61, 0xd3, 0x17, 0xea, 0x3a, + 0x3f, 0x3e, 0x87, 0xbe, 0x79, 0x24, 0xe7, 0xb3, 0xf3, 0xeb, 0xca, 0x2b, + 0x03, 0xa4, 0xb9, 0x3c, 0xde, 0xab, 0xab, 0xdc, 0xd5, 0x1d, 0xc3, 0x80, + 0x2c, 0xd4, 0xe3, 0x5c, 0x9b, 0xee, 0x1e, 0xe1, 0x89, 0x7f, 0xf5, 0xaa, + 0x44, 0x86, 0x61, 0x5c, 0x9a, 0xe6, 0xed, 0xfe, 0x6b, 0x46, 0x08, 0x08, + 0x27, 0x3d, 0x17, 0x10, 0xc1, 0xb1, 0x63, 0xcb, 0x40, 0xb8, 0x2f, 0xf3, + 0x11, 0x21, 0x35, 0x26, 0xf8, 0xe4, 0x3f, 0xc5, 0x1b, 0x97, 0x2f, 0x2d, + 0x7f, 0x0d, 0x5c, 0x0a, 0x10, 0xc1, 0x4b, 0xbb, 0x2a, 0x70, 0xed, 0x5c, + 0x2d, 0x87, 0x88, 0xdf, 0x32, 0x5f, 0x85, 0x5a, 0x5e, 0x35, 0xf3, 0xbf, + 0xde, 0x99, 0xa7, 0x74, 0x95, 0x65, 0xa7, 0xde, 0x6b, 0xdf, 0xd4, 0xfb, + 0xdf, 0xc5, 0xaa, 0xcb, 0xc7, 0xcf, 0xbd, 0x2e, 0xae, 0x77, 0x93, 0x50, + 0xbc, 0xc9, 0x3b, 0x51, 0xea, 0x80, 0x9b, 0x24, 0x98, 0xdc, 0xa2, 0x49, + 0x5e, 0x9f, 0x25, 0x00, 0x71, 0xae, 0x1b, 0xb8, 0x3c, 0xf2, 0x49, 0x19, + 0xde, 0x00, 0x00, 0x09, 0xc1, 0x56, 0xda, 0x00, 0x7d, 0x48, 0x7a, 0x1c, + 0xb6, 0x37, 0x8c, 0xdc, 0x81, 0x0f, 0x30, 0x02, 0x17, 0xab, 0x5e, 0xbd, + 0xf6, 0xb9, 0x48, 0xdf, 0x14, 0x38, 0x02, 0x53, 0xa5, 0x47, 0x0a, 0x0d, + 0x11, 0x63, 0xa7, 0xd0, 0x81, 0x80, 0x1d, 0xc4, 0x93, 0x19, 0xab, 0x9e, + 0x1e, 0x14, 0xee, 0xa1, 0x91, 0x9d, 0xce, 0x51, 0x8a, 0xf2, 0x31, 0x57, + 0x08, 0x8f, 0x11, 0xc2, 0x44, 0x90, 0x85, 0x68, 0xad, 0x15, 0xc6, 0x67, + 0x59, 0x56, 0x99, 0xe9, 0x2e, 0x3b, 0x23, 0x1f, 0xa2, 0x23, 0xee, 0x46, + 0xd5, 0x9f, 0x72, 0x3f, 0xdd, 0xdc, 0x71, 0xb1, 0xd4, 0x32, 0x44, 0x25, + 0xb5, 0xac, 0x00, 0xdb, 0x69, 0x3c, 0x4d, 0x7a, 0x73, 0xd6, 0x20, 0xaa, + 0xe0, 0xb1, 0x5c, 0x9a, 0x80, 0x4a, 0xaa, 0x53, 0x39, 0xa8, 0xf2, 0x04, + 0x5c, 0x42, 0xa9, 0x6a, 0x10, 0xd0, 0xbd, 0x0f, 0xa3, 0xf4, 0xad, 0x5f, + 0x97, 0x78, 0x22, 0x76, 0xdf, 0xa9, 0x7c, 0x7f, 0xec, 0x8b, 0x08, 0x58, + 0x4a, 0xad, 0xbb, 0x24, 0xf9, 0x88, 0x16, 0x13, 0x2e, 0xac, 0x4e, 0x62, + 0x7a, 0x49, 0x9b, 0x1e, 0x61, 0xf1, 0x90, 0xed, 0x1b, 0x2c, 0xc7, 0x3a, + 0xf1, 0x20, 0x53, 0x31, 0xaa, 0x85, 0x3f, 0x02, 0x17, 0x4b, 0xbd, 0xb4, + 0xbe, 0x48, 0xff, 0xce, 0x26, 0x79, 0xf1, 0x8c, 0xfc, 0xe9, 0x19, 0x8a, + 0x65, 0xfc, 0xc9, 0x17, 0xba, 0x2d, 0xf1, 0x3f, 0x45, 0x72, 0xed, 0x3c, + 0x18, 0xe8, 0x66, 0x3d, 0xc1, 0xdb, 0xda, 0x59, 0xb8, 0x10, 0x94, 0xdc, + 0xcb, 0x9f, 0x58, 0xe0, 0xf8, 0xd0, 0x4f, 0x0a, 0xae, 0x73, 0xce, 0xdd, + 0x87, 0x14, 0xe3, 0xb8, 0x5e, 0xf6, 0xe6, 0x12, 0x81, 0x2f, 0x62, 0x71, + 0xca, 0x2e, 0x38, 0x62, 0x14, 0x6f, 0x9e, 0x12, 0xc9, 0x6f, 0x8a, 0xee, + 0x29, 0xa6, 0x30, 0x2a, 0x74, 0x26, 0x9a, 0x0b, 0xbe, 0x00, 0xb6, 0xea, + 0xc5, 0x2b, 0x7f, 0x2f, 0x34, 0xd7, 0x4b, 0xdb, 0x34, 0x37, 0x74, 0x7b, + 0xe9, 0xa1, 0x50, 0x12, 0x97, 0x26, 0x2e, 0xf8, 0xd8, 0x94, 0xeb, 0xba, + 0x27, 0x68, 0x77, 0x31, 0xce, 0xde, 0x0b, 0x03, 0x73, 0x51, 0x7e, 0xb2, + 0x00, 0xe5, 0x14, 0xdf, 0x95, 0x1b, 0x0f, 0xd0, 0x8c, 0x3d, 0xee, 0x85, + 0xfc, 0x46, 0xd2, 0x62, 0x9c, 0x9d, 0x88, 0x6e, 0x8f, 0x21, 0xd2, 0xfe, + 0x38, 0x8d, 0xbe, 0x2e, 0x85, 0xca, 0xcb, 0x3d, 0xbf, 0x31, 0x76, 0x12, + 0x07, 0x7d, 0x76, 0x72, 0x74, 0x98, 0xd2, 0xe4, 0x39, 0x39, 0x29, 0x98, + 0x3b, 0x9d, 0x0b, 0xf6, 0x9b, 0x37, 0xe3, 0x89, 0x9b, 0xce, 0xd9, 0xe9, + 0xb7, 0xfc, 0x9e, 0xe9, 0xa7, 0x92, 0x1b, 0x01, 0xc8, 0x1d, 0x13, 0x11, + 0x51, 0x75, 0x36, 0x2c, 0x26, 0x90, 0xa8, 0xe2, 0xbb, 0xbf, 0xe6, 0x59, + 0x0e, 0xcb, 0xb1, 0x87, 0x8b, 0x06, 0xea, 0x47, 0x93, 0x38, 0xe3, 0x7e, + 0x6a, 0xb8, 0x93, 0x7d, 0x25, 0x6c, 0xb8, 0xd6, 0x0c, 0xc6, 0x00, 0x87, + 0xe0, 0xb1, 0x72, 0xc4, 0xff, 0x55, 0x2d, 0x84, 0xc4, 0x2f, 0x03, 0xf4, + 0x86, 0xf0, 0xaf, 0x0b, 0xff, 0x92, 0x3d, 0x5a, 0xd3, 0x13, 0x1f, 0xd3, + 0x24, 0x8f, 0xd9, 0x82, 0x5f, 0xcd, 0x19, 0x39, 0x71, 0x96, 0x17, 0xeb, + 0xd0, 0x7b, 0x7c, 0x93, 0xa6, 0xdc, 0x36, 0x5c, 0x6e, 0x46, 0x3b, 0x4c, + 0x82, 0x6c, 0x71, 0x3c, 0xbe, 0x04, 0x1e, 0x09, 0xf0, 0x3a, 0xf0, 0x17, + 0xed, 0xf7, 0x65, 0xb5, 0x34, 0x4b, 0x6e, 0xf9, 0x29, 0x7d, 0x59, 0xac, + 0xae, 0x31, 0x47, 0x34, 0xf5, 0x0d, 0x55, 0xfa, 0xb5, 0x87, 0x0a, 0xb5, + 0x40, 0xcb, 0x8f, 0xd3, 0x3c, 0x68, 0x0b, 0x34, 0x38, 0xcb, 0xcb, 0x9a, + 0x5a, 0x21, 0x90, 0x95, 0x63, 0x72, 0x4f, 0x31, 0x25, 0xc0, 0xfb, 0x40, + 0xd0, 0x32, 0x9b, 0xf9, 0xc8, 0x9d, 0x95, 0x5d, 0x4e, 0xe7, 0xb1, 0xa8, + 0x08, 0x71, 0xf2, 0x18, 0x36, 0x7d, 0xd4, 0xda, 0xfd, 0x63, 0x90, 0x8c, + 0x61, 0xe1, 0x79, 0x1d, 0x0e, 0x87, 0xef, 0x51, 0x07, 0xfe, 0xe8, 0x19, + 0xb1, 0x8c, 0xe8, 0xad, 0x9b, 0x57, 0xea, 0x93, 0x37, 0x70, 0x86, 0x9d, + 0x26, 0x0b, 0xf7, 0x8f, 0xe2, 0xf6, 0xe5, 0x79, 0x4f, 0xb9, 0x2c, 0xff, + 0x18, 0x8d, 0x61, 0x35, 0x5c, 0x08, 0xf0, 0xf1, 0xdc, 0x36, 0xa5, 0x2f, + 0xa5, 0x54, 0x99, 0x16, 0xf3, 0x4c, 0x7d, 0xcc, 0x33, 0x2d, 0x3d, 0x57, + 0x97, 0x18, 0xdc, 0xd3, 0x20, 0xb9, 0x89, 0xc6, 0x5f, 0x3e, 0xb6, 0x4b, + 0xe8, 0x5c, 0x97, 0x9d, 0xb1, 0xee, 0x8c, 0x9c, 0xec, 0xe9, 0xb4, 0xc9, + 0xdf, 0xd9, 0x9d, 0x8f, 0x56, 0x77, 0x5f, 0x63, 0xa2, 0xf5, 0xe2, 0xc9, + 0x8c, 0xe6, 0xd7, 0xe2, 0xe9, 0xb5, 0x44, 0x6f, 0x70, 0xe9, 0x19, 0xe2, + 0xaf, 0x2e, 0xfe, 0x4a, 0x60, 0x84, 0xee, 0x7d, 0x3d, 0xb8, 0x2f, 0xdb, + 0x83, 0x9c, 0x0f, 0xaa, 0xd9, 0x85, 0x70, 0x8c, 0x67, 0xd7, 0x37, 0xd1, + 0x10, 0x8e, 0x2e, 0x65, 0x97, 0x8a, 0x65, 0xd6, 0xd2, 0x07, 0x7d, 0x8a, + 0x93, 0xd7, 0xab, 0x8c, 0x1b, 0x46, 0xfc, 0x20, 0x77, 0xf4, 0x3f, 0x57, + 0x17, 0xfb, 0x7e, 0x0b, 0x0f, 0x87, 0x20, 0x22, 0x6d, 0x28, 0xc5, 0x02, + 0xea, 0x52, 0xf0, 0xba, 0xc4, 0xd1, 0x03, 0x06, 0x02, 0xe2, 0xb2, 0xca, + 0xfe, 0xc1, 0x91, 0x17, 0x40, 0x6f, 0xcf, 0x61, 0x90, 0xbf, 0x8b, 0x97, + 0xdb, 0x1c, 0x72, 0x3e, 0x7c, 0x0d, 0x86, 0x18, 0x44, 0xb8, 0x91, 0x7f, + 0x0d, 0xb9, 0x40, 0x9e, 0xac, 0x14, 0xa9, 0x16, 0x2d, 0x42, 0x22, 0x70, + 0xd4, 0x2f, 0xbf, 0x7c, 0xdd, 0x8d, 0x70, 0x0a, 0xec, 0xf7, 0xef, 0x45, + 0x73, 0xee, 0xef, 0x6e, 0x11, 0x4e, 0xd2, 0x7f, 0x7f, 0x45, 0x0e, 0x15, + 0x2f, 0x82, 0x72, 0xad, 0xcf, 0x3c, 0xed, 0xf4, 0x97, 0x49, 0x77, 0xe4, + 0xd7, 0xf1, 0xf5, 0xe7, 0xc1, 0x08, 0xa8, 0xe8, 0x73, 0x8e, 0x76, 0xa8, + 0xf8, 0xbb, 0x8f, 0x8a, 0xbf, 0x7f, 0x15, 0x2a, 0xe2, 0x23, 0xe0, 0x9c, + 0x84, 0xfc, 0x91, 0xd2, 0xbf, 0x4c, 0x3a, 0xa6, 0x2b, 0x3e, 0x77, 0xe1, + 0xd1, 0x5f, 0x43, 0xc8, 0x14, 0xdd, 0xeb, 0x7d, 0x54, 0xfa, 0xe3, 0xab, + 0x50, 0x49, 0xcc, 0x3a, 0x41, 0xa9, 0x85, 0x96, 0xf7, 0x65, 0xb1, 0x67, + 0x23, 0xdc, 0xbb, 0x73, 0x71, 0x5f, 0xb8, 0xd3, 0x19, 0xc8, 0xec, 0x07, + 0xe4, 0x41, 0xe0, 0x73, 0x9d, 0x3a, 0x3a, 0x38, 0x3e, 0x58, 0xad, 0xb1, + 0xf7, 0x57, 0x1b, 0xed, 0x26, 0xf9, 0x20, 0x4c, 0x27, 0x0d, 0x1f, 0x19, + 0x3e, 0x7f, 0x8d, 0xe3, 0xb8, 0xf0, 0xb6, 0x24, 0x64, 0xbe, 0x9e, 0x0e, + 0x97, 0x77, 0xde, 0x09, 0x32, 0x23, 0x3d, 0xc7, 0x16, 0x74, 0xfe, 0xd0, + 0xed, 0xbc, 0xaf, 0xef, 0x7f, 0x7e, 0x8d, 0xbe, 0x0b, 0xcf, 0xb3, 0xaf, + 0xd4, 0xf7, 0xe2, 0x78, 0x17, 0x4e, 0x38, 0x0b, 0xa4, 0x10, 0xfa, 0x56, + 0x94, 0x8f, 0x65, 0xb1, 0x62, 0x81, 0x53, 0xd7, 0x71, 0xcc, 0x5b, 0x47, + 0x76, 0xcf, 0xad, 0x2c, 0xcf, 0xa5, 0xa1, 0x7e, 0x2f, 0xd5, 0x78, 0xfe, + 0x05, 0x17, 0x7e, 0x4b, 0x28, 0x5b, 0x81, 0x8a, 0xef, 0x80, 0xf5, 0xea, + 0x87, 0x90, 0x39, 0x0e, 0xfb, 0x18, 0xf8, 0x84, 0x8b, 0x08, 0xef, 0x0e, + 0x7f, 0x70, 0x23, 0x50, 0xd0, 0x90, 0xe7, 0x74, 0x99, 0xf9, 0x21, 0x20, + 0xa8, 0x52, 0x04, 0x11, 0xb6, 0x03, 0x19, 0x32, 0x95, 0xb4, 0xc8, 0x9d, + 0xce, 0x6a, 0x2e, 0x3c, 0x7c, 0x06, 0x85, 0x77, 0x59, 0xd8, 0xbb, 0x8d, + 0x59, 0x1d, 0xe3, 0x66, 0x87, 0x17, 0x7f, 0xff, 0xed, 0xc9, 0xe4, 0x9f, + 0xe1, 0x3f, 0xff, 0x59, 0xf1, 0x60, 0xf1, 0xf7, 0xdf, 0x72, 0x78, 0xe0, + 0xc3, 0x0b, 0x93, 0xcc, 0x77, 0x53, 0xc9, 0x29, 0x88, 0xcf, 0x2d, 0xdc, + 0x05, 0xc3, 0xc8, 0x88, 0xb1, 0xe2, 0x94, 0x90, 0x74, 0x9b, 0x64, 0xbe, + 0xcb, 0xc8, 0x6b, 0x14, 0x84, 0xa4, 0x73, 0xb0, 0x9f, 0xcb, 0xe1, 0xb8, + 0x3d, 0xc9, 0xe3, 0x86, 0x3f, 0x84, 0x5b, 0xa5, 0x09, 0xb9, 0x79, 0xfd, + 0xb1, 0x9f, 0x8a, 0x66, 0x63, 0x27, 0x45, 0x8d, 0xb9, 0x0a, 0x76, 0xb3, + 0xb1, 0xad, 0x16, 0x64, 0x3f, 0xa2, 0xb5, 0xab, 0xd7, 0xa7, 0x05, 0xcd, + 0xb9, 0x6e, 0x2f, 0x66, 0x6b, 0xf9, 0x37, 0xd4, 0xf0, 0xe7, 0x69, 0xee, + 0xc9, 0x14, 0x7c, 0x14, 0xa7, 0xa0, 0xa8, 0x79, 0x47, 0xaa, 0x18, 0x08, + 0x0f, 0xef, 0x3d, 0x17, 0x4e, 0xb2, 0x6c, 0xb7, 0x3b, 0xdf, 0x5f, 0x16, + 0x74, 0xd9, 0xbd, 0xe5, 0xc0, 0x7f, 0xc4, 0x68, 0x8e, 0x96, 0x6a, 0xa7, + 0x40, 0xb5, 0x8e, 0x3f, 0xbe, 0x15, 0x0a, 0xa3, 0x0b, 0x5f, 0x64, 0x72, + 0x7d, 0x9a, 0x64, 0x1e, 0xc3, 0x83, 0xa2, 0xfd, 0x1c, 0x34, 0xec, 0x44, + 0x7f, 0xd0, 0x72, 0xf4, 0x8b, 0xac, 0xd2, 0x32, 0x72, 0x81, 0x8f, 0xfe, + 0x3d, 0xe5, 0xf3, 0x03, 0x08, 0xf9, 0xf7, 0x04, 0xbf, 0x43, 0x23, 0x4f, + 0xf9, 0x2a, 0x03, 0xd3, 0x31, 0x87, 0x46, 0xc1, 0x0a, 0xc0, 0xc3, 0x1b, + 0x24, 0xa3, 0x5e, 0x30, 0x59, 0xe3, 0x07, 0x91, 0x41, 0xcc, 0x0e, 0xf1, + 0xed, 0xc7, 0xea, 0x03, 0x5a, 0xba, 0x6a, 0x2c, 0x7c, 0x98, 0x84, 0x49, + 0xc4, 0xe3, 0x29, 0x7a, 0x17, 0x9b, 0xa7, 0x79, 0xee, 0x5e, 0xb0, 0xdc, + 0xe4, 0x1a, 0x94, 0x0b, 0x8f, 0xaf, 0xc9, 0x3c, 0x90, 0x9b, 0xe9, 0x10, + 0xdf, 0x99, 0xc6, 0xb2, 0xac, 0x1f, 0x87, 0x29, 0x1b, 0xc7, 0x19, 0xc3, + 0xb7, 0xce, 0xd1, 0x24, 0x37, 0xc1, 0xd7, 0xb7, 0xe9, 0x89, 0x22, 0x0a, + 0x93, 0xca, 0x63, 0x72, 0xe7, 0x16, 0xb2, 0x2b, 0xcc, 0xed, 0xe1, 0x33, + 0xb4, 0x01, 0xba, 0xf6, 0x05, 0x2c, 0x1d, 0x61, 0x14, 0x55, 0xfe, 0x2a, + 0x06, 0xde, 0xeb, 0xb9, 0x8b, 0x46, 0x73, 0x57, 0xbf, 0x31, 0x5f, 0xfe, + 0x9e, 0xfe, 0xb6, 0xd5, 0xdd, 0xda, 0x28, 0x5a, 0x00, 0x9f, 0xfe, 0xa5, + 0x0b, 0xe0, 0x7c, 0x9e, 0x78, 0xfa, 0x48, 0x9e, 0x28, 0x60, 0xff, 0x22, + 0xd6, 0xe7, 0x1b, 0x96, 0x64, 0x7f, 0x73, 0x0f, 0x2b, 0x68, 0x4c, 0x27, + 0xe4, 0xef, 0x68, 0x2f, 0xbc, 0x87, 0xed, 0xdd, 0xce, 0xcb, 0xdd, 0xd1, + 0xb6, 0xde, 0x45, 0xd3, 0xb7, 0x43, 0x8b, 0xee, 0x6e, 0xf3, 0x86, 0xf8, + 0xed, 0xdb, 0x6f, 0xc4, 0xdd, 0x56, 0xe3, 0xdb, 0xd3, 0x9c, 0x6d, 0xcb, + 0xd7, 0x01, 0xe7, 0x92, 0xb2, 0x7b, 0x78, 0xa0, 0x36, 0xa4, 0xef, 0x0f, + 0x8a, 0x08, 0x39, 0x37, 0xa4, 0xd2, 0x40, 0x3d, 0xd5, 0x44, 0x17, 0xe6, + 0xdd, 0x95, 0xce, 0xd7, 0xcd, 0x37, 0xe8, 0xd4, 0x9f, 0x7b, 0xbf, 0x9a, + 0x47, 0xfb, 0xb6, 0xae, 0x58, 0xbf, 0xc1, 0x5b, 0x3a, 0xa7, 0x24, 0x9d, + 0xee, 0x5f, 0x1c, 0x7c, 0xfd, 0xc8, 0x29, 0x65, 0x99, 0xc0, 0x45, 0x5b, + 0x26, 0xea, 0x07, 0xa6, 0xbc, 0xcf, 0x35, 0xa8, 0xf3, 0x8f, 0xf1, 0x7a, + 0xa1, 0xf9, 0xf2, 0x53, 0xcd, 0xca, 0x3f, 0x1a, 0xf7, 0x17, 0x3c, 0x47, + 0x35, 0x1c, 0xfb, 0x1f, 0xa4, 0x22, 0x28, 0x54, 0x82, 0xbf, 0xcf, 0x8b, + 0x93, 0x36, 0xf9, 0xe7, 0xb8, 0x22, 0xc0, 0x01, 0x21, 0x41, 0xe6, 0x63, + 0xca, 0x17, 0x85, 0xde, 0xf6, 0xbf, 0xcd, 0xb2, 0x49, 0xba, 0xbb, 0xb6, + 0xd6, 0x47, 0x5b, 0x2d, 0xc6, 0x37, 0x69, 0x8c, 0xe2, 0x7f, 0x47, 0xc3, + 0x61, 0xd0, 0x88, 0x93, 0x9b, 0xb5, 0x70, 0x5c, 0x7f, 0xd7, 0x59, 0xeb, + 0xc7, 0xbd, 0x74, 0xed, 0xf0, 0xfc, 0x74, 0x0d, 0xaa, 0x77, 0xe3, 0x20, + 0xe9, 0xd3, 0x29, 0xd7, 0x87, 0xde, 0xa7, 0x70, 0x46, 0xf7, 0x7b, 0x0d, + 0xf4, 0xc2, 0x3b, 0xfd, 0x5a, 0x96, 0xf1, 0x0c, 0x22, 0xd1, 0xae, 0x86, + 0x91, 0xf2, 0x68, 0xf4, 0xa5, 0x1c, 0x16, 0xde, 0x21, 0x0c, 0xbc, 0x61, + 0x6e, 0x3c, 0x41, 0x87, 0xd1, 0xf5, 0xd2, 0x49, 0xd0, 0xe3, 0x3a, 0x57, + 0x62, 0x12, 0x15, 0xda, 0x81, 0xde, 0xbd, 0xbf, 0x6b, 0xd0, 0x8b, 0x2f, + 0x80, 0x9e, 0x39, 0xde, 0x00, 0x88, 0xbd, 0x10, 0x4f, 0xe7, 0xec, 0x21, + 0x9c, 0x7f, 0xbd, 0xf5, 0x0d, 0xa0, 0x1e, 0x57, 0x55, 0xe1, 0xd9, 0x40, + 0x54, 0x90, 0xcf, 0x09, 0x1b, 0xc5, 0x71, 0x09, 0x0f, 0xba, 0x1a, 0x93, + 0x9d, 0x65, 0x30, 0x69, 0x75, 0xaf, 0xff, 0x37, 0x7f, 0x50, 0xf0, 0x63, + 0x91, 0xa9, 0x82, 0x76, 0xeb, 0xfc, 0x11, 0xc6, 0x35, 0x0c, 0x3e, 0x9c, + 0x68, 0x34, 0x74, 0x68, 0x0d, 0x59, 0x3f, 0x29, 0xa8, 0xcf, 0x9d, 0xcd, + 0x75, 0xcd, 0xf6, 0x33, 0xb7, 0x26, 0xce, 0x0c, 0x7f, 0xdd, 0x61, 0x38, + 0xc8, 0xea, 0x01, 0x2c, 0xe0, 0xf7, 0xba, 0xfe, 0xfa, 0x33, 0x93, 0x02, + 0xc4, 0x83, 0x46, 0x8c, 0x43, 0xae, 0x8d, 0x2e, 0x20, 0xc6, 0xf9, 0x21, + 0xa7, 0x33, 0x86, 0xf0, 0x0d, 0x52, 0xf6, 0xaf, 0xeb, 0x73, 0x7a, 0x44, + 0xec, 0x59, 0xbd, 0x1b, 0x65, 0xc6, 0xfc, 0x57, 0x35, 0xb6, 0x07, 0x76, + 0x05, 0x8c, 0xf9, 0x4b, 0x35, 0xb6, 0xad, 0x1a, 0xf3, 0x07, 0x17, 0xc6, + 0xe0, 0xb0, 0x88, 0xb4, 0x18, 0xdf, 0x33, 0xd7, 0xbf, 0x9d, 0xc7, 0xf7, + 0xef, 0xa0, 0xec, 0x60, 0x23, 0x56, 0x07, 0x05, 0x58, 0x4d, 0x27, 0x39, + 0x94, 0xb6, 0x1f, 0x8f, 0xd2, 0xfe, 0x22, 0x94, 0x04, 0x1f, 0xf7, 0xb2, + 0x64, 0xe8, 0xb0, 0xb1, 0x21, 0x98, 0xe3, 0xdd, 0xe7, 0xaa, 0xf5, 0xb4, + 0x39, 0x67, 0x4b, 0x14, 0x87, 0x7a, 0xe1, 0x10, 0x67, 0xbd, 0x82, 0xeb, + 0x6e, 0x10, 0x66, 0x9f, 0x35, 0x36, 0x9f, 0xbd, 0x7d, 0x47, 0xf7, 0x63, + 0xb7, 0xf7, 0x1b, 0xcd, 0xc7, 0xf7, 0xfe, 0xf5, 0xd7, 0xeb, 0xfd, 0x97, + 0x77, 0xfe, 0xf5, 0xa2, 0xce, 0x93, 0xba, 0xc4, 0xe8, 0xf8, 0x96, 0x67, + 0xa6, 0x5e, 0xaf, 0xff, 0x59, 0xc0, 0x37, 0x5c, 0xd3, 0x64, 0x54, 0xdf, + 0xf4, 0x55, 0x6f, 0x17, 0x55, 0xbf, 0x8d, 0x47, 0x46, 0xdb, 0xeb, 0x5b, + 0xf3, 0x88, 0xce, 0x23, 0x99, 0x16, 0x11, 0xfd, 0xed, 0x12, 0xb3, 0xc0, + 0x28, 0xec, 0x2c, 0x5b, 0xe3, 0xbe, 0x81, 0xcd, 0xe6, 0xe3, 0xb1, 0x79, + 0xb3, 0x0c, 0x36, 0x6f, 0x0a, 0xb0, 0x99, 0xe0, 0x9b, 0x26, 0x42, 0x53, + 0xc6, 0x31, 0x5a, 0x2f, 0xb1, 0x0f, 0xe4, 0x26, 0x90, 0x90, 0x05, 0xe4, + 0x2b, 0x94, 0x5f, 0xcc, 0x51, 0x9b, 0x7f, 0x2e, 0x60, 0x29, 0xc2, 0x1b, + 0x27, 0x95, 0x81, 0xf9, 0xc6, 0x23, 0x30, 0xb7, 0xf1, 0xfe, 0x52, 0xb4, + 0xb7, 0x16, 0xa1, 0xfd, 0xa6, 0x65, 0xec, 0x74, 0x3a, 0xb6, 0x94, 0x39, + 0x52, 0x17, 0x05, 0x23, 0xf5, 0xa6, 0x6d, 0x56, 0xcd, 0xed, 0x92, 0x58, + 0xf5, 0x7f, 0x8a, 0xaa, 0xae, 0x9b, 0x55, 0x37, 0x7c, 0x55, 0x2f, 0x8b, + 0xaa, 0x6e, 0x98, 0x55, 0x7d, 0x13, 0xef, 0xbc, 0x53, 0x54, 0x75, 0xd3, + 0xac, 0xea, 0x9d, 0xf2, 0xad, 0xcd, 0xa2, 0x49, 0xfb, 0x66, 0xcb, 0xac, + 0xec, 0xdb, 0xd9, 0xaf, 0x5b, 0xcf, 0x0a, 0x2b, 0x3f, 0x33, 0x2b, 0x6f, + 0x7b, 0x2b, 0x6f, 0x17, 0x56, 0xde, 0x36, 0x2b, 0xef, 0x78, 0x2b, 0xef, + 0x14, 0x56, 0xde, 0x31, 0x2a, 0xb7, 0x9b, 0xde, 0x75, 0xaa, 0x59, 0x58, + 0xb9, 0xd5, 0x34, 0x6b, 0xb7, 0xbc, 0xb5, 0x5b, 0xc5, 0xb5, 0x4d, 0xde, + 0x6a, 0xfb, 0x78, 0xeb, 0xba, 0x5d, 0xb8, 0xc6, 0xbe, 0x69, 0x99, 0xec, + 0xd5, 0xf6, 0xb1, 0xd7, 0x75, 0x7b, 0xc3, 0x5b, 0xdb, 0x39, 0x23, 0x03, + 0xb0, 0xa0, 0xfe, 0x6f, 0x3a, 0xe3, 0x68, 0x59, 0x77, 0xde, 0x7e, 0x24, + 0x72, 0x84, 0xb8, 0x8c, 0xa1, 0x9e, 0xb6, 0x36, 0xf1, 0x74, 0x69, 0xa4, + 0x3d, 0x7f, 0xc1, 0x76, 0x9a, 0xf9, 0xc8, 0x41, 0x00, 0xab, 0x6e, 0xaa, + 0x34, 0xcd, 0xc7, 0x8e, 0xc3, 0x10, 0x97, 0xcf, 0xdc, 0xfb, 0x6e, 0xee, + 0xa1, 0x96, 0x2e, 0x0e, 0xaa, 0x5b, 0x26, 0xdc, 0x30, 0x25, 0xd3, 0x0c, + 0x04, 0xf0, 0xa4, 0xb5, 0xb5, 0x59, 0x70, 0xfd, 0x84, 0x24, 0xd8, 0x0b, + 0x02, 0x97, 0x7f, 0x83, 0xaf, 0x70, 0x21, 0xe1, 0x3f, 0x56, 0xbc, 0x2f, + 0x4f, 0xf7, 0xde, 0xfb, 0xba, 0x67, 0xa3, 0xee, 0xa0, 0xb9, 0xbd, 0xe5, + 0x3d, 0x37, 0x0f, 0x43, 0x72, 0xa9, 0xf2, 0x21, 0xa9, 0x5f, 0x43, 0x9f, + 0x87, 0xc9, 0x81, 0x83, 0x49, 0x0e, 0x15, 0xf9, 0xc0, 0x9e, 0x26, 0xe2, + 0xaa, 0x8f, 0x8a, 0xcf, 0x7c, 0x43, 0x42, 0x15, 0xef, 0xa2, 0x74, 0x1a, + 0x0c, 0x4f, 0x8d, 0x33, 0x93, 0xfe, 0x21, 0x0f, 0x9e, 0x51, 0x18, 0x4f, + 0xb3, 0x6a, 0xee, 0x91, 0x79, 0xbb, 0xdc, 0x70, 0xc0, 0xfb, 0xfa, 0x9e, + 0xa0, 0xe5, 0x07, 0xe4, 0x73, 0x8d, 0xb9, 0x6f, 0x0b, 0x7c, 0x5e, 0x82, + 0x1c, 0x7c, 0x42, 0x70, 0x15, 0x5d, 0x63, 0x90, 0xc4, 0xa3, 0x03, 0x11, + 0x49, 0xcc, 0xe4, 0xe1, 0x3a, 0xdb, 0xda, 0x58, 0xf5, 0x2a, 0x5d, 0x1c, + 0x6a, 0xac, 0xb7, 0x73, 0x5c, 0x7d, 0xf6, 0xee, 0xa4, 0x54, 0x73, 0xcd, + 0x85, 0x0d, 0xc0, 0x4c, 0xda, 0x6c, 0xe5, 0x67, 0xd2, 0xe6, 0x66, 0xae, + 0x4d, 0x7e, 0x94, 0xaa, 0x51, 0x54, 0x49, 0x20, 0xe1, 0xa4, 0xc6, 0x6e, + 0x92, 0x78, 0x3a, 0xe1, 0x1f, 0x93, 0xb0, 0x17, 0x27, 0x7d, 0xfe, 0x79, + 0x3a, 0x8e, 0x32, 0xfc, 0xb4, 0x3c, 0x41, 0x00, 0x93, 0xa7, 0x70, 0x44, + 0x2b, 0x45, 0x95, 0xcd, 0xad, 0x1c, 0x86, 0x86, 0x08, 0xb9, 0xa8, 0xd9, + 0x56, 0xc9, 0x56, 0xda, 0xad, 0x9d, 0x5c, 0x33, 0xff, 0xba, 0x06, 0x54, + 0x8d, 0x83, 0xe5, 0xa2, 0xb6, 0xca, 0x36, 0xd5, 0x6e, 0xe5, 0x9b, 0xfa, + 0x00, 0x4d, 0x29, 0x32, 0x97, 0x6b, 0x6d, 0x67, 0x35, 0xaf, 0xc4, 0x31, + 0x5a, 0x15, 0x2b, 0x5b, 0x94, 0x9e, 0x06, 0x3d, 0x31, 0xee, 0xc1, 0x90, + 0x4b, 0x40, 0x30, 0x39, 0xab, 0xb9, 0xcc, 0x51, 0x98, 0x05, 0x98, 0xfb, + 0xe5, 0xab, 0xb1, 0x79, 0xe2, 0x86, 0x71, 0x5e, 0xc0, 0x0d, 0x4f, 0x91, + 0xef, 0xcb, 0xd0, 0xad, 0xb5, 0xd3, 0x2e, 0x6c, 0xe7, 0xd7, 0x4a, 0x09, + 0xfe, 0xdf, 0xd8, 0xf6, 0xf0, 0xff, 0xb3, 0xb9, 0xb8, 0xdb, 0x6c, 0xbb, + 0xb1, 0xed, 0x23, 0xb9, 0xbb, 0x09, 0x7e, 0x96, 0xaf, 0x99, 0x7f, 0xf3, + 0x09, 0x89, 0x2d, 0xd6, 0x7c, 0xfe, 0xcc, 0xc3, 0x8a, 0x77, 0xe1, 0xb6, + 0x5e, 0x37, 0xf7, 0xac, 0xcd, 0xde, 0x6d, 0xe3, 0xb3, 0x05, 0xcc, 0x5c, + 0x67, 0x0d, 0x60, 0x80, 0x01, 0xf7, 0x84, 0x82, 0x5a, 0xa4, 0x97, 0x5a, + 0x08, 0x91, 0x6f, 0x62, 0xa3, 0x28, 0xab, 0x56, 0xa0, 0x38, 0x0a, 0xd5, + 0x95, 0x1a, 0x13, 0x05, 0xec, 0xbc, 0x0a, 0x01, 0x14, 0x99, 0x32, 0x37, + 0xbd, 0x8d, 0xef, 0xcd, 0xe7, 0x4a, 0x28, 0x91, 0x07, 0x33, 0x4e, 0xaa, + 0xbc, 0xfd, 0x15, 0x6f, 0xf3, 0x45, 0xaf, 0xf1, 0xcb, 0x37, 0x60, 0x4c, + 0xed, 0xdb, 0x8d, 0xa1, 0x19, 0xbc, 0x19, 0x8a, 0xdc, 0x1b, 0xd5, 0x9c, + 0x0e, 0x93, 0x6d, 0x7e, 0x4d, 0xaf, 0x6f, 0x3e, 0xcc, 0x6d, 0xe6, 0x40, + 0x55, 0xd3, 0x0d, 0xd5, 0xe4, 0x2b, 0x0f, 0x46, 0x8b, 0x06, 0x3c, 0xfb, + 0x6d, 0x2b, 0x35, 0x18, 0x12, 0x27, 0x60, 0xda, 0x1b, 0x6b, 0x38, 0x34, + 0x66, 0x46, 0xb5, 0xcf, 0x45, 0x48, 0x01, 0xb9, 0x80, 0x0f, 0xd2, 0xb4, + 0x48, 0xf1, 0x28, 0xd5, 0x8c, 0x26, 0x19, 0x57, 0xb4, 0x70, 0x25, 0xe6, + 0x9a, 0x44, 0x80, 0x73, 0xb6, 0x91, 0x41, 0x6d, 0x5b, 0x73, 0xe5, 0xfe, + 0x36, 0x22, 0x45, 0x32, 0x85, 0x17, 0xcf, 0xd5, 0x13, 0xf3, 0xa0, 0xa8, + 0x1a, 0x2a, 0xff, 0x9b, 0x62, 0x82, 0xc9, 0x26, 0x78, 0x62, 0x0e, 0x12, + 0x55, 0x30, 0xe0, 0xfc, 0x6e, 0xf2, 0xa4, 0x7a, 0x36, 0xc4, 0x9a, 0x47, + 0xb8, 0x66, 0x69, 0x89, 0x51, 0x7c, 0xe3, 0xeb, 0x99, 0xf8, 0x22, 0xd7, + 0x2f, 0x07, 0xce, 0xca, 0xbc, 0x35, 0x54, 0x31, 0xe4, 0x23, 0x26, 0xa5, + 0x9c, 0x5f, 0x22, 0xd5, 0x3b, 0xbf, 0xf2, 0x7d, 0xf9, 0x82, 0xc9, 0x6a, + 0x03, 0xb3, 0xe7, 0xe2, 0x04, 0xf9, 0xc4, 0x9a, 0x90, 0x5f, 0x7f, 0xb6, + 0x8a, 0xf6, 0x0b, 0x67, 0xd0, 0xb8, 0xef, 0x57, 0xe0, 0x3b, 0x3a, 0x72, + 0x45, 0x6f, 0xbe, 0x3f, 0xfd, 0x36, 0x0d, 0xa7, 0x8a, 0x0c, 0xf3, 0x05, + 0x3b, 0x12, 0xe7, 0x24, 0x76, 0xf4, 0x85, 0x57, 0xde, 0x33, 0xf3, 0x29, + 0xc9, 0x30, 0x83, 0x29, 0x09, 0x4f, 0x53, 0x8d, 0x17, 0x79, 0xfa, 0x82, + 0x62, 0x4a, 0x17, 0x76, 0xa8, 0x1b, 0x0e, 0xad, 0x45, 0x87, 0xe3, 0xa1, + 0x11, 0xe7, 0x02, 0x2a, 0x7a, 0x39, 0xaf, 0x1a, 0x52, 0x62, 0xae, 0xb3, + 0x72, 0x1c, 0xf8, 0xcb, 0x7a, 0x8d, 0x14, 0xaf, 0x2b, 0x35, 0xba, 0x20, + 0x43, 0x85, 0xc0, 0x82, 0xc3, 0x38, 0x41, 0x54, 0x61, 0x3e, 0x64, 0x21, + 0xe1, 0x3b, 0x8f, 0x00, 0xd4, 0xbd, 0xb9, 0x70, 0x08, 0x04, 0x76, 0x98, + 0x8b, 0x83, 0x86, 0x2b, 0xd3, 0xe4, 0x7c, 0xcc, 0x31, 0xe5, 0x3e, 0xa7, + 0x71, 0x6f, 0x9a, 0x56, 0x8b, 0x17, 0x5d, 0x8c, 0x29, 0x3e, 0xa7, 0xe7, + 0xfd, 0xb0, 0x3b, 0xbd, 0x31, 0x3b, 0x6d, 0x18, 0x10, 0x63, 0x38, 0xfe, + 0x3c, 0x64, 0xf8, 0x37, 0x8d, 0x87, 0x74, 0x0c, 0xf0, 0x66, 0x60, 0x13, + 0x2e, 0xd9, 0x82, 0xe4, 0x06, 0x97, 0xba, 0xfd, 0x24, 0x09, 0x66, 0x26, + 0x63, 0x0d, 0xa3, 0x5e, 0xd8, 0xe8, 0x05, 0xc3, 0x61, 0x15, 0x4a, 0x4c, + 0xb1, 0xf7, 0xa9, 0x66, 0x56, 0x0f, 0x5c, 0x52, 0x9a, 0x89, 0x8b, 0xd7, + 0x4e, 0x76, 0x8d, 0x1a, 0x29, 0xee, 0x38, 0x59, 0x71, 0xff, 0xea, 0xae, + 0x53, 0x23, 0x7f, 0x49, 0xe7, 0x09, 0xf2, 0x17, 0x74, 0x1f, 0x16, 0x11, + 0xbc, 0xe4, 0x65, 0xf4, 0xff, 0xa1, 0xc6, 0x66, 0x7a, 0x16, 0x63, 0xb8, + 0x0c, 0x62, 0x45, 0x58, 0x46, 0x86, 0xe2, 0x43, 0x24, 0xfe, 0x7e, 0x14, + 0x7f, 0x71, 0x61, 0x17, 0x74, 0x79, 0x60, 0xcf, 0xd1, 0x1b, 0x0f, 0x8d, + 0xd2, 0x2d, 0x49, 0xab, 0x19, 0x4f, 0x9b, 0xf1, 0xb4, 0x15, 0x61, 0xfb, + 0xa1, 0x66, 0xf1, 0x05, 0xf6, 0x15, 0xe3, 0x55, 0x77, 0xfc, 0x2e, 0xab, + 0x7d, 0x84, 0x6a, 0xca, 0xf7, 0x8b, 0x5e, 0xf3, 0xbf, 0x16, 0xe3, 0x31, + 0x30, 0x5e, 0x44, 0xe7, 0xba, 0xf5, 0x30, 0x15, 0x0e, 0x10, 0xe8, 0xbe, + 0x80, 0xb1, 0x0f, 0xa4, 0x6f, 0x60, 0x00, 0x25, 0xb9, 0xed, 0x2b, 0x92, + 0x6d, 0x50, 0x00, 0x10, 0x61, 0x67, 0xe6, 0xeb, 0x05, 0xcc, 0x45, 0x18, + 0xbc, 0x6a, 0x54, 0xaf, 0xeb, 0x85, 0x47, 0xa4, 0xe9, 0x1a, 0xd7, 0xd1, + 0x07, 0x1d, 0x98, 0xe2, 0x21, 0xa7, 0x52, 0x54, 0x65, 0x28, 0xee, 0xb2, + 0xe1, 0x98, 0xc7, 0x65, 0xc5, 0xcf, 0xf6, 0x0e, 0xfa, 0x91, 0xbd, 0xd4, + 0x30, 0xbe, 0x22, 0x66, 0x2f, 0xe7, 0x62, 0x16, 0x4f, 0xaa, 0x3e, 0xb4, + 0x56, 0xb4, 0xf3, 0xef, 0x74, 0xd2, 0xc1, 0x50, 0x16, 0xd5, 0x8f, 0x26, + 0xc3, 0x0d, 0x91, 0x4b, 0x1f, 0x9c, 0x91, 0x43, 0x95, 0xa9, 0x39, 0x72, + 0xf8, 0xdd, 0x1c, 0x39, 0xa5, 0xe1, 0x21, 0x41, 0xcd, 0x5c, 0x0f, 0xad, + 0x9e, 0x7d, 0x7c, 0xfa, 0xd4, 0x2c, 0x6c, 0x2c, 0x60, 0x26, 0x31, 0xb0, + 0x88, 0xf5, 0xde, 0xbf, 0xbf, 0x93, 0x46, 0xcc, 0xeb, 0x2e, 0x06, 0x16, + 0xa5, 0x10, 0x88, 0xab, 0x4e, 0x97, 0x8d, 0x26, 0x7a, 0x80, 0x43, 0x3f, + 0x09, 0xc7, 0x46, 0x2b, 0x26, 0x60, 0x7a, 0x2a, 0x4f, 0xe0, 0xde, 0x87, + 0xe5, 0x93, 0x16, 0xe1, 0x1e, 0x88, 0xfc, 0x59, 0x78, 0xc4, 0xbb, 0x52, + 0xad, 0xf4, 0xa3, 0x3b, 0xd3, 0x91, 0x24, 0x1c, 0xe2, 0x54, 0x84, 0x6d, + 0xf1, 0x00, 0x41, 0x57, 0x11, 0x82, 0x91, 0x6b, 0x37, 0x4a, 0xc8, 0x5a, + 0x25, 0x0a, 0x59, 0x45, 0xa1, 0x25, 0xa9, 0x56, 0xaf, 0x9b, 0xa9, 0x45, + 0x54, 0x7b, 0x59, 0x92, 0x6a, 0x79, 0xbe, 0x98, 0x43, 0xa4, 0x97, 0x36, + 0x91, 0xf4, 0xf0, 0xea, 0x8e, 0x99, 0xf0, 0xc4, 0x72, 0x19, 0xc2, 0x3e, + 0x84, 0x2b, 0x53, 0x34, 0x36, 0x5f, 0xbe, 0x03, 0x72, 0x4d, 0x02, 0x74, + 0xae, 0x38, 0xc3, 0x38, 0x03, 0x49, 0x38, 0x8a, 0xef, 0x42, 0x4e, 0x39, + 0x28, 0x3f, 0x87, 0x53, 0x49, 0x5f, 0xff, 0x82, 0xcd, 0x24, 0x4f, 0x8e, + 0x82, 0x4f, 0x21, 0x4b, 0xa7, 0x09, 0x9f, 0xfb, 0xe2, 0x7e, 0x54, 0x9a, + 0x05, 0xb3, 0x94, 0xc5, 0x63, 0xc6, 0x95, 0x81, 0xe6, 0xe6, 0x38, 0xc3, + 0xa3, 0xe1, 0x4c, 0xec, 0x8c, 0xb8, 0x2e, 0xcd, 0x50, 0xfb, 0x6f, 0xed, + 0x9f, 0x0f, 0x58, 0xe4, 0x41, 0x14, 0xc1, 0xe5, 0xec, 0x81, 0x17, 0x59, + 0xb1, 0x4c, 0x08, 0xe8, 0x1b, 0x28, 0x3c, 0x73, 0xf2, 0xce, 0x7e, 0x0a, + 0xec, 0x8a, 0xe3, 0x37, 0xd1, 0xac, 0x31, 0xd7, 0xec, 0xc0, 0xfb, 0x11, + 0x65, 0x95, 0x94, 0x05, 0x30, 0xc5, 0x82, 0x21, 0x1b, 0xa3, 0x09, 0x77, + 0x14, 0x60, 0x9f, 0x92, 0x19, 0x48, 0xb1, 0xbc, 0x44, 0x16, 0xcb, 0x09, + 0x88, 0x3d, 0x8d, 0x93, 0xe8, 0x06, 0xd7, 0x73, 0x9e, 0xc7, 0xfb, 0xc9, + 0xba, 0xd3, 0xc1, 0x20, 0x4c, 0x1a, 0xec, 0xe3, 0x34, 0xcd, 0xe8, 0xc1, + 0x17, 0x32, 0x28, 0xf3, 0xba, 0x28, 0xe4, 0x93, 0x9d, 0x79, 0x1c, 0xdf, + 0x37, 0x24, 0x5a, 0xe2, 0xad, 0x3f, 0xf9, 0xc2, 0x50, 0xc1, 0x46, 0x61, + 0x38, 0x84, 0x98, 0xbb, 0xc5, 0x4c, 0x6f, 0x97, 0xb8, 0xce, 0xe7, 0x5c, + 0x42, 0x56, 0xf3, 0x49, 0x7c, 0xe4, 0x64, 0x9d, 0x97, 0x39, 0x9f, 0x11, + 0x37, 0x41, 0x96, 0x5f, 0x5b, 0x2b, 0xae, 0xf2, 0xfb, 0x8a, 0xf0, 0xae, + 0x2e, 0xae, 0xeb, 0x36, 0x28, 0x89, 0xaf, 0xeb, 0xfa, 0x6a, 0x5b, 0x65, + 0x15, 0xa4, 0xcf, 0xfc, 0x43, 0xe1, 0x31, 0x6e, 0x14, 0x3c, 0xe4, 0x28, + 0x65, 0x1c, 0x27, 0x1d, 0x6a, 0x68, 0xfe, 0x99, 0xd7, 0x74, 0xf1, 0x31, + 0x56, 0xac, 0xda, 0x66, 0x63, 0x91, 0x1e, 0x96, 0x08, 0x4e, 0x64, 0xd6, + 0xe9, 0x4e, 0xcb, 0x2f, 0x59, 0xd0, 0xc5, 0x9d, 0xc1, 0x58, 0x47, 0x64, + 0xb3, 0x70, 0xb8, 0xb8, 0x43, 0xa0, 0x00, 0x68, 0xcf, 0x5d, 0x95, 0x8c, + 0xe3, 0x0b, 0x02, 0x80, 0x2a, 0xbf, 0x7f, 0xde, 0x53, 0x3b, 0x59, 0x53, + 0x09, 0xde, 0xc8, 0x67, 0xd5, 0x3d, 0x48, 0x7c, 0x6e, 0x6c, 0xee, 0xf0, + 0x15, 0xa4, 0xf0, 0xed, 0x55, 0x17, 0x0a, 0xa0, 0xc1, 0xf4, 0xc3, 0x98, + 0x85, 0x84, 0x95, 0x78, 0x59, 0x02, 0x8b, 0xee, 0xeb, 0x83, 0x3e, 0xc9, + 0x3e, 0xc8, 0xae, 0x3c, 0x20, 0x40, 0xb1, 0x70, 0x1a, 0xdd, 0xae, 0xd7, + 0x1f, 0x3e, 0xe0, 0xd1, 0x15, 0x26, 0x3a, 0xe3, 0xb2, 0xb3, 0x38, 0xf3, + 0xd0, 0xcc, 0x57, 0x08, 0x13, 0x96, 0xaf, 0x8c, 0xad, 0x10, 0xc6, 0x82, + 0xd2, 0x76, 0x19, 0xca, 0x3a, 0x4d, 0xc8, 0x6b, 0xe2, 0xe7, 0xc2, 0xf1, + 0xc1, 0xa7, 0x9b, 0xbf, 0x0e, 0xc6, 0x4f, 0x9f, 0x4a, 0x8c, 0x0d, 0x82, + 0xfe, 0x85, 0x98, 0xf3, 0x5b, 0x4e, 0xb8, 0x0c, 0xcd, 0x17, 0x0f, 0x2d, + 0xf1, 0xe5, 0x5a, 0x6f, 0x37, 0xb0, 0xf7, 0xcc, 0x3e, 0x28, 0x11, 0x51, + 0xc9, 0x6f, 0x04, 0x96, 0x62, 0x26, 0xac, 0x1a, 0x32, 0x1c, 0x89, 0x6f, + 0x2b, 0x06, 0xdb, 0x3c, 0xd8, 0x6c, 0xf3, 0xf0, 0xf4, 0xa9, 0xe4, 0x19, + 0x6c, 0xe7, 0xfa, 0xe1, 0x83, 0x72, 0xfe, 0xf3, 0x3b, 0xad, 0xcd, 0xe6, + 0x89, 0xfc, 0x80, 0xc1, 0x49, 0x38, 0xf8, 0x0f, 0xf6, 0x8b, 0x61, 0x07, + 0x8c, 0x61, 0x7d, 0x40, 0x89, 0xce, 0xee, 0xc8, 0xa3, 0x3a, 0xc1, 0xd1, + 0x74, 0x57, 0x63, 0x8d, 0x0f, 0x0d, 0x1f, 0x6e, 0x38, 0x73, 0x20, 0x29, + 0x59, 0xc9, 0x84, 0x04, 0x9b, 0xa8, 0xa6, 0x06, 0x4a, 0xd1, 0x88, 0xe5, + 0x34, 0x31, 0x99, 0xca, 0xe8, 0xb0, 0xe0, 0x2b, 0x53, 0x3e, 0xa7, 0x0e, + 0x61, 0x65, 0x4e, 0xa2, 0x40, 0x89, 0xec, 0x82, 0x72, 0x82, 0xc2, 0xd7, + 0xf2, 0xbb, 0x58, 0x3b, 0x8a, 0xd7, 0x0d, 0x87, 0x01, 0x22, 0x87, 0x01, + 0xc4, 0x1c, 0xc0, 0xbc, 0xc2, 0x9e, 0x12, 0x2a, 0xf9, 0x2e, 0x4a, 0xd5, + 0xa4, 0xea, 0x5e, 0xc1, 0x80, 0x8a, 0x5e, 0xfa, 0x8e, 0x21, 0x45, 0x2d, + 0x46, 0xd6, 0xaa, 0x8c, 0xbc, 0xa0, 0xa9, 0x3a, 0x0e, 0x46, 0x8a, 0xc7, + 0x30, 0xe7, 0x0c, 0xbe, 0x1b, 0xb3, 0xb9, 0x4a, 0xf9, 0x4f, 0xe1, 0x88, + 0xbf, 0xda, 0x88, 0xc6, 0xfd, 0xf0, 0xe1, 0x7c, 0x20, 0x00, 0xa0, 0x92, + 0xb1, 0x59, 0xd8, 0xa4, 0xd0, 0x96, 0xcc, 0xf1, 0xac, 0xe4, 0x0a, 0x22, + 0x4c, 0xac, 0xd4, 0x48, 0x21, 0x52, 0xcc, 0x1b, 0xc6, 0x9b, 0x74, 0x56, + 0x47, 0xe8, 0x65, 0x3a, 0x17, 0x22, 0xa5, 0xa2, 0xdf, 0xb3, 0x78, 0xb7, + 0x8e, 0x7c, 0x35, 0x31, 0x0a, 0xe6, 0x77, 0xf8, 0x10, 0xef, 0x0a, 0x45, + 0xba, 0x5c, 0xe3, 0xaf, 0x16, 0x1f, 0xb2, 0x63, 0xec, 0x12, 0xab, 0x1e, + 0x9f, 0x1d, 0x8a, 0x77, 0xa0, 0x37, 0x56, 0x1b, 0x5e, 0x0a, 0x52, 0x39, + 0xff, 0x3e, 0x3a, 0xe3, 0x73, 0xca, 0x94, 0xeb, 0xf2, 0x72, 0x98, 0xb5, + 0xd5, 0xcc, 0xea, 0x75, 0x43, 0x95, 0xc7, 0x8b, 0x55, 0x85, 0xae, 0xa8, + 0xc0, 0x69, 0x56, 0x78, 0x9c, 0x22, 0xd6, 0xa7, 0xec, 0x92, 0x07, 0x4d, + 0x90, 0xd8, 0x5f, 0x1e, 0x0b, 0xe4, 0xfb, 0x7e, 0xe4, 0x45, 0x8c, 0x85, + 0x63, 0x7f, 0x1f, 0x90, 0x09, 0x3e, 0xaa, 0xbd, 0x5f, 0xa0, 0x66, 0x74, + 0xe6, 0xb9, 0x23, 0x6a, 0xda, 0x3d, 0x91, 0xfe, 0xbe, 0xe8, 0x0c, 0x13, + 0xa7, 0x69, 0xd4, 0x1d, 0xce, 0x18, 0x0a, 0xd0, 0x5c, 0x06, 0x46, 0x4d, + 0x6c, 0x37, 0x1c, 0xc6, 0xf7, 0xe4, 0xfd, 0x0f, 0x98, 0x49, 0x5c, 0x3a, + 0x46, 0x9f, 0x0b, 0xfc, 0xf8, 0xaf, 0x5b, 0x7b, 0xad, 0xb7, 0xf0, 0x67, + 0x63, 0x63, 0xf4, 0xcf, 0xf0, 0x14, 0x3e, 0x34, 0x47, 0x15, 0x59, 0x5a, + 0x1f, 0xac, 0x70, 0xaf, 0x5e, 0xc5, 0xee, 0xd3, 0x12, 0xb7, 0x06, 0x13, + 0x6f, 0xfa, 0x00, 0x4d, 0xde, 0x06, 0x77, 0x51, 0x9c, 0xac, 0x38, 0x67, + 0x8c, 0x14, 0x7d, 0x9a, 0xa4, 0x27, 0xb1, 0x75, 0x28, 0xa9, 0x31, 0x29, + 0x0e, 0x3b, 0xa0, 0x05, 0x86, 0x1f, 0x5d, 0x49, 0x08, 0xfe, 0xe5, 0xc6, + 0x78, 0x6f, 0x5e, 0x7b, 0xaa, 0xa2, 0xd9, 0x2c, 0x24, 0x7c, 0xc4, 0xeb, + 0x38, 0xda, 0x18, 0x8c, 0xa4, 0xc0, 0x6c, 0x29, 0xbb, 0x59, 0x4a, 0xdf, + 0x9c, 0x3b, 0xb4, 0x1e, 0x94, 0xc5, 0xa5, 0x04, 0x1f, 0x96, 0xe5, 0xb2, + 0x1e, 0x7b, 0x83, 0x62, 0x3a, 0x0f, 0x6c, 0x0c, 0x2c, 0xd6, 0x29, 0xe2, + 0x2d, 0xc7, 0x72, 0xc1, 0xd9, 0x43, 0x3f, 0x4f, 0x8a, 0x1a, 0x24, 0x6c, + 0x4b, 0x90, 0x37, 0x9e, 0xd0, 0x83, 0x1d, 0x79, 0x37, 0x6e, 0xcf, 0x71, + 0xc4, 0xc0, 0xa6, 0xf0, 0xcd, 0x76, 0x0f, 0x4a, 0xfc, 0x85, 0xf6, 0x82, + 0xc9, 0x4a, 0x32, 0x0c, 0x97, 0x6f, 0x4c, 0x51, 0xaf, 0x98, 0x1a, 0x7c, + 0xe5, 0x38, 0xe8, 0x1c, 0xab, 0x95, 0x43, 0x3d, 0x15, 0xb5, 0x56, 0xfe, + 0x81, 0x28, 0xdf, 0x36, 0x20, 0x9e, 0x83, 0x32, 0x11, 0x15, 0xd7, 0x37, + 0xd5, 0xbc, 0x9c, 0x88, 0xfb, 0x05, 0xea, 0x0d, 0x51, 0x39, 0x37, 0x79, + 0x06, 0x69, 0xb4, 0x64, 0x99, 0x96, 0x9e, 0xc3, 0xac, 0x2e, 0xaa, 0xe4, + 0xa6, 0x72, 0xd3, 0x38, 0x6e, 0x36, 0x15, 0x85, 0xd5, 0x0b, 0x53, 0x6b, + 0xcb, 0xbc, 0x2b, 0x55, 0xd8, 0x27, 0xd7, 0x67, 0xfd, 0x6b, 0xf5, 0xea, + 0xa9, 0xbf, 0x57, 0x2f, 0x8d, 0xa9, 0x69, 0x2f, 0x4e, 0xbe, 0x93, 0xd3, + 0x67, 0xa7, 0xd3, 0x07, 0x46, 0xa7, 0xcb, 0xbd, 0x56, 0x55, 0xd8, 0x6f, + 0x59, 0xfd, 0xab, 0x77, 0xfd, 0xc1, 0xdf, 0x75, 0x5b, 0xd2, 0xb6, 0xba, + 0xfe, 0x60, 0xea, 0x32, 0x8b, 0xba, 0x7e, 0x68, 0x74, 0xbd, 0xe4, 0x1b, + 0x58, 0x85, 0x7d, 0x57, 0xf5, 0xff, 0x82, 0xce, 0x7b, 0xb9, 0xf9, 0xc1, + 0xe0, 0xe6, 0x07, 0x1f, 0x37, 0x8b, 0x47, 0xb4, 0xd6, 0x1e, 0xfb, 0x74, + 0x56, 0x61, 0x57, 0x01, 0xce, 0xbc, 0x5e, 0xe2, 0x53, 0x17, 0xa8, 0x52, + 0xe6, 0x16, 0x2c, 0xd8, 0xfa, 0x8c, 0x0e, 0x2b, 0x4d, 0x8c, 0xea, 0xb5, + 0x56, 0x93, 0x19, 0x57, 0x8d, 0xa0, 0xb6, 0xae, 0xd5, 0xfa, 0xa0, 0xc6, + 0xcf, 0x3c, 0xf9, 0xf2, 0x32, 0xfa, 0x9c, 0x8b, 0x10, 0xb1, 0xb5, 0xe7, + 0xda, 0xec, 0xc9, 0x1b, 0x6f, 0x1a, 0x55, 0x65, 0x21, 0xdf, 0x94, 0xe1, + 0xa5, 0x3d, 0xf3, 0x45, 0x00, 0xc7, 0x06, 0x0d, 0xe0, 0x66, 0xfb, 0xc6, + 0x5b, 0x95, 0x90, 0xea, 0x63, 0x4a, 0x5e, 0xda, 0xc3, 0x91, 0x2b, 0x06, + 0xc3, 0x12, 0xd1, 0x8c, 0xb9, 0x8b, 0xc3, 0xe4, 0x0c, 0xea, 0x3f, 0x0a, + 0x9f, 0x1a, 0x13, 0xba, 0x93, 0x0b, 0x1c, 0x9b, 0x26, 0x63, 0xf5, 0x97, + 0xa2, 0xe0, 0x6b, 0x12, 0x3f, 0xe4, 0x28, 0x3b, 0x05, 0x5b, 0x46, 0xc1, + 0xfd, 0x2e, 0x88, 0x2d, 0x76, 0x76, 0xdb, 0xcc, 0x1e, 0x0e, 0xed, 0xcc, + 0x75, 0x23, 0x13, 0x83, 0x97, 0xf5, 0xe9, 0x25, 0x8b, 0x54, 0x5c, 0x98, + 0xe4, 0x0d, 0xc9, 0x78, 0xa1, 0xec, 0x1f, 0xbc, 0x6a, 0x1e, 0x77, 0xbc, + 0x35, 0x5c, 0x80, 0x7f, 0x47, 0xc6, 0xa7, 0x28, 0xdf, 0x13, 0xb7, 0x4a, + 0x61, 0x9f, 0x72, 0x05, 0xb1, 0x77, 0x45, 0xe7, 0x3b, 0xf5, 0x36, 0xdb, + 0x3c, 0xb6, 0x27, 0x11, 0x52, 0xdd, 0xff, 0x96, 0x0c, 0xaf, 0xc6, 0x1f, + 0x1b, 0x51, 0x8e, 0xa8, 0xee, 0xc9, 0x90, 0x73, 0x80, 0x10, 0x00, 0x66, + 0x4a, 0xe7, 0xaa, 0x84, 0x2e, 0x94, 0xd5, 0x5a, 0x32, 0x55, 0x1c, 0xcc, + 0x3e, 0x2a, 0x3d, 0x1f, 0xea, 0xfc, 0xd9, 0x47, 0x7d, 0x30, 0xb3, 0x5b, + 0x20, 0x51, 0xee, 0x63, 0x4e, 0xb3, 0x6c, 0x78, 0x8e, 0xda, 0x6f, 0x6e, + 0x1b, 0x35, 0xe1, 0x6c, 0xbe, 0x18, 0x35, 0x99, 0xa2, 0x95, 0xe2, 0x5f, + 0x84, 0x87, 0x72, 0x98, 0xcd, 0xd9, 0x34, 0xdc, 0x46, 0x0a, 0x41, 0xbb, + 0x20, 0x95, 0x17, 0x2d, 0xa9, 0x02, 0xc6, 0x31, 0x4b, 0x89, 0x5b, 0x49, + 0x44, 0x75, 0xab, 0xb8, 0x5b, 0x44, 0xc1, 0xb3, 0x7a, 0x45, 0x93, 0x0d, + 0xa4, 0x7c, 0xae, 0xaa, 0x29, 0x31, 0xdf, 0xa0, 0x2c, 0x52, 0x78, 0xf1, + 0x8c, 0x53, 0x93, 0xe8, 0x07, 0x67, 0x12, 0x71, 0x84, 0x68, 0x06, 0xf9, + 0x91, 0x72, 0xb9, 0xbc, 0x1c, 0x7a, 0x9e, 0x5a, 0x45, 0x88, 0x2e, 0x39, + 0x8d, 0x5c, 0xf5, 0x86, 0x39, 0x87, 0xbe, 0xee, 0xd4, 0xf9, 0x42, 0xf6, + 0x2e, 0xe4, 0x4a, 0x87, 0xe9, 0x8a, 0xaa, 0xd9, 0x6c, 0xb4, 0x30, 0xa4, + 0x78, 0x7e, 0xe4, 0xce, 0xb8, 0x35, 0x60, 0xee, 0x38, 0xbd, 0x8e, 0x87, + 0x7d, 0x3b, 0x7d, 0x83, 0xd2, 0xdf, 0xc1, 0x39, 0x37, 0x41, 0xee, 0x76, + 0x72, 0x37, 0x79, 0x2d, 0xc8, 0xf9, 0xc4, 0xaa, 0x68, 0x20, 0x0b, 0x92, + 0x14, 0xaf, 0xbd, 0x21, 0x1c, 0xa7, 0x81, 0x67, 0x54, 0xf4, 0x78, 0x4c, + 0x67, 0x55, 0x3b, 0x6b, 0x5b, 0x66, 0x45, 0x78, 0xd8, 0x85, 0x83, 0x63, + 0xd4, 0x08, 0x1b, 0x35, 0x76, 0x1b, 0xf5, 0xfb, 0xe1, 0x98, 0x55, 0xdf, + 0x5f, 0xad, 0x37, 0x9b, 0xab, 0x2e, 0xaf, 0xb4, 0xad, 0x4e, 0x8d, 0xc3, + 0x08, 0x4e, 0xc7, 0x09, 0xeb, 0x42, 0xc3, 0x78, 0xd8, 0x60, 0x83, 0x20, + 0x1a, 0xbb, 0x7d, 0x6c, 0x8b, 0xde, 0x9c, 0xc5, 0x19, 0x9b, 0x16, 0xf4, + 0xa8, 0x2d, 0xfa, 0xd4, 0xc9, 0xc2, 0xa0, 0x0f, 0x9b, 0x09, 0xde, 0xb9, + 0xef, 0x62, 0xff, 0xa2, 0xf1, 0x4d, 0x0e, 0x1c, 0xef, 0x13, 0x17, 0x82, + 0x80, 0x61, 0xa9, 0x70, 0xc4, 0x7b, 0x98, 0x2b, 0xcb, 0x3b, 0xf9, 0xde, + 0xee, 0x22, 0x56, 0x98, 0xd7, 0xcd, 0x75, 0x35, 0xeb, 0x32, 0x5c, 0xa4, + 0x43, 0xf4, 0x2a, 0x1d, 0xf7, 0xf9, 0xe3, 0xe0, 0x38, 0x89, 0x5e, 0x0f, + 0x41, 0x46, 0x74, 0xab, 0xb4, 0xe6, 0x56, 0xb9, 0x74, 0x7b, 0xbc, 0xae, + 0x26, 0x9e, 0xbf, 0xc2, 0xf7, 0x68, 0x7c, 0x72, 0xab, 0xac, 0xcf, 0xad, + 0xf2, 0x73, 0x38, 0x1c, 0xa2, 0x1d, 0xca, 0xae, 0xb3, 0xb1, 0xa0, 0x2b, + 0xd3, 0xd0, 0xad, 0xb1, 0x39, 0xb7, 0xc6, 0x69, 0x70, 0x83, 0xa1, 0x13, + 0xdc, 0x4a, 0x5b, 0x73, 0x2b, 0x1d, 0xcc, 0x82, 0x5c, 0x67, 0x9e, 0xcd, + 0xad, 0xf1, 0x23, 0x3a, 0xf4, 0xb8, 0x55, 0x76, 0xe6, 0x56, 0x91, 0xf2, + 0x6f, 0x55, 0xda, 0xf1, 0x56, 0xdd, 0x49, 0xa5, 0x87, 0x15, 0xaf, 0x0e, + 0x97, 0x18, 0xd6, 0x0d, 0x63, 0x58, 0x7d, 0x55, 0x72, 0xc3, 0xba, 0x61, + 0x0c, 0xab, 0xaf, 0x82, 0x67, 0x58, 0x37, 0x8c, 0x61, 0xf5, 0x55, 0xf1, + 0x0d, 0xeb, 0x86, 0x31, 0xac, 0xfe, 0xae, 0xb8, 0xc3, 0xba, 0x61, 0x0c, + 0xab, 0xaf, 0x86, 0x77, 0x58, 0x37, 0x8c, 0x61, 0xf5, 0x55, 0xca, 0x0f, + 0xeb, 0x86, 0x31, 0xac, 0xbe, 0x1a, 0x9e, 0x61, 0xdd, 0x30, 0x86, 0xd5, + 0x57, 0xc5, 0x37, 0xac, 0x1c, 0xc0, 0xf1, 0x80, 0xb5, 0xb6, 0xea, 0xbc, + 0x60, 0x3a, 0x9d, 0xd0, 0xd3, 0x04, 0x18, 0x79, 0x23, 0x1e, 0x4d, 0x40, + 0xba, 0xe8, 0xd7, 0x48, 0x75, 0x37, 0x88, 0x91, 0x7c, 0x18, 0x00, 0x84, + 0xbc, 0x7a, 0x1a, 0x8c, 0xed, 0xa7, 0xe9, 0x74, 0x14, 0xae, 0x08, 0xfb, + 0x66, 0x90, 0x71, 0x8d, 0x5b, 0x25, 0x45, 0x53, 0x30, 0xbf, 0x01, 0xcf, + 0xd0, 0x4e, 0x8c, 0xea, 0xa0, 0x34, 0xe6, 0x25, 0x10, 0xd0, 0x71, 0xe7, + 0x5c, 0x20, 0x45, 0xef, 0x71, 0x61, 0x19, 0x09, 0x03, 0x5a, 0x89, 0x92, + 0x34, 0x83, 0xd5, 0x26, 0x1e, 0x60, 0xb8, 0x0f, 0xa8, 0x19, 0x23, 0x6e, + 0xd0, 0xd8, 0xd5, 0x2d, 0xac, 0x32, 0x58, 0x22, 0x88, 0xb8, 0x4b, 0x0d, + 0x81, 0xe0, 0x2d, 0x40, 0x32, 0x87, 0xd0, 0xa5, 0x0b, 0xc6, 0x0c, 0x97, + 0x30, 0xd4, 0x29, 0x61, 0x65, 0xab, 0x45, 0x7e, 0x25, 0x5f, 0x51, 0x6c, + 0x67, 0xf9, 0xf5, 0x69, 0x67, 0xd9, 0xf5, 0x69, 0x67, 0xf9, 0xf5, 0x69, + 0xe7, 0x11, 0xeb, 0xd3, 0xce, 0xd2, 0xeb, 0xd3, 0xce, 0x63, 0xd6, 0xa7, + 0x9d, 0xa5, 0xd7, 0xa7, 0x9d, 0xe5, 0xd7, 0xa7, 0x16, 0x0c, 0xcb, 0xd2, + 0x2b, 0x0c, 0x56, 0x5a, 0x72, 0x8d, 0xc1, 0x2a, 0x4b, 0xaf, 0x32, 0x58, + 0x69, 0xf9, 0x75, 0x06, 0x6b, 0x2d, 0xbb, 0xd2, 0x60, 0x9d, 0x47, 0xac, + 0x35, 0x58, 0x6d, 0xd9, 0xd5, 0x06, 0xeb, 0x94, 0x5a, 0x6f, 0xd4, 0x7a, + 0xc1, 0xe7, 0xa0, 0xb1, 0x48, 0x30, 0x90, 0x56, 0x6f, 0x69, 0xb6, 0xe5, + 0x96, 0x12, 0xf1, 0xc4, 0x08, 0xac, 0x23, 0x51, 0xc6, 0x01, 0x88, 0x9c, + 0xd4, 0x5e, 0x58, 0x6a, 0x0c, 0x3d, 0xa2, 0x59, 0xf2, 0x70, 0x97, 0xed, + 0xce, 0x61, 0x08, 0x83, 0x8b, 0xf0, 0x32, 0x9f, 0x07, 0x5b, 0x59, 0x59, + 0xac, 0x78, 0x06, 0xda, 0xdb, 0xdb, 0x75, 0x06, 0x45, 0xda, 0x9b, 0x4b, + 0x2f, 0x77, 0xce, 0x0e, 0xba, 0x8d, 0x87, 0xa7, 0x4d, 0xc6, 0x75, 0x4a, + 0x73, 0xd8, 0x1b, 0x41, 0xa5, 0xf4, 0xb8, 0xa6, 0x06, 0xe0, 0x2e, 0xdb, + 0x3e, 0x58, 0xbe, 0x31, 0xf0, 0xc3, 0xf2, 0xda, 0x13, 0xcd, 0x77, 0x6c, + 0x8a, 0xce, 0x17, 0x00, 0xe3, 0x7c, 0x92, 0x45, 0x23, 0xf4, 0xda, 0x81, + 0xb5, 0x36, 0xc2, 0x50, 0x97, 0x18, 0xbc, 0xab, 0xd9, 0xf0, 0xaa, 0xa3, + 0xe8, 0xde, 0x0b, 0xda, 0xf9, 0xb5, 0xee, 0xea, 0x85, 0xe9, 0x52, 0xcf, + 0x55, 0x39, 0x53, 0x6a, 0x58, 0x9e, 0x54, 0x95, 0xcd, 0x15, 0x0b, 0x68, + 0x2f, 0xd3, 0xcf, 0xd2, 0x06, 0xab, 0x95, 0x5a, 0xa2, 0x15, 0xd3, 0xe8, + 0x2a, 0x3e, 0x0f, 0x86, 0x01, 0xf9, 0xa3, 0x5a, 0xf0, 0x5f, 0xbe, 0x64, + 0xad, 0x6d, 0x59, 0x00, 0x3d, 0x84, 0xab, 0x6e, 0xf6, 0xce, 0x2a, 0xfb, + 0x96, 0x35, 0x1f, 0x5a, 0x83, 0x81, 0x28, 0xd6, 0xbd, 0x71, 0x81, 0xd8, + 0xf9, 0x13, 0xd7, 0xc8, 0x3b, 0xb4, 0x8c, 0xbb, 0x13, 0xad, 0x7f, 0x8b, + 0x3e, 0x08, 0xb7, 0x12, 0xa4, 0x11, 0x2a, 0xb7, 0xd6, 0xe9, 0xb2, 0xc1, + 0x04, 0x2f, 0xf1, 0xac, 0x1b, 0x97, 0x78, 0x80, 0xc0, 0x80, 0x1b, 0x1f, + 0xbe, 0x6d, 0xa9, 0xab, 0x40, 0x2c, 0x26, 0xac, 0x0e, 0x75, 0x84, 0x03, + 0x8b, 0x56, 0x95, 0x11, 0xac, 0x0d, 0x0d, 0x6b, 0xc3, 0x86, 0xd5, 0x75, + 0x61, 0x75, 0x25, 0xac, 0x8d, 0x02, 0x58, 0x3b, 0x1a, 0xd6, 0x4e, 0x01, + 0x5e, 0xad, 0x2d, 0x91, 0x38, 0x21, 0xff, 0x97, 0x3d, 0x17, 0xcd, 0x9d, + 0x02, 0xd0, 0xad, 0xa6, 0x86, 0xdd, 0x6a, 0x16, 0x20, 0x5a, 0x00, 0x5c, + 0xe1, 0x0d, 0x40, 0x3c, 0xd0, 0x2d, 0xae, 0x12, 0x97, 0xec, 0x68, 0x1e, + 0x4b, 0xdc, 0x4c, 0x86, 0x10, 0x1c, 0xc6, 0x19, 0xc2, 0xc2, 0xbe, 0xea, + 0xe6, 0x6b, 0x8e, 0xb0, 0x10, 0xb1, 0x8a, 0x39, 0x05, 0x90, 0x52, 0xa2, + 0xb5, 0xe6, 0x9e, 0x45, 0xbd, 0x17, 0xb9, 0x82, 0x5d, 0x27, 0x31, 0xd7, + 0xa7, 0x96, 0x4d, 0x24, 0x3c, 0xea, 0xa1, 0x47, 0xb4, 0xd5, 0xab, 0x3f, + 0x5e, 0x48, 0xb5, 0x56, 0xae, 0xfa, 0x86, 0x55, 0x5d, 0x1f, 0x00, 0xbd, + 0x40, 0xda, 0x05, 0x40, 0x36, 0x6d, 0x1c, 0xf0, 0x64, 0xe8, 0x56, 0xdd, + 0x28, 0xa8, 0x6a, 0x8f, 0xb1, 0x38, 0x27, 0xd2, 0x0a, 0x3c, 0x11, 0x27, + 0x48, 0x9d, 0x8b, 0xb6, 0x5b, 0xda, 0x10, 0xac, 0x30, 0x94, 0xd7, 0xeb, + 0xad, 0x11, 0x9a, 0x6f, 0xdb, 0xa3, 0x5b, 0xdc, 0x22, 0xe1, 0xe3, 0xb3, + 0xd1, 0x7d, 0x9c, 0x0c, 0xfb, 0xf0, 0xa9, 0xfd, 0x6c, 0x74, 0x1b, 0xc1, + 0xdf, 0x51, 0xc5, 0xc5, 0x67, 0xbb, 0x00, 0x9f, 0x6d, 0x17, 0x1f, 0x7e, + 0x36, 0xcd, 0x91, 0x73, 0xab, 0xa0, 0x7e, 0xbb, 0x6d, 0x01, 0xa0, 0x93, + 0x32, 0x8c, 0x89, 0x55, 0xff, 0xdb, 0x17, 0xec, 0xcf, 0xa2, 0xf1, 0x68, + 0x6f, 0xe4, 0xea, 0xeb, 0x41, 0xc9, 0x41, 0x29, 0x1a, 0x90, 0xf6, 0x66, + 0x1e, 0x8b, 0xdc, 0xa8, 0x20, 0x80, 0xa2, 0x61, 0x69, 0x3f, 0xcb, 0x01, + 0x10, 0x63, 0x93, 0x03, 0x51, 0x44, 0xc9, 0xf6, 0xb6, 0x0f, 0x84, 0x87, + 0x9c, 0x44, 0x8e, 0x22, 0x7a, 0xae, 0xef, 0x58, 0x50, 0xb8, 0x19, 0x78, + 0x70, 0xb3, 0xd4, 0x94, 0xcc, 0x33, 0xbd, 0x0f, 0x68, 0xf7, 0xa6, 0xdc, + 0xfc, 0xcd, 0xa3, 0xb8, 0xed, 0x5f, 0x04, 0x41, 0x1c, 0x10, 0xa9, 0x7a, + 0xdb, 0xbb, 0x8e, 0x50, 0xc5, 0xfc, 0x21, 0x1f, 0xf1, 0x8d, 0x1c, 0x05, + 0xdb, 0x7b, 0xea, 0x3b, 0xf5, 0x6c, 0x14, 0x64, 0xbd, 0x5b, 0xba, 0xfc, + 0x52, 0x55, 0x19, 0x4c, 0xef, 0x17, 0x84, 0xd7, 0x60, 0x50, 0xf3, 0xe4, + 0xf1, 0x56, 0xe6, 0xe6, 0xb7, 0x65, 0xbe, 0xe3, 0xbd, 0x8c, 0x2d, 0x03, + 0x76, 0x75, 0x58, 0x58, 0xf2, 0x2b, 0x92, 0x8b, 0xa8, 0x49, 0x8c, 0x5c, + 0x07, 0x37, 0xe7, 0x75, 0xd0, 0xda, 0xf9, 0x04, 0x26, 0x4e, 0xf7, 0x27, + 0xb6, 0x12, 0x3b, 0x3f, 0x8c, 0xdb, 0xfe, 0x0d, 0xe2, 0x8b, 0x08, 0xdf, + 0xfd, 0x7f, 0x46, 0xf8, 0xae, 0x26, 0xbc, 0xbb, 0xea, 0xff, 0xe7, 0x08, + 0xdf, 0x2d, 0x43, 0x78, 0xd8, 0x61, 0xbd, 0xb3, 0x72, 0xad, 0xbb, 0xdc, + 0xc4, 0x2c, 0x3b, 0xd7, 0x7e, 0xb7, 0xb5, 0xc2, 0x56, 0x20, 0x4a, 0x10, + 0x2d, 0xc9, 0x63, 0x8f, 0xa4, 0xd2, 0x5d, 0xf6, 0x5f, 0x7d, 0x0a, 0xc5, + 0x6a, 0xfa, 0xf1, 0x2a, 0xdb, 0x9f, 0x16, 0x23, 0xab, 0x7c, 0xe5, 0x79, + 0xfe, 0x1c, 0xb6, 0xf7, 0x55, 0xf6, 0x07, 0x31, 0x3d, 0x7c, 0xd9, 0xc1, + 0xcf, 0xdd, 0x1b, 0xd7, 0x18, 0xb8, 0xe0, 0x9d, 0xc5, 0xbc, 0xee, 0xd7, + 0x2a, 0xd6, 0xa0, 0xb7, 0x4c, 0x48, 0x45, 0xf2, 0xeb, 0xaf, 0xe7, 0x3f, + 0x60, 0xa8, 0xf5, 0x28, 0xe5, 0x95, 0x10, 0x7e, 0x93, 0x8d, 0x2d, 0x08, + 0xfc, 0x90, 0x25, 0x5a, 0x70, 0x2d, 0xca, 0xd5, 0x83, 0x8b, 0xcb, 0x55, + 0xcb, 0xae, 0x2c, 0x9a, 0x17, 0x2d, 0x98, 0x80, 0x13, 0x90, 0xfc, 0x7b, + 0xec, 0xd2, 0xb2, 0x6c, 0x88, 0xa6, 0x0a, 0x7b, 0x53, 0xc3, 0xe8, 0xc2, + 0xf5, 0x74, 0x12, 0xf6, 0xa2, 0x41, 0xd4, 0x73, 0xfa, 0xb6, 0x24, 0x66, + 0xa8, 0xf2, 0x46, 0x77, 0x16, 0x01, 0xe2, 0x95, 0x44, 0x88, 0x55, 0x03, + 0xd2, 0xf0, 0xa4, 0x3c, 0xaa, 0x11, 0x1c, 0x91, 0xfe, 0x1d, 0x26, 0x71, + 0x4e, 0xf3, 0xbe, 0x69, 0xb6, 0x76, 0x91, 0xf0, 0x17, 0x1a, 0x53, 0x8e, + 0x31, 0x87, 0x0c, 0x20, 0xf1, 0x08, 0x87, 0xc3, 0x53, 0x4d, 0x50, 0x31, + 0xad, 0x61, 0x00, 0x66, 0xb2, 0x40, 0x8b, 0x17, 0xc0, 0xed, 0xc7, 0x29, + 0x64, 0xa9, 0xb6, 0x45, 0x43, 0xef, 0x0e, 0x7f, 0xc8, 0x35, 0xd2, 0x96, + 0x8d, 0x4c, 0xc7, 0xc3, 0xb8, 0xf7, 0x29, 0xec, 0xaf, 0xe6, 0x9a, 0x69, + 0xcb, 0x66, 0x44, 0x01, 0xb7, 0x0d, 0x8b, 0x74, 0x32, 0x1c, 0xa3, 0x6e, + 0x48, 0x0f, 0xda, 0x2b, 0xae, 0x40, 0xdf, 0x63, 0x08, 0x10, 0x7e, 0x37, + 0xe5, 0x6f, 0x04, 0x7e, 0x06, 0xb5, 0x6f, 0xd9, 0xfe, 0x28, 0x4c, 0xa2, + 0x5e, 0x30, 0x96, 0x8d, 0x5c, 0xc1, 0xf9, 0x6d, 0x18, 0x80, 0x64, 0x94, + 0xdd, 0xc7, 0x7c, 0x62, 0xf3, 0x67, 0x44, 0xe8, 0x80, 0x89, 0x07, 0xbc, + 0xf7, 0x57, 0x1b, 0x28, 0x56, 0xb3, 0xe9, 0xa4, 0x46, 0x82, 0x55, 0x3f, + 0x04, 0x62, 0x84, 0x78, 0x59, 0xb6, 0x2e, 0xf4, 0x5b, 0x84, 0x0d, 0x51, + 0x87, 0x0a, 0x9c, 0xfc, 0xd0, 0x6c, 0x51, 0x38, 0x5d, 0x6e, 0x73, 0x72, + 0x8f, 0xa9, 0x9b, 0x42, 0x53, 0x21, 0xba, 0x23, 0x1e, 0x06, 0xf0, 0xf7, + 0x86, 0xca, 0x8e, 0x99, 0x2a, 0x14, 0xdc, 0x05, 0xd1, 0x30, 0xe0, 0xca, + 0xfe, 0x81, 0x3a, 0x1b, 0xd7, 0xa3, 0x71, 0x0d, 0x88, 0x69, 0x57, 0xe4, + 0x9d, 0x3e, 0x8b, 0x65, 0x5d, 0xaa, 0x01, 0x98, 0x7b, 0xcf, 0xa6, 0xe6, + 0x13, 0xa1, 0x45, 0x27, 0x53, 0x37, 0x18, 0x8e, 0xba, 0x76, 0x5a, 0x64, + 0x11, 0x13, 0x46, 0xa9, 0x4d, 0x2b, 0xa8, 0xa9, 0xe8, 0x66, 0x42, 0x9d, + 0x57, 0x19, 0xdc, 0xaf, 0x4b, 0xc5, 0xe3, 0xbd, 0x6e, 0x8e, 0xcd, 0x8b, + 0x52, 0x56, 0xbc, 0x32, 0x82, 0xb9, 0x65, 0xc1, 0x14, 0x77, 0x78, 0x26, + 0x62, 0x32, 0x15, 0x42, 0x35, 0xe3, 0x0c, 0x3f, 0x65, 0xda, 0xbf, 0xd0, + 0x0a, 0xb3, 0xed, 0x06, 0xe9, 0x7e, 0xaa, 0x1c, 0x59, 0xf2, 0x05, 0x2f, + 0x0b, 0xb0, 0x74, 0x6e, 0x65, 0x19, 0x44, 0x73, 0x1f, 0x33, 0x03, 0xec, + 0xf1, 0xf5, 0x51, 0xf4, 0xc7, 0x57, 0x31, 0x99, 0xc7, 0x78, 0x13, 0x27, + 0x1c, 0xa1, 0xca, 0x44, 0x14, 0x31, 0x62, 0x33, 0x07, 0xe3, 0x99, 0x50, + 0xa0, 0x02, 0xf0, 0xf0, 0xa1, 0x17, 0x4e, 0x32, 0xf6, 0x6a, 0xab, 0xc6, + 0xb6, 0x38, 0x73, 0x6e, 0x96, 0x1a, 0x92, 0xc7, 0x91, 0xef, 0xd5, 0x7f, + 0x8c, 0x7e, 0xd2, 0x1a, 0x6a, 0xb3, 0xce, 0x38, 0xc6, 0x17, 0x5b, 0x55, + 0x00, 0x50, 0x91, 0x9a, 0xc3, 0xb2, 0xd5, 0x5a, 0xc0, 0x3c, 0x6d, 0x1b, + 0x6c, 0x3f, 0x46, 0x82, 0x0b, 0x8d, 0xd3, 0x14, 0x1f, 0xdd, 0xef, 0x8b, + 0xb7, 0x02, 0x60, 0x8a, 0xa7, 0x73, 0x9b, 0x6a, 0x2f, 0x6c, 0x6a, 0xcb, + 0xe9, 0x01, 0xae, 0x40, 0x81, 0x58, 0x81, 0x10, 0x3e, 0xad, 0x1d, 0xf3, + 0xdb, 0x78, 0xb6, 0xd7, 0xda, 0x6b, 0xee, 0x2d, 0x9a, 0x11, 0x9b, 0xeb, + 0x2e, 0xad, 0xfa, 0x61, 0x8f, 0x0d, 0xf9, 0xdc, 0x5f, 0x1b, 0xe1, 0x2b, + 0xec, 0x73, 0x9b, 0xd9, 0x2c, 0x6c, 0x80, 0x0b, 0x01, 0x86, 0x93, 0xe5, + 0x7e, 0xbf, 0x4f, 0x8c, 0x92, 0xba, 0xae, 0x96, 0xff, 0x8d, 0x9f, 0xe5, + 0xdb, 0x23, 0x29, 0xab, 0xbe, 0x46, 0x1f, 0xdd, 0x55, 0x6d, 0x52, 0xf6, + 0x3c, 0xc4, 0x71, 0x7c, 0xf0, 0xb6, 0xc8, 0x93, 0x9b, 0x1e, 0x0c, 0xc1, + 0x28, 0x18, 0x0b, 0x7d, 0xd5, 0x6a, 0xdc, 0x99, 0xeb, 0xa3, 0xba, 0x5c, + 0xbc, 0xa4, 0x07, 0xdb, 0x8a, 0xe5, 0x55, 0x65, 0x7b, 0x1c, 0x63, 0x4d, + 0xe5, 0xe3, 0x41, 0x77, 0x6d, 0xca, 0xdf, 0xe2, 0x10, 0x6e, 0x20, 0xd4, + 0x52, 0xbd, 0x8e, 0x9a, 0x99, 0x8f, 0xd6, 0x6d, 0x1c, 0x2b, 0x80, 0x04, + 0xdd, 0x1b, 0x01, 0x34, 0x3e, 0x48, 0x77, 0xe4, 0x8f, 0x4f, 0x9f, 0x92, + 0xbb, 0xb3, 0xba, 0x1e, 0xec, 0x96, 0x53, 0x57, 0x27, 0x5d, 0x6f, 0x90, + 0x23, 0xc3, 0x9b, 0xee, 0x2c, 0x7c, 0xc8, 0xb8, 0x07, 0x46, 0xa1, 0xc7, + 0xe0, 0x99, 0xf0, 0xca, 0x48, 0xf1, 0x0a, 0x81, 0xd8, 0xb6, 0xd1, 0xcd, + 0x94, 0xbd, 0x2a, 0x76, 0xae, 0x43, 0xb0, 0xf3, 0xdc, 0x24, 0xfe, 0x0f, + 0xf8, 0x8f, 0xb2, 0x39, 0x4e, 0x87, 0x6f, 0x4c, 0x7f, 0x43, 0xf5, 0xf2, + 0x7d, 0x39, 0x32, 0x25, 0x21, 0xde, 0x1b, 0x97, 0xde, 0xc5, 0xf3, 0x88, + 0xa4, 0x20, 0xff, 0x55, 0x94, 0x2a, 0xeb, 0x3f, 0x3c, 0x8f, 0x14, 0xdf, + 0x1b, 0xa4, 0x30, 0x9c, 0x3f, 0xba, 0x29, 0x88, 0xa1, 0x20, 0xe6, 0xb0, + 0x6b, 0x9f, 0x07, 0x26, 0xce, 0x37, 0xee, 0x83, 0xf9, 0x76, 0x7f, 0x9e, + 0x0f, 0x26, 0x02, 0x54, 0xa0, 0xfe, 0x02, 0x97, 0x53, 0x51, 0x43, 0xdf, + 0x79, 0xd4, 0xfd, 0x3a, 0xb1, 0x17, 0x23, 0xf2, 0x83, 0xf1, 0xac, 0x3f, + 0x27, 0xf3, 0x96, 0x1f, 0xee, 0x29, 0x58, 0x76, 0xf9, 0x79, 0xcc, 0xd2, + 0x33, 0x77, 0xe5, 0x59, 0x59, 0xe2, 0x42, 0x43, 0xbe, 0xa0, 0xef, 0x02, + 0xc3, 0x5e, 0x7e, 0x59, 0x32, 0x24, 0x91, 0xdc, 0x13, 0x35, 0xfc, 0x52, + 0xc7, 0x75, 0xeb, 0x64, 0xfe, 0xb5, 0x8e, 0xfa, 0x32, 0xb7, 0x3a, 0x88, + 0x56, 0xf3, 0x6f, 0x71, 0xe4, 0x2b, 0x7d, 0xb4, 0x82, 0xb4, 0xac, 0x79, + 0x2f, 0x5f, 0xf8, 0x2f, 0x55, 0xcc, 0xe6, 0xe4, 0x39, 0x17, 0x2e, 0x6c, + 0xfe, 0x39, 0xc5, 0xcf, 0xf2, 0x2d, 0xa9, 0x42, 0xfe, 0x39, 0x2c, 0xe0, + 0x1f, 0x1e, 0x81, 0xee, 0xff, 0xab, 0xf8, 0xe7, 0x91, 0xbc, 0xb3, 0xe0, + 0x4a, 0xd0, 0x52, 0xbc, 0x23, 0x2e, 0xe1, 0x2c, 0xcb, 0x3d, 0x44, 0xde, + 0xff, 0x34, 0xff, 0x5c, 0xd8, 0xfc, 0x33, 0x4f, 0x08, 0x3a, 0x2c, 0x12, + 0x82, 0xc4, 0xcb, 0x61, 0xcb, 0x08, 0x41, 0x7f, 0x8d, 0x04, 0xf4, 0x58, + 0x99, 0x67, 0x81, 0x88, 0x23, 0xdd, 0x1a, 0x5b, 0x45, 0x12, 0x8e, 0x11, + 0x1e, 0xc5, 0x15, 0x72, 0x7e, 0xa2, 0x3b, 0x47, 0xe4, 0xce, 0xb9, 0x80, + 0xbc, 0x47, 0x45, 0xe4, 0xa5, 0xae, 0xfc, 0xff, 0xa2, 0x88, 0x79, 0x0d, + 0xb2, 0xa5, 0x79, 0x23, 0xd6, 0xf6, 0x02, 0xfd, 0xd5, 0xf4, 0x02, 0x55, + 0x1a, 0x2a, 0xb9, 0x8d, 0x73, 0x2d, 0xc3, 0x7c, 0xa9, 0xe0, 0xed, 0x45, + 0x91, 0x54, 0x80, 0x6f, 0xe1, 0xc7, 0xe9, 0x7f, 0x4c, 0x24, 0xf8, 0x1a, + 0xb7, 0x70, 0x5a, 0x1b, 0x2d, 0xb6, 0xd5, 0x62, 0x01, 0x9c, 0x7c, 0xde, + 0x5e, 0x5c, 0x32, 0x52, 0xfa, 0xbc, 0x8d, 0x93, 0xe8, 0xdf, 0x31, 0xbe, + 0xb1, 0xa4, 0x09, 0x74, 0x19, 0x0e, 0x03, 0x32, 0xb8, 0xb9, 0x32, 0xe2, + 0x81, 0x5f, 0x46, 0x7c, 0x2b, 0x6b, 0xca, 0x8a, 0x7f, 0x05, 0x35, 0xfe, + 0x92, 0x0b, 0x49, 0x3d, 0x7c, 0x3e, 0x77, 0xdc, 0x97, 0x7a, 0x50, 0xd3, + 0x51, 0xf8, 0x22, 0x89, 0x46, 0x41, 0x32, 0x63, 0x87, 0xfb, 0x79, 0x7f, + 0x61, 0x10, 0x30, 0xe3, 0x51, 0x94, 0x65, 0x70, 0xb2, 0xae, 0xbf, 0x64, + 0xe2, 0x5d, 0x4c, 0xad, 0x7c, 0x4e, 0xb9, 0xa3, 0x49, 0x26, 0x29, 0x45, + 0xaa, 0x39, 0x09, 0x83, 0x6b, 0x40, 0xf0, 0x49, 0xc1, 0x10, 0x23, 0xe6, + 0x50, 0xa8, 0x16, 0x1e, 0xba, 0xa9, 0x27, 0x49, 0x7b, 0x7c, 0xa8, 0x5c, + 0xdc, 0xd0, 0x47, 0x0d, 0x5f, 0x74, 0x55, 0x28, 0x40, 0x7b, 0x52, 0xa1, + 0xb9, 0xc7, 0xda, 0xd8, 0x81, 0xea, 0xaf, 0xbf, 0xbe, 0xbf, 0x42, 0x7b, + 0x39, 0x79, 0xc8, 0xec, 0xf7, 0xef, 0x30, 0x46, 0x62, 0x9f, 0xbd, 0x8f, + 0xfa, 0x61, 0x4c, 0x1e, 0x18, 0xf1, 0xb8, 0x52, 0x59, 0xf5, 0xd6, 0x6f, + 0x1a, 0xf5, 0x5b, 0xbc, 0xfe, 0x99, 0xac, 0x93, 0xfa, 0x2a, 0x6d, 0x19, + 0x15, 0xda, 0xfe, 0x02, 0x4d, 0x80, 0xcb, 0x71, 0xdb, 0x83, 0x6f, 0x7b, + 0x6c, 0x1b, 0xfe, 0xed, 0x50, 0xda, 0x26, 0xa9, 0x7d, 0x79, 0xf5, 0x76, + 0xbb, 0xa9, 0xaa, 0xa3, 0xde, 0x92, 0x7a, 0x50, 0xa7, 0x50, 0x6f, 0x9a, + 0x42, 0x86, 0x0e, 0xb3, 0x1f, 0x93, 0xdd, 0x70, 0x14, 0x06, 0x63, 0x54, + 0x1c, 0xc1, 0xc0, 0xc2, 0x29, 0xa7, 0x3b, 0x53, 0x8e, 0x7d, 0xa3, 0x34, + 0x1c, 0xde, 0xc1, 0x3e, 0xc9, 0x18, 0xc1, 0xb6, 0xab, 0xc2, 0x26, 0x1b, + 0x0e, 0x87, 0x58, 0x03, 0x09, 0x7d, 0x1b, 0xa3, 0xf1, 0x18, 0xbd, 0x05, + 0x07, 0x61, 0x20, 0x14, 0x9f, 0xf8, 0x32, 0x3a, 0xf7, 0x16, 0x92, 0x83, + 0xa6, 0x7c, 0x88, 0x5c, 0x57, 0x21, 0xec, 0x6b, 0x6b, 0xbd, 0x5d, 0xe7, + 0xcb, 0x46, 0xea, 0x73, 0xd2, 0x17, 0x4a, 0x6a, 0x9f, 0xd2, 0x5c, 0xfb, + 0xef, 0xd3, 0x72, 0xe8, 0xf3, 0xf4, 0xa6, 0x47, 0x1e, 0x4d, 0xc5, 0x8d, + 0xeb, 0xf0, 0x46, 0x4e, 0xda, 0xf4, 0x50, 0x02, 0xa0, 0x99, 0x84, 0x93, + 0x61, 0xd0, 0xa3, 0xb0, 0x4c, 0x14, 0x69, 0x93, 0xaf, 0x75, 0x18, 0xb4, + 0xd3, 0xaf, 0x47, 0xbf, 0x02, 0xc1, 0x66, 0x1c, 0xf5, 0xa0, 0xa6, 0x2a, + 0x9d, 0xeb, 0x03, 0xef, 0x05, 0xbe, 0xb3, 0xce, 0xed, 0x68, 0x35, 0x16, + 0x36, 0x6e, 0x1a, 0xf8, 0xc6, 0xe8, 0x66, 0x7b, 0xd3, 0x2d, 0xbc, 0xa3, + 0x0b, 0xa3, 0xa7, 0x80, 0x54, 0xd4, 0xb0, 0x2a, 0xf7, 0xe1, 0x3e, 0x3c, + 0x3a, 0x50, 0x3a, 0x5f, 0xd4, 0x0f, 0xea, 0x6b, 0x4a, 0x2f, 0x69, 0x02, + 0x72, 0x68, 0x45, 0x93, 0xb0, 0x43, 0xee, 0x48, 0xcb, 0x4d, 0x43, 0x73, + 0x14, 0x2b, 0x29, 0x83, 0x69, 0x30, 0xce, 0xd0, 0x88, 0x41, 0x14, 0x93, + 0x20, 0xd0, 0x35, 0x94, 0xcf, 0xcb, 0x47, 0x4c, 0xc8, 0xba, 0x84, 0x42, + 0x33, 0x93, 0xb1, 0xe3, 0x8c, 0xa5, 0xb7, 0xf1, 0x74, 0xd8, 0x17, 0xaa, + 0xf6, 0x78, 0x2c, 0xf5, 0xed, 0x6d, 0xf5, 0x26, 0x6b, 0x8d, 0x41, 0x97, + 0x84, 0x6a, 0x34, 0xc4, 0x97, 0xb9, 0xfb, 0xa9, 0x82, 0x02, 0xab, 0x14, + 0x2f, 0x0e, 0x73, 0xc0, 0x9d, 0xe8, 0x48, 0xa6, 0x09, 0xba, 0x6e, 0xdd, + 0xe1, 0xaf, 0x9e, 0x24, 0xd8, 0xfd, 0x6d, 0x98, 0x84, 0x98, 0xc3, 0x75, + 0xf8, 0x0e, 0xef, 0xe2, 0xaa, 0xac, 0x88, 0x35, 0x61, 0xf2, 0x8e, 0x83, + 0x58, 0x28, 0x2a, 0x95, 0x86, 0x95, 0xd9, 0x52, 0x99, 0x34, 0x2b, 0x45, + 0x26, 0xa2, 0x0d, 0x8d, 0x46, 0xa9, 0xf4, 0x9b, 0x1d, 0xdd, 0xa3, 0x2f, + 0xac, 0xf0, 0x7d, 0x65, 0x55, 0xf4, 0x64, 0x12, 0x2f, 0xf5, 0x51, 0x07, + 0xee, 0x83, 0x54, 0x05, 0x66, 0x1a, 0xea, 0x89, 0xc9, 0x7e, 0x7a, 0x93, + 0x84, 0xe1, 0xf6, 0x16, 0xcc, 0x48, 0x54, 0xe4, 0x8e, 0xa7, 0xa3, 0x6e, + 0x08, 0x0c, 0x95, 0x62, 0x0c, 0x20, 0x9c, 0x91, 0xb4, 0xe8, 0xec, 0x6c, + 0xae, 0x22, 0x19, 0x61, 0x6a, 0x13, 0xbf, 0x50, 0x3f, 0x04, 0x91, 0x01, + 0x5a, 0x0d, 0xfb, 0x1d, 0x8d, 0xfb, 0xf4, 0x6c, 0x3f, 0x47, 0xe7, 0xf2, + 0xfc, 0x94, 0xf5, 0x00, 0x42, 0x12, 0xf5, 0x6f, 0x70, 0x04, 0x6f, 0xa2, + 0x34, 0x4b, 0x68, 0x80, 0x45, 0x0b, 0x84, 0xbe, 0x34, 0x82, 0x05, 0xc3, + 0x7b, 0x8c, 0x89, 0x85, 0xd6, 0x25, 0xea, 0xdc, 0x69, 0x9c, 0xe0, 0x75, + 0x9e, 0x01, 0xde, 0x8e, 0xc0, 0x3a, 0x62, 0x8a, 0x73, 0xf1, 0x1d, 0xa7, + 0x05, 0x6c, 0x6d, 0xbd, 0x46, 0x0f, 0x36, 0x0d, 0x8a, 0xd6, 0xd1, 0x6e, + 0xb6, 0xda, 0x35, 0xf2, 0xdc, 0x1a, 0x39, 0x15, 0x05, 0xa9, 0xee, 0xa2, + 0x91, 0x54, 0x6c, 0xa7, 0xbc, 0x43, 0xff, 0xba, 0xbe, 0x7e, 0xd5, 0xec, + 0x21, 0x83, 0xe2, 0xa7, 0x56, 0x8f, 0x05, 0x03, 0x9c, 0x96, 0x0e, 0x6b, + 0x2a, 0xce, 0xab, 0xbe, 0x5a, 0x2d, 0x0a, 0x34, 0xca, 0x27, 0xc5, 0x62, + 0x6f, 0x3b, 0xc3, 0xfe, 0xdb, 0xfc, 0x40, 0xb1, 0x7d, 0x94, 0x43, 0xdc, + 0x4a, 0xb1, 0xc5, 0x43, 0x6d, 0xa4, 0x51, 0x5a, 0xad, 0x70, 0xf7, 0x6a, + 0xad, 0xd8, 0x96, 0x81, 0xed, 0x31, 0x0f, 0x9d, 0x26, 0xeb, 0x53, 0x58, + 0x38, 0x60, 0xde, 0x14, 0x14, 0xe1, 0x71, 0xb8, 0x2a, 0x46, 0x54, 0xed, + 0xbc, 0x42, 0x7b, 0xaf, 0xdd, 0x93, 0xba, 0x59, 0xd7, 0xaa, 0x80, 0x20, + 0xe8, 0xe8, 0x34, 0x17, 0xc2, 0x96, 0xae, 0xbf, 0xc0, 0x32, 0xf1, 0xd2, + 0xb4, 0x4c, 0xf0, 0x79, 0x47, 0x33, 0x11, 0x7b, 0x22, 0x93, 0x85, 0x71, + 0x82, 0xa5, 0x93, 0x28, 0xa3, 0xb6, 0x64, 0x46, 0x0c, 0x73, 0x35, 0xe0, + 0xee, 0x91, 0x7f, 0xae, 0x3f, 0x6b, 0xc2, 0x44, 0x27, 0x3d, 0xda, 0x2b, + 0xf1, 0xf4, 0xa5, 0x8f, 0x6c, 0xc5, 0x48, 0xbf, 0x6c, 0xee, 0xb5, 0x9f, + 0x6d, 0xed, 0x35, 0xe7, 0x76, 0xdd, 0x26, 0xf0, 0x1c, 0x60, 0xdb, 0x9b, + 0x7b, 0x3b, 0x9b, 0x0b, 0x80, 0xe5, 0xe8, 0x28, 0xdc, 0x6e, 0xc4, 0x9e, + 0x06, 0xeb, 0x65, 0x77, 0xc6, 0xf8, 0x39, 0x55, 0x06, 0xd4, 0xd4, 0x05, + 0xad, 0x74, 0x3a, 0x07, 0x93, 0x85, 0x56, 0xee, 0xa7, 0x8d, 0x1c, 0x62, + 0x9a, 0xed, 0x9e, 0xb2, 0xca, 0x5c, 0xbc, 0x16, 0xb3, 0xc8, 0xcb, 0xed, + 0xf5, 0xbd, 0x8d, 0x66, 0xb3, 0xb9, 0x6e, 0xf6, 0xd0, 0x23, 0xd9, 0x93, + 0x8b, 0x2a, 0xd7, 0x72, 0xba, 0x62, 0x3d, 0x23, 0xf1, 0xdd, 0xbd, 0x67, + 0x2d, 0xa4, 0x7c, 0x10, 0xe9, 0xdf, 0x17, 0x89, 0xf4, 0x38, 0xd9, 0xff, + 0x52, 0x91, 0x7e, 0x56, 0x28, 0xd2, 0x3f, 0x3a, 0xa6, 0x40, 0x6b, 0x63, + 0x13, 0x03, 0xd5, 0x87, 0x20, 0xd2, 0xbf, 0x47, 0x91, 0x9e, 0xbd, 0x0f, + 0x61, 0x5d, 0xed, 0x95, 0x92, 0xe6, 0x0b, 0xd4, 0xe2, 0xef, 0xff, 0x7a, + 0x69, 0xfe, 0x2f, 0x8a, 0xac, 0x40, 0x0e, 0xce, 0x03, 0xbe, 0x26, 0x1b, + 0xe7, 0x1a, 0x9c, 0xf6, 0x79, 0xb2, 0x14, 0xdc, 0xc9, 0x17, 0x87, 0x42, + 0x71, 0x31, 0xff, 0xed, 0xfb, 0x82, 0x8b, 0xf9, 0x6f, 0x15, 0x95, 0xca, + 0x2d, 0xc8, 0x9a, 0x10, 0xdc, 0xb3, 0x59, 0x8f, 0xbf, 0xbe, 0x74, 0x6f, + 0x96, 0x69, 0x7d, 0x50, 0xa7, 0x6d, 0x9b, 0x75, 0xf4, 0xa5, 0xfe, 0x2f, + 0x22, 0x5c, 0xee, 0x94, 0x69, 0x5e, 0xfb, 0xff, 0x4a, 0xc7, 0xab, 0x11, + 0xbb, 0x65, 0xe4, 0x6c, 0x4e, 0xcf, 0xa4, 0x54, 0x3b, 0xa7, 0x39, 0x6f, + 0x08, 0x94, 0x3b, 0x94, 0x13, 0xc4, 0x3e, 0xd1, 0x50, 0x14, 0xde, 0x77, + 0x0b, 0x6f, 0x88, 0x5b, 0x90, 0xa4, 0x05, 0xe7, 0x65, 0x8e, 0x2f, 0xdd, + 0x42, 0x2d, 0x75, 0xdf, 0x62, 0xdc, 0x5f, 0x43, 0x93, 0x05, 0xdd, 0x3b, + 0xec, 0xe4, 0xca, 0xb5, 0x85, 0x40, 0xb4, 0x3f, 0xcd, 0x62, 0xdc, 0xc9, + 0x7b, 0xec, 0x2c, 0xbc, 0xa7, 0xbd, 0xbe, 0x7a, 0x72, 0x76, 0x6a, 0xdd, + 0xa4, 0x87, 0x4e, 0x08, 0x57, 0x19, 0x10, 0x4c, 0x40, 0xb0, 0xbf, 0xc3, + 0x88, 0x2d, 0xd4, 0x3e, 0xc5, 0x86, 0xa1, 0xbb, 0xc0, 0x57, 0xde, 0xdb, + 0xa2, 0xfb, 0xfa, 0x41, 0x33, 0x69, 0x95, 0x50, 0x4f, 0xb6, 0x1f, 0xfc, + 0xe0, 0x27, 0xc6, 0x61, 0x98, 0x46, 0x37, 0x63, 0x6c, 0xe2, 0x5d, 0x67, + 0xbf, 0x73, 0x70, 0x7c, 0x4c, 0x62, 0x87, 0x2d, 0xd7, 0xb3, 0xef, 0x9b, + 0xf5, 0xef, 0xd7, 0x65, 0x65, 0x84, 0xb6, 0x0f, 0x38, 0x73, 0xa3, 0x39, + 0x7a, 0x5f, 0xf1, 0xc3, 0x20, 0xca, 0xda, 0xbe, 0xf0, 0x01, 0x70, 0x74, + 0x61, 0xfc, 0x01, 0x7f, 0x41, 0x45, 0xc4, 0xe6, 0xfc, 0xc4, 0x4f, 0xee, + 0xce, 0x28, 0x8e, 0x41, 0x9a, 0xa9, 0x76, 0x86, 0xf1, 0xfd, 0x2a, 0xe3, + 0x21, 0x94, 0x78, 0x9f, 0x0f, 0x72, 0x35, 0xa4, 0xf7, 0x0c, 0xf7, 0xdb, + 0xe5, 0xa7, 0x4f, 0x5e, 0xf4, 0xcc, 0x2d, 0xca, 0x8f, 0x42, 0xe7, 0x24, + 0x2c, 0x6a, 0x2c, 0xce, 0xdd, 0x62, 0xfc, 0xc6, 0xc8, 0x8f, 0x49, 0x30, + 0x11, 0x5b, 0xb1, 0x2a, 0xba, 0xff, 0xa3, 0x5b, 0x76, 0x5b, 0x8d, 0x67, + 0x1d, 0x4e, 0x44, 0x61, 0x90, 0x69, 0x5a, 0xef, 0xe7, 0x86, 0x7f, 0x47, + 0x31, 0x09, 0x80, 0xc4, 0x05, 0xf1, 0x27, 0xf6, 0x2d, 0xfb, 0x19, 0xe5, + 0x7e, 0x10, 0xb1, 0x32, 0xf8, 0x43, 0x31, 0xe6, 0x1b, 0xc8, 0xbc, 0xa1, + 0xbc, 0x15, 0x61, 0xc8, 0xfc, 0xc4, 0xa4, 0x58, 0xed, 0x0a, 0x46, 0xe5, + 0x93, 0x79, 0x38, 0x57, 0xb7, 0x49, 0x08, 0xfe, 0x2d, 0x45, 0xa1, 0x8a, + 0x87, 0x5d, 0x58, 0x27, 0xab, 0xb8, 0xbf, 0x17, 0x71, 0x2b, 0xc5, 0xc3, + 0x7c, 0x2d, 0xae, 0xd1, 0x4a, 0x5e, 0xa9, 0x06, 0x59, 0xb6, 0xd5, 0x72, + 0xaf, 0xbc, 0xb6, 0x44, 0x4f, 0xe9, 0x88, 0x89, 0xcc, 0x31, 0x82, 0x53, + 0x2c, 0xec, 0xe7, 0xd8, 0xd1, 0x8b, 0x37, 0x6f, 0x72, 0xa5, 0xf5, 0x95, + 0x3d, 0x72, 0x38, 0xe0, 0x47, 0x8f, 0x0c, 0x65, 0x9e, 0x01, 0x06, 0x5b, + 0x12, 0xb1, 0x53, 0xa9, 0xf6, 0xd1, 0x4f, 0x05, 0x1e, 0x51, 0xd4, 0x11, + 0x89, 0x15, 0x94, 0xbc, 0x3a, 0x38, 0x72, 0x29, 0xba, 0x6e, 0xf6, 0x99, + 0x2b, 0x93, 0x8b, 0x7a, 0x2d, 0xef, 0xad, 0x1e, 0x8d, 0xd1, 0xfb, 0x07, + 0xba, 0x30, 0xce, 0xea, 0xf4, 0x62, 0x1d, 0xf6, 0x5d, 0xae, 0xa4, 0x69, + 0x41, 0xd5, 0x6d, 0x51, 0x15, 0xe7, 0xc2, 0x55, 0xf8, 0x29, 0x4b, 0xe2, + 0x31, 0xc8, 0x7b, 0x8a, 0x2f, 0xae, 0x8e, 0x7e, 0x28, 0xb8, 0x4b, 0xba, + 0x8f, 0xb7, 0x6d, 0xd8, 0x76, 0x53, 0x4e, 0x81, 0xd3, 0xdc, 0xf4, 0x90, + 0x57, 0x48, 0x51, 0xc6, 0xaf, 0xa2, 0xcb, 0x2b, 0x00, 0xae, 0x82, 0x80, + 0x48, 0x4e, 0x25, 0xa1, 0xbe, 0x74, 0x98, 0x6b, 0xa0, 0x6d, 0x76, 0x87, + 0x9f, 0xcb, 0xd1, 0x23, 0x4a, 0x9d, 0xca, 0x0f, 0xec, 0xd9, 0x8b, 0x78, + 0x9e, 0x29, 0x6e, 0xba, 0x3c, 0xc8, 0xcf, 0x3c, 0x3e, 0xf7, 0xae, 0x30, + 0x18, 0xde, 0x39, 0xb0, 0x5a, 0x90, 0xe0, 0x34, 0xc1, 0x98, 0xf6, 0xfe, + 0x9b, 0xa2, 0x62, 0xca, 0xd5, 0xef, 0xed, 0x89, 0x52, 0x70, 0x43, 0x94, + 0x78, 0xed, 0x24, 0xbe, 0xb9, 0xe1, 0x47, 0xd7, 0x2b, 0x3c, 0xba, 0x45, + 0xa9, 0x88, 0x40, 0x05, 0xc7, 0x56, 0x79, 0x99, 0x0a, 0x25, 0xc4, 0x40, + 0x9f, 0x96, 0xc9, 0x3d, 0xab, 0x8e, 0x62, 0x30, 0xe3, 0x01, 0xb5, 0xfc, + 0xd7, 0x49, 0xdf, 0x51, 0x48, 0x02, 0xe8, 0x2b, 0xad, 0x61, 0x1d, 0xce, + 0x5d, 0xaf, 0x45, 0x64, 0x5e, 0x56, 0xa5, 0xd6, 0x46, 0xc1, 0x8c, 0x75, + 0x43, 0x6c, 0x48, 0x51, 0x41, 0xb5, 0x48, 0x07, 0xa4, 0x28, 0x0b, 0x8f, + 0xc7, 0xb7, 0x51, 0x37, 0xca, 0x8a, 0x88, 0xbe, 0x25, 0x7a, 0x63, 0x2e, + 0xb1, 0x9f, 0xe8, 0xd1, 0x48, 0x4e, 0xde, 0xdc, 0xea, 0xba, 0x25, 0xf0, + 0xc3, 0xa0, 0x41, 0xf4, 0x1a, 0x29, 0xbd, 0x94, 0x91, 0xd2, 0x71, 0x5f, + 0xbd, 0x4e, 0x4c, 0x75, 0x5f, 0xe7, 0xea, 0xf2, 0xdb, 0x61, 0xcd, 0x52, + 0x6b, 0x06, 0x2e, 0xc2, 0x5a, 0xd1, 0x37, 0x0c, 0x51, 0xc5, 0x63, 0x2d, + 0x23, 0xa5, 0x56, 0x0f, 0x79, 0xd3, 0x10, 0xa9, 0xf9, 0x36, 0x1a, 0x46, + 0xb4, 0xe3, 0x2c, 0xaa, 0xd2, 0x56, 0x55, 0x0e, 0xf0, 0x39, 0x87, 0xd3, + 0xb8, 0x64, 0x53, 0xeb, 0xc6, 0xc0, 0x2d, 0x51, 0x6d, 0x43, 0xd3, 0xe3, + 0x0d, 0xbe, 0xb1, 0x70, 0x3c, 0x5e, 0xa3, 0xbf, 0xe7, 0x53, 0xfe, 0x0a, + 0x7f, 0x5e, 0xff, 0xd4, 0x54, 0xf7, 0x0d, 0xc5, 0x5c, 0x39, 0x22, 0x35, + 0x48, 0x28, 0x09, 0x9a, 0x67, 0x5a, 0x7e, 0xe7, 0x52, 0x50, 0x9e, 0x6f, + 0x3e, 0xb0, 0x70, 0x75, 0x79, 0x98, 0x69, 0xd4, 0xd2, 0x64, 0x33, 0x3c, + 0xa9, 0x4d, 0xa0, 0x49, 0xff, 0xfa, 0xda, 0xe4, 0x6e, 0x9f, 0x05, 0xd5, + 0x91, 0x05, 0xf8, 0xa8, 0x15, 0xd5, 0x5e, 0x57, 0x62, 0x07, 0xb0, 0x34, + 0x14, 0xcd, 0xd8, 0x13, 0x7c, 0x7b, 0xe5, 0x09, 0x7f, 0x5f, 0x84, 0xa6, + 0x73, 0x88, 0x37, 0x82, 0x6f, 0x19, 0x30, 0xab, 0xaa, 0x5e, 0x0d, 0xa9, + 0x7f, 0x5c, 0x53, 0x41, 0xf9, 0xaf, 0xa3, 0xec, 0x78, 0x8c, 0x68, 0x16, + 0xf0, 0x33, 0x6f, 0xcb, 0x22, 0x0e, 0xb9, 0xde, 0x82, 0xbc, 0x0a, 0xfb, + 0x78, 0x34, 0x88, 0x50, 0x8f, 0x89, 0x92, 0xc0, 0x3e, 0xc6, 0xf6, 0x07, + 0x92, 0x9f, 0x4d, 0x47, 0x6a, 0xf2, 0x9c, 0xc4, 0xbd, 0x4f, 0x5c, 0x4f, + 0x28, 0x67, 0x98, 0xd9, 0xfe, 0x78, 0x3a, 0xa2, 0x02, 0x73, 0x5b, 0xde, + 0xd2, 0x83, 0x89, 0xb1, 0xef, 0x48, 0xbd, 0x04, 0x4c, 0x00, 0x5d, 0x95, + 0xed, 0x63, 0x7c, 0x6e, 0x68, 0x43, 0x36, 0x21, 0x61, 0x98, 0x2d, 0x21, + 0x65, 0x10, 0x44, 0x7a, 0x44, 0xef, 0x88, 0xcd, 0x6f, 0xf1, 0x99, 0x6e, + 0xf1, 0xf0, 0xe8, 0x44, 0xe8, 0xcb, 0x91, 0x5c, 0xe8, 0x90, 0x35, 0xbe, + 0xa9, 0x8b, 0xd9, 0xcc, 0xad, 0x8e, 0xb2, 0x3e, 0x22, 0xe0, 0x81, 0xb5, + 0xe3, 0x60, 0x4f, 0xc8, 0x23, 0xa5, 0xca, 0xe3, 0x1e, 0x0c, 0xb3, 0x92, + 0xa8, 0xcb, 0x0d, 0xe5, 0x87, 0x30, 0xc4, 0x07, 0xcc, 0x86, 0x62, 0x4a, + 0x23, 0xcb, 0x0b, 0xb7, 0x54, 0x76, 0x0b, 0x43, 0x3e, 0xc4, 0x61, 0x37, + 0x2e, 0x04, 0xe7, 0x07, 0xe6, 0x13, 0x00, 0xe8, 0xa8, 0xfa, 0x73, 0x5b, + 0xd4, 0xab, 0x01, 0x56, 0x3c, 0x38, 0x39, 0xbe, 0x78, 0x7d, 0xbe, 0x7f, + 0x79, 0xa8, 0x9b, 0x77, 0x47, 0x5e, 0x6b, 0x16, 0x43, 0x51, 0xe8, 0x2a, + 0x3e, 0x18, 0x46, 0x13, 0xe9, 0xdf, 0x3b, 0xa7, 0x2d, 0x6b, 0x37, 0x7b, + 0x97, 0xdc, 0x84, 0xe3, 0xde, 0x8c, 0xdd, 0x47, 0xe3, 0x3e, 0xac, 0x99, + 0xa3, 0x60, 0x1c, 0xdc, 0xc0, 0x3e, 0x76, 0x8b, 0x92, 0x04, 0x52, 0x59, + 0xd6, 0x3f, 0x80, 0x4d, 0x1c, 0xe6, 0x57, 0xfd, 0x7b, 0xdc, 0x4a, 0x84, + 0xdc, 0xdd, 0xf7, 0xb2, 0x23, 0x3e, 0x35, 0x73, 0x9c, 0x12, 0xdc, 0xcc, + 0xb0, 0x88, 0x14, 0xe3, 0xb3, 0x6e, 0xe2, 0x93, 0x04, 0x11, 0xde, 0x23, + 0x95, 0xf7, 0xee, 0x05, 0x5a, 0x34, 0xde, 0x0a, 0x05, 0x09, 0xc3, 0xc1, + 0xc4, 0x44, 0x42, 0x3d, 0x12, 0x33, 0xbf, 0xe9, 0x65, 0xb7, 0x34, 0x09, + 0xc2, 0xdc, 0x42, 0x4b, 0x6e, 0x68, 0xbc, 0x41, 0x2e, 0xdd, 0x60, 0x68, + 0x2f, 0xe9, 0xc9, 0x1a, 0xa4, 0x14, 0xbb, 0x0b, 0xa5, 0xe8, 0xaf, 0xb9, + 0x7f, 0xf2, 0xe6, 0x76, 0xe6, 0x35, 0xc7, 0x95, 0x65, 0x66, 0xdf, 0x25, + 0x04, 0x8b, 0x04, 0x35, 0xd6, 0x83, 0x5d, 0x0e, 0x9f, 0x9b, 0x62, 0xd0, + 0x1c, 0x45, 0x57, 0xf0, 0x20, 0x2a, 0xf1, 0x33, 0xf9, 0xd2, 0x8f, 0xa6, + 0x90, 0x48, 0x40, 0xe0, 0xe8, 0x92, 0xc7, 0x09, 0xad, 0x09, 0xd0, 0x50, + 0x2f, 0x53, 0xd1, 0x16, 0x5a, 0x12, 0x8a, 0x18, 0x23, 0x44, 0x54, 0xd1, + 0x0f, 0x8f, 0x3d, 0xb8, 0x10, 0xf2, 0xc9, 0x12, 0x09, 0x75, 0x2c, 0xd7, + 0xb9, 0x0e, 0xe2, 0x3a, 0x1a, 0xa9, 0xd5, 0x06, 0x6d, 0xbc, 0x38, 0x0d, + 0xbc, 0x12, 0x50, 0x84, 0x9c, 0xec, 0x36, 0xe0, 0xda, 0x7f, 0x02, 0x9d, + 0x3f, 0x44, 0xf1, 0x4b, 0xf3, 0xfa, 0xb2, 0xb8, 0x84, 0xbc, 0x86, 0x1f, + 0x60, 0xed, 0x50, 0x12, 0x2c, 0xae, 0x60, 0x85, 0xf5, 0x75, 0x20, 0x81, + 0xce, 0x74, 0x5c, 0xae, 0x8a, 0x0e, 0x24, 0xf0, 0xf6, 0xa2, 0x5c, 0x0d, + 0x1d, 0x45, 0xa0, 0x73, 0x70, 0x5e, 0xa6, 0xca, 0x96, 0xd1, 0xaf, 0x61, + 0x78, 0x13, 0xc0, 0xc4, 0x97, 0x7e, 0xbd, 0x2c, 0x1c, 0x4d, 0x87, 0x5c, + 0xce, 0xaa, 0xfe, 0xd4, 0x6a, 0x5d, 0x6e, 0x79, 0x18, 0x6a, 0xcb, 0xe8, + 0x16, 0xb7, 0x7c, 0xe4, 0x6b, 0xe7, 0x8f, 0xe1, 0x56, 0xdc, 0x02, 0x94, + 0x37, 0x42, 0x54, 0x4f, 0x4e, 0x82, 0x14, 0x26, 0x9b, 0x42, 0x13, 0x45, + 0x03, 0x69, 0x88, 0xbb, 0xcd, 0xb2, 0xc9, 0xee, 0xda, 0xda, 0x5d, 0x86, + 0xc6, 0x92, 0x71, 0x98, 0xad, 0xf5, 0xe3, 0x5e, 0x0a, 0x5f, 0xa1, 0xc1, + 0x3a, 0x57, 0xdf, 0x4f, 0x60, 0x2c, 0x36, 0x1a, 0xb7, 0xd9, 0x68, 0x58, + 0xf0, 0x70, 0x00, 0x9d, 0x17, 0xe6, 0xa8, 0x6d, 0xb0, 0x1c, 0x30, 0x1b, + 0x4f, 0xe6, 0xda, 0xe4, 0xb8, 0xfb, 0x11, 0x78, 0x50, 0xa9, 0x94, 0x8b, + 0x2f, 0x97, 0xdb, 0x31, 0xbd, 0xe7, 0x5c, 0xf8, 0xd6, 0xaf, 0xcf, 0x20, + 0x3a, 0xea, 0xee, 0xd6, 0x07, 0xa5, 0xf4, 0x5c, 0xe1, 0x6b, 0xa3, 0x75, + 0xa9, 0xbd, 0xdc, 0xcd, 0x05, 0xc7, 0x47, 0x7e, 0x43, 0xfb, 0x53, 0x73, + 0x4d, 0x2c, 0x29, 0x51, 0x04, 0x11, 0x64, 0x3c, 0x5a, 0xfe, 0xe3, 0xf1, + 0xfb, 0x6e, 0x9a, 0xde, 0xd8, 0x42, 0xe3, 0x83, 0x17, 0x40, 0xb3, 0x23, + 0x1e, 0x61, 0xb1, 0xa8, 0x7e, 0xf9, 0x9b, 0x03, 0x73, 0x91, 0x6f, 0x39, + 0xc8, 0x1b, 0x93, 0x56, 0x1c, 0x49, 0x4b, 0xf4, 0xc1, 0x81, 0x61, 0x3c, + 0x81, 0x88, 0x51, 0x80, 0x75, 0xe8, 0x60, 0xf1, 0xdc, 0x61, 0xe3, 0x5d, + 0xc7, 0x7d, 0xbe, 0xc6, 0xac, 0xd2, 0x5a, 0xbe, 0x4a, 0x7b, 0xf9, 0x2a, + 0xeb, 0x0b, 0xab, 0x90, 0x01, 0xc3, 0xd4, 0xf7, 0x30, 0x34, 0x0a, 0xce, + 0xa1, 0xc3, 0xfa, 0x2e, 0xd6, 0xc1, 0xe3, 0x2f, 0x46, 0xc7, 0xc4, 0x1a, + 0x4e, 0xf3, 0x18, 0xa6, 0xef, 0x80, 0x3f, 0x7c, 0xa4, 0x74, 0x7b, 0x0e, + 0x8a, 0xfc, 0x19, 0x96, 0x2a, 0x00, 0x31, 0xc2, 0x27, 0x97, 0xbd, 0xe1, + 0x42, 0x15, 0xb8, 0x91, 0xb0, 0x24, 0xfb, 0x3d, 0x73, 0x2a, 0xeb, 0x43, + 0x6e, 0x49, 0x00, 0xad, 0xb6, 0x75, 0x9b, 0x80, 0x77, 0x8b, 0x07, 0x90, + 0xa5, 0xb8, 0x6c, 0x8b, 0x21, 0x6c, 0xb9, 0x1d, 0x18, 0xc6, 0x37, 0xd5, + 0x4a, 0x27, 0x4c, 0x50, 0x3c, 0xa7, 0xab, 0x16, 0xc2, 0xf2, 0x1c, 0xf6, + 0xcd, 0x2d, 0x45, 0x1c, 0x48, 0x1b, 0x15, 0x77, 0x90, 0x8d, 0x32, 0x3f, + 0x70, 0x29, 0x77, 0x31, 0x0e, 0x3b, 0x34, 0x72, 0x3f, 0xb5, 0x9a, 0xfc, + 0xac, 0x64, 0xf6, 0x68, 0x1c, 0xcb, 0x93, 0x26, 0x06, 0x4c, 0x83, 0x51, + 0x45, 0xc0, 0xf4, 0x11, 0xe4, 0xa2, 0x70, 0x28, 0x12, 0xc5, 0x21, 0xa2, + 0x61, 0x91, 0xa6, 0xd9, 0x6c, 0x12, 0x5c, 0x58, 0x3c, 0x89, 0x83, 0xf2, + 0x90, 0x39, 0xb4, 0x46, 0x2e, 0x55, 0x80, 0xab, 0xc9, 0x7b, 0x3b, 0x3d, + 0x2e, 0x7d, 0x49, 0xd3, 0x39, 0xb5, 0xec, 0xb6, 0xd5, 0xa6, 0xb6, 0xc4, + 0x69, 0x99, 0x8e, 0x88, 0x56, 0x93, 0xb2, 0x18, 0x67, 0x52, 0xbc, 0x1c, + 0x94, 0x2f, 0xc3, 0xec, 0xac, 0xba, 0x38, 0xc1, 0x73, 0x2c, 0xc5, 0xb1, + 0xb3, 0x66, 0x96, 0x95, 0x62, 0x79, 0x46, 0xe6, 0x72, 0xd2, 0x73, 0x48, + 0x0c, 0x6e, 0xc3, 0x61, 0x9f, 0xe1, 0xa3, 0xaf, 0x0d, 0x7b, 0x78, 0x1e, + 0x5a, 0x4d, 0x7e, 0x1e, 0x7d, 0x61, 0x6e, 0x00, 0x3b, 0xce, 0x20, 0x12, + 0xc9, 0x3c, 0xe5, 0x90, 0xa6, 0x4e, 0x51, 0xae, 0x5a, 0x71, 0xca, 0xbe, + 0xf4, 0x95, 0xa4, 0xae, 0x1e, 0x51, 0x2f, 0x72, 0x3c, 0xc1, 0x5d, 0xe8, + 0xac, 0x27, 0x11, 0x7b, 0x72, 0xfd, 0xab, 0x08, 0xeb, 0x45, 0x65, 0xcf, + 0xc3, 0xa8, 0xaf, 0xd1, 0x72, 0x8e, 0xae, 0x2f, 0x31, 0x27, 0xa5, 0x3c, + 0x9d, 0x2f, 0xb8, 0xb0, 0xd4, 0x6c, 0x6e, 0xec, 0xf2, 0x15, 0x06, 0xc4, + 0x2b, 0x7a, 0x45, 0x31, 0x1a, 0xaf, 0xd1, 0xdf, 0x58, 0x9d, 0xf0, 0x4d, + 0x4a, 0x8b, 0x22, 0xbb, 0x68, 0xf0, 0x3e, 0xce, 0x65, 0x40, 0x1d, 0xca, + 0x39, 0x77, 0xd7, 0xbb, 0x71, 0x9f, 0xb4, 0x06, 0x65, 0x26, 0x72, 0xb3, + 0xb9, 0x49, 0x18, 0x4d, 0xb3, 0xc1, 0x36, 0xea, 0x31, 0xf9, 0x92, 0x67, + 0xb3, 0x07, 0xf7, 0x6e, 0xcd, 0x06, 0x92, 0xda, 0x36, 0x50, 0xc2, 0x26, + 0x01, 0x91, 0xb0, 0xaf, 0xcd, 0xf0, 0x56, 0x27, 0xd2, 0x68, 0x84, 0xfe, + 0x1b, 0x70, 0xe6, 0xa1, 0xc8, 0x61, 0xc3, 0x00, 0xce, 0x29, 0xb0, 0xd7, + 0x0f, 0xa7, 0x21, 0xdd, 0x02, 0xa5, 0x96, 0xb5, 0xdb, 0xcc, 0x7c, 0x64, + 0xb7, 0x38, 0xf9, 0x6e, 0x92, 0xb9, 0xb8, 0x42, 0xfe, 0x23, 0x71, 0xa5, + 0xd7, 0xff, 0xf0, 0xb8, 0x19, 0xf4, 0xfb, 0x0c, 0x96, 0x74, 0x54, 0xe9, + 0x46, 0xc0, 0xd3, 0x56, 0x21, 0x52, 0x6f, 0x10, 0xe5, 0x9f, 0x77, 0xf7, + 0x1e, 0xf6, 0x66, 0xa7, 0x66, 0xa6, 0x58, 0x36, 0x8c, 0xec, 0xd1, 0xdc, + 0x2e, 0xb5, 0x04, 0xfd, 0x51, 0x59, 0x32, 0x7f, 0x00, 0xb0, 0xc4, 0x23, + 0xbb, 0xc5, 0xdd, 0x37, 0xb8, 0xb6, 0x63, 0x5e, 0x7f, 0xf2, 0xdd, 0xe1, + 0xab, 0x80, 0xce, 0xbc, 0x9a, 0x27, 0x11, 0xf0, 0xae, 0xe0, 0xa3, 0xb0, + 0xe2, 0xec, 0x63, 0xf7, 0x80, 0xa7, 0xbd, 0xe5, 0xb1, 0x27, 0x5f, 0xe8, + 0xf7, 0x68, 0x8b, 0x89, 0xb3, 0xc1, 0x97, 0xe8, 0x60, 0x98, 0xd9, 0x0f, + 0x92, 0xb9, 0xe0, 0x85, 0x0c, 0x85, 0x5b, 0xad, 0xf9, 0x1c, 0x2d, 0xff, + 0x21, 0x8f, 0xd8, 0x37, 0xfb, 0x27, 0x27, 0xf5, 0xab, 0xb7, 0x97, 0xe7, + 0xef, 0xbe, 0x7f, 0x6b, 0x89, 0x71, 0xcf, 0xfc, 0x2d, 0x38, 0x78, 0xcc, + 0x2f, 0x65, 0x8a, 0x90, 0x7c, 0x61, 0x32, 0x23, 0x04, 0x88, 0x07, 0x5a, + 0xe4, 0xc3, 0x68, 0x66, 0x06, 0x7f, 0x7e, 0x26, 0xdd, 0x35, 0x1c, 0x70, + 0x6b, 0x56, 0x36, 0x39, 0x00, 0xef, 0x1a, 0xce, 0xc0, 0x4e, 0x36, 0x1c, + 0x03, 0x27, 0x32, 0x1b, 0x3f, 0xdb, 0xd9, 0x0f, 0x22, 0xeb, 0xc1, 0xa9, + 0x25, 0x6b, 0xd8, 0xc9, 0xea, 0x15, 0x8a, 0x5d, 0xf3, 0x0a, 0x00, 0x7c, + 0xf7, 0x15, 0xe3, 0x5e, 0xed, 0xbb, 0xf9, 0xcb, 0x02, 0x76, 0x61, 0x7c, + 0xa7, 0x41, 0x14, 0xc2, 0x8f, 0x56, 0x1e, 0xee, 0xbd, 0x3f, 0xfd, 0x44, + 0x61, 0x8c, 0xe5, 0x73, 0xd6, 0xe8, 0x9d, 0x8d, 0x9b, 0xca, 0x2b, 0xb7, + 0xa0, 0xc8, 0x17, 0xa0, 0xc4, 0xb7, 0x9a, 0x5b, 0x8a, 0xbf, 0x9b, 0x2d, + 0x0a, 0xf1, 0x2f, 0xb9, 0x32, 0x52, 0xea, 0xb3, 0x41, 0x99, 0x98, 0x7d, + 0xde, 0x33, 0xbe, 0x48, 0xf1, 0x0c, 0x70, 0x5b, 0xcd, 0xa5, 0xeb, 0xc7, + 0xee, 0xc4, 0x53, 0x13, 0x4e, 0xbe, 0xfb, 0x3c, 0xb2, 0x80, 0x5f, 0x28, + 0xd8, 0x3b, 0x86, 0xde, 0x21, 0x13, 0xef, 0x76, 0x70, 0x53, 0x8c, 0xc7, + 0xe0, 0xba, 0xb4, 0xa9, 0x57, 0x98, 0x50, 0xbe, 0x9a, 0xad, 0x57, 0xc4, + 0xc2, 0x45, 0x9f, 0x11, 0x6e, 0x31, 0xcb, 0x5b, 0x7a, 0x87, 0x05, 0x96, + 0x5e, 0xf1, 0x24, 0x09, 0xa4, 0x5f, 0x76, 0xfc, 0xb6, 0x5e, 0x01, 0x7c, + 0x79, 0x33, 0x2f, 0xba, 0x54, 0xf2, 0x75, 0x54, 0x1a, 0x72, 0x7d, 0x46, + 0xdb, 0xed, 0x66, 0x79, 0x9b, 0xed, 0x3f, 0xa6, 0xa3, 0x09, 0xab, 0xbe, + 0x81, 0x03, 0x74, 0x39, 0x8b, 0xad, 0x40, 0xbd, 0x84, 0xc1, 0xd6, 0xee, + 0xe4, 0x22, 0xbb, 0xed, 0x59, 0xbc, 0x94, 0xe9, 0x16, 0x8a, 0x2f, 0x65, + 0xbd, 0x3d, 0x8c, 0xc7, 0x95, 0x8c, 0x4b, 0x27, 0xf3, 0x6c, 0xb8, 0x5e, + 0xcb, 0xec, 0x5b, 0xda, 0x7d, 0x4a, 0x59, 0x66, 0xe3, 0xc9, 0x92, 0x86, + 0x59, 0x8e, 0xd7, 0x64, 0x29, 0xf3, 0xec, 0x49, 0x34, 0x8a, 0x64, 0x1d, + 0xf4, 0x46, 0xa3, 0x51, 0xc3, 0x16, 0xd1, 0xb1, 0x31, 0x5e, 0x64, 0x9e, + 0xa5, 0xde, 0x94, 0x33, 0xcf, 0x0a, 0xa2, 0x95, 0x37, 0xd2, 0x1e, 0x72, + 0xdd, 0xdd, 0x52, 0x56, 0x5a, 0xa9, 0x21, 0xc7, 0xba, 0xa5, 0xad, 0xae, + 0x67, 0xf1, 0x63, 0x0d, 0xaf, 0x12, 0xc5, 0x72, 0x96, 0x57, 0xa5, 0x32, + 0x3d, 0x5b, 0x64, 0x79, 0x1d, 0x0c, 0x16, 0x9b, 0x5e, 0xcf, 0xe2, 0x65, + 0xad, 0xaf, 0xc0, 0x4f, 0xda, 0xf8, 0x5a, 0x7d, 0xb4, 0xf5, 0x35, 0x87, + 0xb9, 0xd6, 0x55, 0x8b, 0x59, 0x6a, 0x2b, 0xaa, 0xbd, 0xd6, 0xd3, 0xb3, + 0x29, 0x5d, 0xdf, 0x7f, 0xbc, 0xe5, 0x94, 0x5f, 0xea, 0x2a, 0x61, 0x36, + 0x2d, 0x37, 0x59, 0xbf, 0xae, 0xf1, 0x94, 0xb7, 0x39, 0x5d, 0xde, 0x84, + 0xaa, 0x2b, 0x3e, 0xc6, 0x90, 0xaa, 0x6b, 0x3f, 0xc2, 0x9c, 0x6a, 0xd0, + 0x69, 0x69, 0xa3, 0xaa, 0x9c, 0x07, 0x4b, 0x59, 0x55, 0x45, 0x83, 0x73, + 0x6d, 0xab, 0xca, 0x84, 0xb5, 0xc0, 0xc4, 0x5a, 0x0c, 0xab, 0xbc, 0xa1, + 0x95, 0xc3, 0x88, 0x3c, 0xe6, 0x56, 0x35, 0x5d, 0xc4, 0x14, 0xb1, 0x6c, + 0x5c, 0x4b, 0x1b, 0x59, 0x25, 0xb1, 0xbe, 0xc4, 0xca, 0x2a, 0x11, 0x59, + 0xd6, 0xcc, 0x6a, 0x0c, 0xb2, 0x36, 0x57, 0xfa, 0x6c, 0xad, 0xb6, 0xed, + 0xd0, 0x6a, 0xee, 0xb1, 0xb6, 0x56, 0xae, 0x97, 0xbf, 0xa4, 0x17, 0xa7, + 0x8b, 0x8c, 0xae, 0x12, 0x82, 0xb8, 0xf1, 0x39, 0xd7, 0xe8, 0xea, 0xed, + 0x8b, 0xc7, 0xf4, 0x3a, 0xa7, 0x2b, 0xcb, 0x9b, 0x5e, 0x0f, 0xf9, 0x5d, + 0xa0, 0x4f, 0xb6, 0x05, 0x96, 0x9a, 0x9e, 0x6f, 0x7e, 0xb5, 0xda, 0x7d, + 0xb4, 0xfd, 0xf5, 0xe2, 0xf2, 0xf8, 0x74, 0xff, 0xf2, 0x67, 0x8f, 0xf5, + 0xd5, 0xc7, 0x9a, 0x8f, 0x32, 0xbf, 0x4a, 0xf6, 0xfc, 0x3a, 0xf6, 0x57, + 0xab, 0xdb, 0x8f, 0x34, 0xc0, 0x4a, 0x8c, 0x4a, 0x58, 0x60, 0x25, 0x8c, + 0x12, 0xc8, 0x2c, 0x6d, 0x88, 0xf5, 0x6d, 0x6e, 0x86, 0x09, 0x52, 0x3c, + 0x79, 0x2e, 0x20, 0xf0, 0x58, 0xef, 0x70, 0xde, 0x8d, 0xb8, 0x56, 0xd2, + 0xb5, 0xe2, 0x7e, 0x91, 0xa1, 0xb2, 0xd0, 0x7c, 0x0b, 0x87, 0x85, 0x0c, + 0xaf, 0x89, 0xb8, 0x26, 0xd5, 0x4b, 0xd7, 0x82, 0xfb, 0xc5, 0xe6, 0xe2, + 0x9d, 0xb9, 0x64, 0xa1, 0x15, 0x2c, 0xb1, 0x90, 0x51, 0x86, 0xcf, 0x42, + 0x9c, 0xe6, 0x21, 0x93, 0xe7, 0x96, 0x32, 0xc6, 0x5a, 0xc7, 0x4a, 0x2b, + 0x81, 0x94, 0x36, 0xd6, 0xfa, 0xac, 0xb4, 0x7a, 0x74, 0xca, 0x1b, 0x6b, + 0xf9, 0x19, 0xee, 0x4b, 0xcc, 0xb5, 0x1c, 0xc2, 0x92, 0x06, 0x5b, 0x5e, + 0x69, 0x39, 0x93, 0xad, 0x68, 0x68, 0x39, 0xa3, 0x2d, 0xaf, 0xf4, 0x05, + 0x66, 0x5b, 0x0e, 0xc0, 0x53, 0x13, 0xb6, 0x72, 0xe8, 0xf4, 0xda, 0xc5, + 0x01, 0xe3, 0x6a, 0xe7, 0x42, 0x13, 0x2e, 0x87, 0xe0, 0x37, 0xe2, 0x16, + 0x3d, 0xe4, 0xf9, 0x7f, 0xc9, 0x14, 0xab, 0x10, 0xfa, 0x7f, 0x66, 0x8c, + 0x5d, 0xa8, 0x67, 0x5c, 0x64, 0x8d, 0x2d, 0x06, 0xf0, 0x1f, 0x34, 0xc7, + 0x2e, 0xec, 0x85, 0x11, 0xe0, 0x4b, 0xe1, 0x42, 0xd7, 0x08, 0xc8, 0x82, + 0x02, 0xe7, 0xc4, 0x6f, 0xbf, 0x75, 0x0c, 0x92, 0xb6, 0x92, 0xd2, 0x34, + 0x44, 0xda, 0xe5, 0xfc, 0x36, 0x49, 0xad, 0xc6, 0x12, 0x27, 0x16, 0xbb, + 0xd2, 0xa3, 0x8d, 0x97, 0x0b, 0x3b, 0xba, 0xd0, 0x7a, 0xb9, 0x58, 0xb1, + 0xbc, 0xd0, 0x7c, 0xb9, 0x10, 0x44, 0x81, 0xfd, 0x92, 0x46, 0x99, 0x6e, + 0x51, 0xc3, 0x7c, 0xc5, 0x49, 0x2e, 0x54, 0x84, 0xcb, 0x98, 0x2d, 0x17, + 0xb6, 0xed, 0xb7, 0x5b, 0x2e, 0xb2, 0x3e, 0x7e, 0x55, 0x8b, 0xa1, 0x6b, + 0xd4, 0x73, 0x70, 0xce, 0x5b, 0xf3, 0x7c, 0x05, 0x6c, 0x1b, 0x9e, 0xaf, + 0x84, 0x6d, 0xbb, 0xf3, 0x95, 0x28, 0x32, 0xde, 0x55, 0xbe, 0x9e, 0x1d, + 0x2e, 0x67, 0x54, 0x2b, 0x61, 0xb8, 0x78, 0x84, 0x55, 0xad, 0x0c, 0xd4, + 0xa5, 0xcd, 0x5f, 0x25, 0x80, 0x3e, 0xce, 0x00, 0xb5, 0x78, 0x51, 0xe5, + 0x60, 0x6f, 0x51, 0x8f, 0x56, 0xc2, 0x18, 0xb4, 0xd8, 0x50, 0x59, 0xd6, + 0x16, 0x54, 0xc6, 0xdc, 0x23, 0x66, 0xe5, 0x62, 0x8b, 0x8f, 0xaf, 0x20, + 0xab, 0xe7, 0xdd, 0xf3, 0xf2, 0x4b, 0xaf, 0xcf, 0x0e, 0xa4, 0xad, 0x3c, + 0xd2, 0x17, 0x84, 0x97, 0xe2, 0x69, 0x39, 0xf3, 0x01, 0x0f, 0xad, 0x64, + 0x97, 0x54, 0x11, 0x61, 0xec, 0x92, 0x68, 0xfb, 0x71, 0x4b, 0x62, 0x5a, + 0xae, 0xe4, 0x83, 0x53, 0xea, 0x21, 0x0f, 0xcb, 0x85, 0x93, 0x37, 0x6b, + 0x48, 0xc3, 0x90, 0x53, 0x52, 0xa5, 0x17, 0xd4, 0xe0, 0x06, 0x22, 0x6f, + 0x25, 0xf3, 0xe5, 0x75, 0xa3, 0x1e, 0xda, 0x8c, 0x9c, 0xf2, 0x98, 0x34, + 0xc7, 0x10, 0x33, 0x1d, 0x5a, 0x66, 0x18, 0x18, 0x42, 0x7d, 0x1d, 0x50, + 0xf8, 0x12, 0x98, 0xe1, 0xe9, 0x45, 0x19, 0x97, 0x38, 0xb4, 0x8b, 0xfd, + 0xb4, 0xe7, 0x2d, 0x34, 0xb3, 0x0a, 0xfd, 0xec, 0x14, 0xfa, 0x9c, 0xdf, + 0x51, 0x0b, 0x1f, 0x46, 0x77, 0x89, 0xf4, 0x25, 0xd6, 0x22, 0x71, 0x4f, + 0x53, 0x48, 0xf1, 0xe4, 0x9f, 0xa8, 0x14, 0xde, 0x97, 0x5c, 0xe1, 0x7d, + 0x9d, 0xc1, 0xc8, 0x70, 0xfd, 0x91, 0x75, 0x8f, 0x97, 0xdf, 0x59, 0xc2, + 0x07, 0x65, 0x40, 0x26, 0x84, 0xb3, 0xa7, 0x38, 0x6b, 0xf6, 0xf1, 0x76, + 0x1a, 0x99, 0x2e, 0xae, 0x5e, 0xbb, 0x36, 0x9d, 0xa4, 0xc0, 0x07, 0x90, + 0xb7, 0x29, 0xda, 0x9b, 0x27, 0x80, 0x9a, 0xf2, 0x9d, 0x16, 0x00, 0x73, + 0xdc, 0x65, 0xdc, 0xf5, 0xfc, 0xe3, 0x0f, 0xbc, 0xc8, 0x59, 0x37, 0xee, + 0xbb, 0x3a, 0x4c, 0x65, 0xdc, 0xf9, 0x94, 0x17, 0xe8, 0xf9, 0xbd, 0xcd, + 0xba, 0x13, 0xff, 0x47, 0x07, 0x3c, 0xcc, 0x3f, 0x9f, 0x2e, 0xb4, 0x0c, + 0xa6, 0xfb, 0x6e, 0x15, 0xa3, 0x70, 0x34, 0x3a, 0x3f, 0x17, 0xbc, 0x9c, + 0xaf, 0x6d, 0xce, 0x45, 0x1d, 0x36, 0x38, 0x8a, 0x99, 0x51, 0x9c, 0x0c, + 0x26, 0x62, 0xfa, 0x19, 0x5a, 0x03, 0x99, 0x29, 0x47, 0xc6, 0x39, 0xfb, + 0x2e, 0xc0, 0x47, 0x1c, 0x4e, 0x4b, 0xa0, 0xe4, 0x70, 0x3b, 0x52, 0xcd, + 0x26, 0x8d, 0x89, 0x20, 0xcf, 0x34, 0xa2, 0xbc, 0x9e, 0x84, 0x29, 0xc6, + 0xc2, 0x7d, 0x87, 0xae, 0xbf, 0x4e, 0x9c, 0x57, 0x11, 0x94, 0xdc, 0x79, + 0x8d, 0xfd, 0x2a, 0xe8, 0xca, 0xc3, 0x0f, 0x94, 0x81, 0x69, 0x0c, 0x27, + 0x9f, 0x78, 0x92, 0x8f, 0xa3, 0xf9, 0xf6, 0xaa, 0xc4, 0xe3, 0xec, 0x00, + 0xac, 0xa8, 0x6f, 0xde, 0x0b, 0xd4, 0xc4, 0x3e, 0xd8, 0xb9, 0x39, 0xf1, + 0xc7, 0xf4, 0xd2, 0x08, 0xbb, 0x20, 0x1a, 0x15, 0xfc, 0xd1, 0x53, 0x3b, + 0x4c, 0x5a, 0x00, 0xa7, 0x13, 0xfc, 0xce, 0xd7, 0x73, 0xa7, 0x17, 0x9d, + 0x77, 0x05, 0xdc, 0x42, 0x35, 0xdf, 0x4d, 0xbe, 0x3a, 0xf2, 0x56, 0x40, + 0x3b, 0x63, 0xf7, 0x78, 0xea, 0xda, 0xf2, 0x3d, 0xc1, 0xd4, 0x16, 0x55, + 0x13, 0x86, 0x7d, 0x4f, 0x5c, 0xbd, 0x55, 0x41, 0xa1, 0xe5, 0x62, 0xe6, + 0x29, 0x64, 0x1e, 0x1b, 0x3b, 0xef, 0x4a, 0x0d, 0x01, 0xba, 0x9a, 0x15, + 0x0f, 0xc2, 0xe1, 0xbc, 0x41, 0x38, 0xc4, 0xaa, 0xff, 0x4f, 0x86, 0x41, + 0xd2, 0x73, 0xf9, 0x91, 0xa0, 0x01, 0xfc, 0x3f, 0x33, 0x0c, 0x7b, 0x9e, + 0x5f, 0x57, 0x7c, 0xee, 0x1f, 0x8f, 0xa3, 0x2c, 0x42, 0xa5, 0xa0, 0xd2, + 0x1b, 0x0b, 0x3f, 0xb9, 0x4c, 0x9a, 0x6b, 0x18, 0xbb, 0xd0, 0xd1, 0xa4, + 0xd4, 0x6b, 0x92, 0xd7, 0x38, 0x1c, 0x7b, 0x14, 0xc7, 0xe6, 0x81, 0xff, + 0x99, 0xed, 0x91, 0x80, 0x85, 0x71, 0x05, 0x30, 0x0c, 0x3f, 0xc5, 0xfd, + 0x2b, 0xb0, 0x5f, 0x71, 0x10, 0xda, 0x20, 0xe4, 0x8d, 0xdb, 0x1a, 0x71, + 0x11, 0x56, 0x96, 0x2a, 0xe2, 0x00, 0x00, 0x75, 0x09, 0x67, 0x8b, 0xbb, + 0x60, 0x9c, 0xed, 0x32, 0x7e, 0x1f, 0x1d, 0x05, 0xf0, 0x96, 0x49, 0x02, + 0x8c, 0xb5, 0x64, 0x76, 0x9a, 0xab, 0x6a, 0xe2, 0x71, 0xc8, 0x64, 0x54, + 0x9b, 0x41, 0x18, 0xf0, 0x20, 0x58, 0x42, 0x71, 0x97, 0x45, 0xd9, 0x90, + 0x2b, 0x6f, 0x52, 0xf9, 0x36, 0x9c, 0x7c, 0x26, 0x8b, 0x20, 0x90, 0x57, + 0x5c, 0x83, 0x09, 0xd5, 0xe3, 0x70, 0x56, 0x63, 0x4f, 0x48, 0x7f, 0xf2, + 0xc4, 0xd6, 0xf0, 0x0a, 0xb0, 0x3c, 0x48, 0x52, 0x94, 0x62, 0x68, 0xf6, + 0x54, 0x86, 0xf6, 0x41, 0x7d, 0x32, 0xbe, 0x1b, 0x2a, 0x54, 0xcb, 0x64, + 0x0c, 0xe8, 0xa2, 0xad, 0x8e, 0x82, 0x27, 0x89, 0xa7, 0x44, 0x24, 0x5a, + 0xdd, 0x99, 0xb0, 0x83, 0xd2, 0x93, 0x79, 0x62, 0xdf, 0x8f, 0x50, 0xc8, + 0xc5, 0x23, 0x9f, 0x9c, 0x4d, 0xa8, 0xe2, 0x71, 0xb1, 0x8f, 0xc6, 0x00, + 0x8d, 0x82, 0xb4, 0xd8, 0xaa, 0x2b, 0xcb, 0x98, 0x80, 0x6d, 0x71, 0x65, + 0xf6, 0x5a, 0xd4, 0x83, 0x51, 0x1a, 0x06, 0xdd, 0x70, 0x98, 0xb2, 0x29, + 0x29, 0xbb, 0x6f, 0xc3, 0x87, 0xa0, 0x1f, 0xf6, 0x22, 0x14, 0xea, 0x3c, + 0xce, 0x1f, 0x02, 0xc4, 0x6f, 0xd3, 0x30, 0x99, 0x2d, 0x06, 0xa2, 0xf4, + 0xe3, 0x39, 0x68, 0xed, 0xd2, 0x08, 0xbd, 0xbb, 0x7a, 0x53, 0xdf, 0xf6, + 0x39, 0x8a, 0x94, 0x43, 0xc5, 0xac, 0x5e, 0x45, 0xfe, 0x84, 0x21, 0x80, + 0xf3, 0x22, 0xc5, 0x75, 0x82, 0xe1, 0x7f, 0x72, 0x45, 0xd4, 0xa3, 0x4b, + 0x17, 0x4f, 0x0a, 0xb7, 0xee, 0x30, 0xa3, 0x62, 0x54, 0xaa, 0x88, 0x35, + 0xdd, 0x69, 0xf8, 0xbf, 0x6a, 0xab, 0x45, 0x73, 0xf2, 0x52, 0x7b, 0xed, + 0xeb, 0xb9, 0x7b, 0xad, 0x04, 0xf7, 0x97, 0x6e, 0xb6, 0x20, 0x05, 0xde, + 0x15, 0x6f, 0xb6, 0x5d, 0x9c, 0x55, 0xe4, 0xbb, 0x42, 0x96, 0x0d, 0x15, + 0x8a, 0xfb, 0x26, 0x09, 0x26, 0xb7, 0x51, 0xcf, 0x08, 0xe2, 0x80, 0xfd, + 0xe4, 0xf1, 0x84, 0x2e, 0x8f, 0x0a, 0xc2, 0x8b, 0x70, 0x2f, 0x18, 0x15, + 0x75, 0x5b, 0x3b, 0x32, 0x2c, 0xdd, 0x39, 0xea, 0x47, 0x8d, 0x07, 0xb2, + 0x7a, 0x61, 0xac, 0xdf, 0xd7, 0xf9, 0x85, 0x7b, 0xf6, 0x41, 0x14, 0xa6, + 0xa0, 0x9d, 0x58, 0xea, 0x5a, 0x10, 0xa0, 0xce, 0xb8, 0xa8, 0xca, 0xbf, + 0x8b, 0x07, 0x7a, 0x44, 0x10, 0x4f, 0x5f, 0xa8, 0x54, 0xa3, 0xae, 0x0e, + 0xcf, 0x69, 0x93, 0xeb, 0x86, 0xe1, 0xd0, 0xb3, 0x03, 0x3c, 0x9e, 0xb2, + 0xea, 0xd5, 0xeb, 0x03, 0xef, 0xab, 0xec, 0x3c, 0x1b, 0x78, 0x86, 0x66, + 0xb9, 0xf0, 0x81, 0x2a, 0x78, 0xa3, 0x7d, 0xdd, 0xa8, 0x21, 0x5f, 0xf2, + 0xbf, 0x88, 0x31, 0xdc, 0x41, 0x84, 0x0b, 0x94, 0xb8, 0x3e, 0x64, 0xcc, + 0x34, 0x5e, 0xb4, 0x43, 0xec, 0x16, 0xf3, 0xc7, 0xfd, 0x1b, 0x05, 0x77, + 0x8c, 0x82, 0xf1, 0x38, 0x48, 0xba, 0x71, 0xb2, 0x16, 0x04, 0x41, 0x7d, + 0x7a, 0xb3, 0x26, 0x16, 0xf3, 0xad, 0xc2, 0x5b, 0x46, 0xc0, 0xc8, 0x1c, + 0xfc, 0x17, 0xc4, 0xce, 0x31, 0x9e, 0x29, 0x34, 0xf5, 0x96, 0x78, 0xac, + 0x14, 0xc4, 0xa5, 0x1a, 0xee, 0x03, 0x50, 0xfc, 0x29, 0x32, 0x8b, 0x85, + 0xc5, 0xe1, 0xf4, 0xf7, 0xcf, 0x79, 0xc6, 0x1d, 0xb1, 0x88, 0xb1, 0x53, + 0xe0, 0xb2, 0x00, 0xc8, 0x3b, 0x99, 0xb1, 0xea, 0xa9, 0x7f, 0x24, 0x78, + 0xc0, 0x09, 0x19, 0x2f, 0xc2, 0x3f, 0x02, 0x86, 0xfb, 0x4c, 0x3c, 0x18, + 0xc8, 0x27, 0x2e, 0xe4, 0xe5, 0x80, 0x61, 0x98, 0x78, 0x6c, 0x18, 0x9b, + 0x46, 0x9d, 0xf1, 0xdc, 0x2a, 0xea, 0x48, 0x17, 0x71, 0x00, 0x36, 0xd2, + 0x73, 0x1f, 0x2c, 0x6a, 0x19, 0x5d, 0xa0, 0x99, 0x80, 0xf0, 0x03, 0xd8, + 0x61, 0x61, 0x7e, 0xf2, 0x05, 0x64, 0x6e, 0x47, 0x82, 0x29, 0xf0, 0x08, + 0x55, 0x5e, 0x84, 0xff, 0xbc, 0x92, 0x2d, 0x66, 0x91, 0x12, 0x77, 0xb3, + 0x18, 0x0d, 0x5c, 0xa8, 0xfc, 0x18, 0x06, 0xb0, 0x81, 0x46, 0x37, 0xe3, + 0x18, 0xb7, 0x3a, 0xee, 0xed, 0x95, 0xab, 0x6c, 0x76, 0x02, 0x18, 0x9a, + 0x1e, 0x4d, 0xf2, 0xbf, 0xcf, 0x3a, 0x42, 0xca, 0x10, 0x61, 0xca, 0xac, + 0xcb, 0x4a, 0x36, 0x18, 0xe9, 0x13, 0x39, 0xac, 0xd0, 0x7c, 0xff, 0x95, + 0xc6, 0xbe, 0xba, 0xf0, 0x82, 0x9f, 0xa6, 0xdc, 0x36, 0xc8, 0x03, 0xaa, + 0xd1, 0xab, 0xdf, 0x3d, 0xd4, 0x9b, 0xdd, 0xdf, 0x86, 0xda, 0x32, 0x07, + 0xc9, 0x18, 0x3e, 0x2c, 0x4b, 0xa6, 0xbd, 0x8c, 0x85, 0xdc, 0xae, 0x9f, + 0xe2, 0x1d, 0x99, 0x31, 0xbe, 0xd9, 0x7d, 0x1b, 0x0f, 0x69, 0x61, 0x34, + 0xe2, 0xe8, 0xc1, 0xbe, 0x8f, 0xda, 0x4c, 0xf5, 0xce, 0xb6, 0x76, 0xc7, + 0x20, 0xb7, 0x11, 0xf9, 0xfa, 0x6f, 0xc0, 0x6e, 0x22, 0xbc, 0xd0, 0xc1, + 0xdd, 0x41, 0xae, 0xd4, 0x73, 0xde, 0x2a, 0x38, 0x19, 0x05, 0x7b, 0x94, + 0x21, 0x3d, 0xb9, 0xff, 0x41, 0x76, 0xab, 0x7d, 0x0a, 0xc8, 0xb9, 0x0e, + 0x66, 0x33, 0x75, 0x4d, 0x40, 0xe0, 0x0f, 0xde, 0x9a, 0x20, 0x52, 0x8d, + 0x07, 0x75, 0x9a, 0xde, 0xaa, 0x49, 0xd1, 0x61, 0x53, 0x0a, 0x42, 0x12, + 0x5e, 0x83, 0xde, 0xfc, 0xcd, 0xfc, 0x50, 0x38, 0x04, 0x11, 0x9f, 0xb2, + 0x66, 0xe3, 0x41, 0x86, 0x71, 0xb2, 0x47, 0xc6, 0x2c, 0xca, 0x50, 0x44, + 0x41, 0x19, 0x74, 0x28, 0x84, 0x2a, 0x0f, 0xeb, 0x12, 0x41, 0x66, 0x7c, + 0xef, 0xfc, 0x21, 0x17, 0x12, 0xb4, 0x6d, 0x94, 0x79, 0x23, 0xc6, 0x3b, + 0x5f, 0x6a, 0xc3, 0x28, 0x75, 0x8e, 0x83, 0x65, 0x14, 0x39, 0x1e, 0xd0, + 0x9b, 0x34, 0x96, 0x98, 0xcb, 0x89, 0x5d, 0x23, 0x5e, 0xb3, 0x5f, 0x5c, + 0x57, 0xb8, 0x03, 0x94, 0x48, 0x8c, 0xb9, 0xd5, 0x05, 0x3f, 0x5b, 0x42, + 0xa5, 0x4b, 0x05, 0xa7, 0x2c, 0x67, 0xaa, 0x97, 0xca, 0x84, 0x94, 0xa8, + 0x59, 0x03, 0x36, 0x1d, 0xd8, 0xa8, 0x84, 0xdd, 0x9a, 0x5f, 0xef, 0xee, + 0xb3, 0x3b, 0x58, 0x12, 0xe8, 0x92, 0xbc, 0x87, 0xb1, 0x25, 0x0b, 0x6a, + 0xbb, 0x75, 0xa2, 0xa2, 0x36, 0xe2, 0x18, 0xeb, 0xf1, 0xe1, 0xe3, 0x8e, + 0xa2, 0x50, 0xbd, 0xf5, 0xa4, 0xc6, 0x5b, 0xe2, 0x30, 0x7a, 0xb0, 0x13, + 0xe0, 0x1b, 0x9a, 0xa1, 0x10, 0xd0, 0xc4, 0x9b, 0xd4, 0x31, 0x5d, 0x1e, + 0xb6, 0x1a, 0x08, 0x1d, 0xb6, 0xcc, 0xa4, 0xe4, 0xe7, 0x65, 0x4b, 0xc3, + 0xf4, 0xee, 0x0b, 0x38, 0xfb, 0x1f, 0x18, 0xff, 0xcc, 0xc6, 0x38, 0xd5, + 0xac, 0x9b, 0x07, 0xcc, 0xb4, 0x23, 0x87, 0xf4, 0xb1, 0xf9, 0x11, 0x5d, + 0x40, 0xe6, 0x97, 0xac, 0x89, 0x55, 0x63, 0x9a, 0x4a, 0x2f, 0x26, 0x31, + 0x96, 0x1c, 0x02, 0x3a, 0x57, 0xd1, 0x2d, 0xa5, 0xe0, 0x13, 0xbe, 0xfb, + 0x2a, 0xa2, 0xa4, 0x86, 0x7d, 0x45, 0x56, 0x1c, 0x10, 0xed, 0x7a, 0x6a, + 0x5c, 0xd8, 0xe6, 0xf5, 0x83, 0x3e, 0x2d, 0x2b, 0x81, 0xd1, 0x0b, 0x80, + 0x16, 0x06, 0xc0, 0x24, 0xb2, 0x16, 0x79, 0xa2, 0xd1, 0xa2, 0x45, 0x0f, + 0x9f, 0x49, 0x1c, 0xf4, 0xc0, 0x24, 0x7e, 0xce, 0x15, 0x3d, 0x38, 0x55, + 0xbc, 0x57, 0x9a, 0x7b, 0x27, 0x7a, 0x4d, 0x75, 0xb8, 0x6b, 0x12, 0xd3, + 0x56, 0x77, 0x2a, 0x03, 0xd1, 0x72, 0x4f, 0x50, 0x77, 0x7d, 0x15, 0x07, + 0x1d, 0x6b, 0x91, 0xc5, 0x1e, 0x90, 0xb1, 0x82, 0xbb, 0xd0, 0x88, 0x1d, + 0x53, 0xb9, 0x9b, 0x60, 0x2a, 0x3d, 0xfe, 0x84, 0xa8, 0xcb, 0x01, 0x7e, + 0x1f, 0x0c, 0xa3, 0xbe, 0xbc, 0xca, 0x24, 0x4f, 0x49, 0x8a, 0x50, 0xbb, + 0x9e, 0x0d, 0x7f, 0x8c, 0x8e, 0xad, 0xb9, 0x76, 0x7c, 0x8b, 0x13, 0x95, + 0xe1, 0x97, 0xec, 0x9c, 0xa3, 0x33, 0x37, 0xd0, 0x44, 0xfc, 0x9e, 0x92, + 0x98, 0xa2, 0x3e, 0xd6, 0x15, 0x01, 0x5a, 0x73, 0x8d, 0xe5, 0x16, 0x26, + 0xa6, 0xc3, 0x77, 0x88, 0xd5, 0xc9, 0x61, 0x29, 0x21, 0x98, 0x88, 0x39, + 0x8b, 0x4d, 0xb7, 0x58, 0xd1, 0x62, 0x74, 0xa1, 0x47, 0xa0, 0xd4, 0x80, + 0x7e, 0xc3, 0x26, 0x38, 0x94, 0xf1, 0x20, 0xd3, 0x91, 0x76, 0x13, 0x75, + 0x35, 0xa0, 0x73, 0x25, 0x9e, 0x80, 0x5c, 0x70, 0x41, 0x3d, 0x43, 0x2a, + 0x6c, 0xd4, 0x5b, 0xcd, 0xe2, 0x1b, 0xea, 0xd0, 0x02, 0x3f, 0xa0, 0xcf, + 0xd3, 0x89, 0x16, 0x5d, 0x51, 0x9a, 0xe3, 0x55, 0x30, 0xc7, 0x82, 0x3d, + 0xcf, 0x3c, 0x4d, 0xb6, 0x2c, 0x10, 0x6c, 0x30, 0x7b, 0x65, 0xa1, 0x35, + 0x18, 0x4b, 0xbf, 0xf2, 0x14, 0xcb, 0xbb, 0x07, 0xe4, 0x74, 0xe8, 0xcd, + 0x22, 0x85, 0xb9, 0x65, 0x8e, 0xd8, 0x33, 0x28, 0x50, 0xf0, 0x18, 0xbc, + 0x7d, 0x6e, 0xe3, 0xba, 0x73, 0x0b, 0x2f, 0x71, 0x97, 0xc6, 0x30, 0xc3, + 0x50, 0x32, 0xbf, 0x88, 0xa3, 0x8b, 0xbb, 0xe5, 0x91, 0x63, 0xaf, 0xb1, + 0xc6, 0x07, 0x99, 0x6f, 0x1d, 0x6a, 0xfe, 0x2e, 0xa7, 0xfb, 0xa5, 0x08, + 0x45, 0x4d, 0x51, 0xb1, 0xd5, 0xed, 0x8e, 0xcb, 0xff, 0x39, 0x45, 0x9f, + 0xa9, 0x37, 0x40, 0x85, 0xf7, 0x57, 0xeb, 0x4d, 0x1d, 0x19, 0x1a, 0x63, + 0x78, 0xcf, 0x0c, 0xd6, 0xe6, 0xd0, 0x60, 0xeb, 0x1a, 0xfd, 0x9d, 0x09, + 0x57, 0x34, 0x11, 0xef, 0x39, 0x95, 0xf1, 0x98, 0x09, 0xa8, 0x0c, 0x75, + 0x4c, 0xee, 0x5c, 0x97, 0xa7, 0x3c, 0x04, 0x20, 0x0a, 0xc8, 0xba, 0x8c, + 0x21, 0xc7, 0xa8, 0x49, 0xde, 0x04, 0x2a, 0xf2, 0x57, 0x30, 0x7b, 0xf1, + 0xcd, 0x38, 0xfa, 0xb7, 0x8e, 0x88, 0xd1, 0xa2, 0x2b, 0xb5, 0xca, 0xd3, + 0xab, 0x0d, 0x5f, 0x89, 0xc1, 0x65, 0xc2, 0x3a, 0x24, 0x4c, 0x80, 0x61, + 0x83, 0x31, 0xec, 0x67, 0xc3, 0x99, 0x59, 0x76, 0xc3, 0xc9, 0xe2, 0xf5, + 0xbc, 0x47, 0x5b, 0xa2, 0xcd, 0xfe, 0x38, 0x8d, 0x4a, 0xcf, 0xbc, 0x57, + 0x3e, 0xe2, 0xe2, 0x35, 0x9d, 0x89, 0xb8, 0xa6, 0xf3, 0x38, 0x1a, 0xbf, + 0x52, 0x54, 0x9e, 0x94, 0xa5, 0x32, 0xd7, 0xaf, 0xd5, 0x1c, 0x2a, 0x73, + 0x02, 0x8b, 0x6d, 0x28, 0x55, 0xfe, 0x86, 0x38, 0xfa, 0x1c, 0xa7, 0x82, + 0x43, 0x3e, 0x75, 0x44, 0x5c, 0x35, 0x2a, 0x4d, 0x0c, 0xa9, 0xbf, 0x7c, + 0x62, 0x6e, 0x2e, 0x20, 0x7e, 0x92, 0x34, 0x8d, 0xdb, 0x24, 0x67, 0x62, + 0x71, 0xe9, 0x07, 0xa9, 0xe1, 0x5d, 0xfc, 0xb9, 0x31, 0x98, 0x00, 0x14, + 0xec, 0x03, 0xd2, 0x33, 0xcc, 0x8e, 0x4b, 0x2e, 0xb2, 0xda, 0x22, 0xab, + 0x9d, 0xcf, 0x5a, 0x17, 0x59, 0xeb, 0x2a, 0xcb, 0x8b, 0x80, 0x2b, 0x33, + 0xfb, 0x36, 0xa1, 0xed, 0x3a, 0x7a, 0x41, 0x8a, 0xd3, 0x60, 0xce, 0xf9, + 0x1d, 0x4b, 0x3c, 0xb3, 0x4a, 0xb0, 0xaa, 0xd8, 0x4a, 0x48, 0x77, 0x48, + 0x4c, 0x80, 0x4f, 0x14, 0xfb, 0xf6, 0x1c, 0x17, 0xb4, 0x7f, 0x8f, 0x38, + 0xd0, 0x74, 0x3d, 0x11, 0x6b, 0x43, 0xa9, 0x11, 0xfa, 0x0d, 0x3d, 0xc6, + 0x61, 0x55, 0x3c, 0x39, 0x3a, 0xe4, 0x17, 0x4f, 0x4e, 0x4e, 0xe6, 0x28, + 0x38, 0x50, 0xc4, 0x86, 0x92, 0x9d, 0xa2, 0x83, 0x75, 0x4b, 0x5c, 0x13, + 0x42, 0xe5, 0xf4, 0xd9, 0x74, 0x44, 0xce, 0xe8, 0xbe, 0x3e, 0xf1, 0x12, + 0x07, 0xc1, 0x24, 0xf5, 0x14, 0x59, 0x37, 0x8a, 0x08, 0x9b, 0x84, 0x17, + 0x0e, 0x6f, 0xec, 0xe8, 0x01, 0x5d, 0xc2, 0xa7, 0x51, 0x7a, 0x5b, 0xdc, + 0x62, 0xdb, 0x2d, 0x59, 0xd0, 0x72, 0x9b, 0xc9, 0x30, 0x4e, 0xba, 0xa8, + 0x85, 0x81, 0x2f, 0x18, 0x33, 0x50, 0x8f, 0x88, 0x57, 0x92, 0xe0, 0x9d, + 0x0b, 0xf6, 0x9b, 0x31, 0x1d, 0xf8, 0x66, 0xc3, 0xdf, 0x93, 0xe0, 0x33, + 0xe1, 0x1d, 0x3e, 0x6a, 0x8c, 0xd7, 0xed, 0x5c, 0x76, 0xe0, 0x03, 0xd1, + 0x95, 0xb7, 0xbc, 0xba, 0xc3, 0x1c, 0xfe, 0x2d, 0x4f, 0x89, 0xa2, 0xa1, + 0xe2, 0x34, 0x49, 0x33, 0x7a, 0x43, 0xd7, 0x03, 0x6b, 0xdd, 0x86, 0xa5, + 0x9e, 0xf4, 0xf7, 0xc9, 0xea, 0x02, 0x8a, 0x51, 0xa6, 0x80, 0x49, 0xa9, + 0xb7, 0x1d, 0xea, 0x6c, 0x49, 0x72, 0x3d, 0xd1, 0xd4, 0x42, 0xff, 0x74, + 0x43, 0x3b, 0x89, 0x90, 0x85, 0xa9, 0x42, 0x3d, 0x68, 0x22, 0x48, 0xb8, + 0xef, 0x2e, 0x26, 0x42, 0x6e, 0x2e, 0x23, 0x4e, 0xd2, 0xc2, 0x79, 0x48, + 0xcb, 0x31, 0x7d, 0x3c, 0xc1, 0xa3, 0x14, 0x7f, 0x04, 0x63, 0x3e, 0xd7, + 0x7b, 0x2b, 0x92, 0x3c, 0x99, 0x7f, 0x40, 0xa3, 0xbd, 0xa8, 0xa9, 0x42, + 0x0a, 0xe2, 0x6b, 0x3e, 0xaa, 0xe3, 0x42, 0xaa, 0x28, 0xb5, 0x2f, 0x8d, + 0xa4, 0x23, 0x83, 0xb4, 0x7d, 0xe7, 0x6e, 0x8f, 0xbe, 0xe7, 0x27, 0x62, + 0x7e, 0x26, 0x54, 0x27, 0xcb, 0x0b, 0xd2, 0x6d, 0xdc, 0x45, 0x20, 0x2f, + 0xcb, 0xd7, 0x12, 0xc8, 0x7e, 0x2d, 0x74, 0x03, 0x08, 0x0a, 0x9d, 0xe6, + 0xa1, 0x98, 0x8c, 0x3f, 0x90, 0x08, 0x3b, 0x92, 0x78, 0xdb, 0x12, 0xa9, + 0xce, 0x77, 0xa3, 0x79, 0xc6, 0x75, 0x81, 0x09, 0xc7, 0xa1, 0x1c, 0x73, + 0x64, 0xb0, 0xbb, 0x0c, 0xe1, 0x5f, 0x17, 0xfe, 0x25, 0x7b, 0xb4, 0xf3, + 0xca, 0x07, 0x99, 0x6f, 0xd1, 0xdc, 0x66, 0x3e, 0xd0, 0x81, 0x72, 0x07, + 0xd0, 0x0c, 0x92, 0xa7, 0x43, 0x54, 0xbb, 0x26, 0x61, 0xc0, 0x6f, 0xa7, + 0xee, 0x5f, 0xee, 0xaf, 0xd6, 0xc4, 0x83, 0xd3, 0x7c, 0x0b, 0xd6, 0x23, + 0x65, 0x35, 0x60, 0x3d, 0x60, 0x91, 0x70, 0x58, 0xb6, 0x93, 0xb1, 0x59, + 0xc0, 0x7a, 0xe3, 0x9d, 0x4e, 0x8b, 0x3d, 0xc2, 0x69, 0x17, 0x4d, 0x8d, + 0xad, 0x1a, 0xdb, 0xa8, 0xb1, 0xcd, 0x1a, 0x7b, 0x46, 0xd5, 0xcf, 0xce, + 0xaf, 0x8e, 0x76, 0xcd, 0xc7, 0x88, 0x2b, 0xf2, 0x0c, 0x42, 0x32, 0x1d, + 0x3d, 0x01, 0x82, 0x47, 0x2d, 0xc1, 0x7c, 0x45, 0xac, 0x81, 0xbd, 0x3d, + 0x1e, 0x5f, 0x4a, 0xcc, 0xe6, 0x29, 0x74, 0x33, 0x53, 0x99, 0x2b, 0x15, + 0xef, 0xcc, 0x08, 0xb0, 0x2d, 0xd2, 0xba, 0x3a, 0xad, 0x2d, 0xd3, 0x12, + 0x9d, 0xb6, 0x2e, 0xd3, 0x02, 0xce, 0x87, 0x22, 0x79, 0x83, 0xeb, 0xda, + 0xc9, 0xdf, 0x19, 0x16, 0x03, 0x51, 0x26, 0xa2, 0x44, 0xe1, 0xda, 0x9c, + 0xb1, 0xe7, 0x00, 0x1c, 0x5f, 0x47, 0x64, 0x99, 0x76, 0x6f, 0x5e, 0xa4, + 0xfb, 0xff, 0xc0, 0x6d, 0xbb, 0x04, 0x03, 0xfd, 0xa5, 0x87, 0xdc, 0x47, + 0x3a, 0x71, 0x7c, 0xa4, 0x49, 0xa9, 0x1f, 0xa1, 0x36, 0xff, 0x3a, 0x20, + 0xf5, 0xbf, 0x48, 0x80, 0x7e, 0x7d, 0x30, 0x7d, 0x7d, 0xca, 0xdb, 0x76, + 0x15, 0xad, 0xe6, 0x66, 0xb7, 0x3f, 0xac, 0xe6, 0x27, 0x9d, 0xe9, 0xfd, + 0x52, 0x3c, 0xe3, 0xe6, 0xce, 0x1e, 0xa1, 0x57, 0x2a, 0x9e, 0x42, 0x38, + 0x1f, 0x1f, 0x31, 0x7f, 0x4c, 0x1b, 0xb3, 0x10, 0xb0, 0x7e, 0x54, 0xf7, + 0x77, 0xa2, 0x89, 0x72, 0xc8, 0xa7, 0xeb, 0x57, 0xfd, 0x8c, 0x3f, 0xa1, + 0x02, 0x28, 0xdd, 0xe3, 0x3d, 0x18, 0xf8, 0x4b, 0x7a, 0x0f, 0xb4, 0xc5, + 0xa5, 0xc6, 0xc3, 0xee, 0x69, 0xa8, 0x65, 0x1c, 0xf7, 0xaa, 0x06, 0x37, + 0xea, 0xf1, 0xbb, 0x54, 0xc3, 0xf8, 0x9e, 0x37, 0x76, 0x3e, 0x11, 0x24, + 0x32, 0x94, 0x95, 0xc5, 0x72, 0x20, 0xc8, 0x4d, 0x30, 0x49, 0xd1, 0x85, + 0x36, 0x10, 0x4f, 0x22, 0x07, 0x43, 0x47, 0x36, 0x84, 0xbe, 0x02, 0x11, + 0x7d, 0xca, 0xa9, 0xc3, 0xb0, 0x8e, 0x36, 0xc6, 0x68, 0x20, 0x4d, 0x8e, + 0xbe, 0x45, 0xf9, 0x78, 0x4e, 0x89, 0x75, 0x7a, 0xdb, 0xfe, 0x01, 0x7f, + 0xcd, 0xb0, 0xec, 0x29, 0xde, 0x4e, 0x13, 0x57, 0x8b, 0x60, 0x8a, 0x5f, + 0x3f, 0xd4, 0xd8, 0xec, 0x43, 0x6e, 0x83, 0x84, 0xd2, 0xb7, 0x74, 0xf1, + 0x0f, 0x3f, 0xdd, 0x47, 0xfd, 0xec, 0x56, 0x5c, 0x42, 0x40, 0xff, 0x30, + 0xec, 0x19, 0x9f, 0xfa, 0x0a, 0x8e, 0xac, 0x2f, 0x2a, 0x61, 0x87, 0x79, + 0x2d, 0x58, 0xc4, 0x26, 0xd1, 0x43, 0xe8, 0xca, 0x97, 0x22, 0xba, 0x72, + 0x10, 0xa5, 0x5e, 0x70, 0x9c, 0x78, 0x09, 0x3e, 0xb9, 0x2d, 0x4c, 0xe6, + 0x69, 0x16, 0xf4, 0x3e, 0x29, 0xf3, 0x2e, 0xdd, 0x92, 0x4a, 0xfa, 0xfe, + 0x67, 0xa0, 0x4e, 0xe2, 0x7b, 0xf1, 0x1c, 0x8c, 0x0f, 0xaa, 0xbc, 0x39, + 0x39, 0xd0, 0x9a, 0x68, 0xc6, 0xa1, 0x17, 0x00, 0x7d, 0x26, 0xee, 0x5f, + 0x90, 0xff, 0x5e, 0x0e, 0x6c, 0xee, 0xba, 0xfd, 0x42, 0xca, 0xd1, 0x43, + 0x4e, 0x01, 0x2e, 0xe6, 0x9a, 0x6c, 0xd7, 0xbc, 0xca, 0x1e, 0x95, 0xff, + 0x80, 0x44, 0x2b, 0x7a, 0x40, 0x6a, 0x87, 0x5a, 0x68, 0x5a, 0xb7, 0xa1, + 0x60, 0x25, 0x88, 0x46, 0x78, 0xd4, 0xf4, 0xe2, 0xc4, 0x6b, 0x70, 0x6e, + 0x3a, 0x15, 0x25, 0x25, 0x4d, 0xc4, 0x3b, 0x52, 0x89, 0xc0, 0x2e, 0x76, + 0x2e, 0x79, 0x61, 0xaa, 0xe7, 0x56, 0x8b, 0xc6, 0xe0, 0x1d, 0x40, 0x21, + 0xc7, 0xc1, 0xba, 0x30, 0x5e, 0xf9, 0xef, 0xd1, 0x68, 0x04, 0xc4, 0x2e, + 0x97, 0x59, 0xb5, 0xdc, 0x0a, 0xf2, 0xce, 0x0c, 0xc5, 0xff, 0xb2, 0xc6, + 0x10, 0xc6, 0x29, 0x33, 0x2c, 0x03, 0x66, 0x9e, 0x62, 0x8d, 0x94, 0xc5, + 0x13, 0x34, 0xa3, 0x8d, 0xe3, 0xb1, 0x98, 0x3a, 0x51, 0xd8, 0x87, 0xfd, + 0x92, 0x6e, 0x7c, 0xa1, 0x8b, 0x21, 0x7f, 0xba, 0xba, 0x05, 0x0b, 0xba, + 0x03, 0x49, 0x82, 0x10, 0x8d, 0xa1, 0xd2, 0x50, 0xd6, 0xcf, 0x55, 0x6f, + 0x63, 0x75, 0x07, 0xef, 0xf5, 0x42, 0xbc, 0xe5, 0xa3, 0xf9, 0x0d, 0x12, + 0x65, 0xd0, 0xf2, 0x1e, 0x71, 0x30, 0xea, 0xa9, 0x81, 0x3d, 0x9a, 0xa2, + 0x33, 0x96, 0x39, 0x30, 0x37, 0x0a, 0x61, 0xea, 0x99, 0xe5, 0x00, 0xd5, + 0x5a, 0x03, 0x1f, 0x33, 0xba, 0x0d, 0x6c, 0x9b, 0x0d, 0xd0, 0x4c, 0x13, + 0x2e, 0xa0, 0x36, 0xaf, 0xfa, 0x59, 0xd2, 0xee, 0x4c, 0x01, 0xfb, 0xbb, + 0x2d, 0xee, 0xcc, 0x6b, 0x51, 0xf0, 0x51, 0xa9, 0xe6, 0x76, 0x4a, 0x34, + 0xd7, 0x56, 0x73, 0x25, 0x47, 0xc1, 0x0a, 0x1f, 0x5f, 0xee, 0xbe, 0x61, + 0x12, 0x51, 0x02, 0x38, 0xc7, 0x5b, 0xb7, 0x27, 0x8c, 0x17, 0x60, 0x9d, + 0x2b, 0x07, 0x70, 0x21, 0x9b, 0x56, 0x52, 0xee, 0x23, 0x63, 0x0d, 0x0c, + 0x01, 0x1b, 0x4a, 0x10, 0x05, 0x20, 0xdb, 0xc6, 0xdc, 0xa2, 0xed, 0x97, + 0x83, 0x25, 0x34, 0xf9, 0x9a, 0xca, 0x97, 0x32, 0xf2, 0x21, 0xd1, 0x0f, + 0xae, 0xd1, 0xf2, 0xe5, 0x6e, 0x0c, 0x6d, 0x63, 0xda, 0xb9, 0xb0, 0x24, + 0x80, 0x79, 0x35, 0xdb, 0x6e, 0x4d, 0xa7, 0x71, 0x7f, 0xdd, 0xf5, 0xff, + 0x0f, 0x7b, 0xdf, 0xd2, 0xe3, 0x46, 0x92, 0x1c, 0x7c, 0xef, 0x5f, 0x51, + 0x12, 0x06, 0x43, 0x12, 0x62, 0x77, 0x93, 0x6c, 0x3d, 0x9b, 0x92, 0x06, + 0x7a, 0xb4, 0x76, 0x84, 0x6d, 0x8d, 0x7a, 0xd4, 0xda, 0xd1, 0xee, 0x37, + 0xa3, 0x1d, 0x55, 0x15, 0x8b, 0xcd, 0x1a, 0x91, 0x2c, 0x2e, 0xab, 0xd8, + 0xcd, 0x5a, 0x4d, 0x0f, 0x3e, 0xf8, 0x60, 0x60, 0x01, 0x63, 0x61, 0x18, + 0x03, 0xdb, 0x07, 0x1f, 0x0c, 0xd8, 0xbe, 0xf9, 0x60, 0x03, 0x06, 0x0c, + 0xf8, 0x71, 0xf1, 0x1f, 0xf0, 0x7f, 0x98, 0x5f, 0xe2, 0x8c, 0x88, 0x7c, + 0x57, 0x66, 0x91, 0xfd, 0xd0, 0x3c, 0x30, 0x3b, 0xf0, 0x5a, 0xcd, 0xca, + 0xc8, 0xc8, 0xcc, 0xc8, 0x88, 0xc8, 0x88, 0xc8, 0xcc, 0x48, 0x87, 0x7e, + 0xaa, 0x1b, 0x04, 0x2c, 0xd4, 0xb5, 0xc3, 0xd8, 0xd1, 0x86, 0xe1, 0x40, + 0xa8, 0xb0, 0xd4, 0x55, 0xef, 0x39, 0xaa, 0x57, 0xba, 0x51, 0x45, 0x70, + 0x1f, 0x30, 0xc8, 0xfb, 0x77, 0x5c, 0x45, 0xaa, 0x63, 0x86, 0x60, 0xde, + 0xec, 0x1f, 0x78, 0x4e, 0x99, 0x48, 0x7b, 0x24, 0xe1, 0x06, 0xca, 0x79, + 0xfd, 0x83, 0x42, 0xb8, 0x40, 0xf4, 0xf8, 0xc7, 0x1a, 0x0e, 0xc2, 0x0b, + 0xcb, 0x41, 0x20, 0x04, 0x97, 0xe4, 0x25, 0x98, 0x1e, 0xc2, 0x9c, 0x7a, + 0xc5, 0xd4, 0x23, 0x2e, 0x24, 0xef, 0xc3, 0x4d, 0xe0, 0x4d, 0xac, 0xe9, + 0x2a, 0xb8, 0x77, 0xdf, 0x0b, 0x15, 0xbd, 0x58, 0xf3, 0x5c, 0x1e, 0x93, + 0xdd, 0x3d, 0xd8, 0xdd, 0x92, 0x26, 0x1a, 0x61, 0x10, 0x99, 0xae, 0xc3, + 0x00, 0xec, 0xc2, 0xb1, 0x3a, 0x83, 0xe7, 0xf0, 0xca, 0x0f, 0x2f, 0x70, + 0xec, 0xed, 0xd3, 0xf5, 0xce, 0xbb, 0x79, 0x8e, 0xb9, 0xd5, 0xb6, 0xec, + 0x3d, 0xdf, 0xb6, 0xa2, 0x4d, 0xaa, 0xa7, 0x0e, 0xb5, 0x49, 0x63, 0xcc, + 0x7b, 0xba, 0xcd, 0xe3, 0xf4, 0xc9, 0xa3, 0x6d, 0x4f, 0x88, 0x76, 0x67, + 0x88, 0x42, 0x69, 0xf3, 0x78, 0x12, 0xce, 0xe1, 0x88, 0xc9, 0x26, 0xdc, + 0xb9, 0x0f, 0x8e, 0xe1, 0xf0, 0x12, 0x8f, 0xa4, 0xbc, 0x7a, 0xf8, 0x99, + 0x37, 0x16, 0xc5, 0x26, 0x9e, 0xe8, 0x9b, 0x0d, 0x87, 0x36, 0xe1, 0xda, + 0x40, 0x06, 0x06, 0x40, 0xf2, 0x3e, 0xb6, 0xcd, 0xa8, 0x1b, 0x0c, 0xe0, + 0x26, 0xfb, 0xdf, 0x2d, 0xf6, 0x3f, 0x06, 0x75, 0x9b, 0xef, 0xce, 0x1d, + 0x8d, 0x7c, 0xbe, 0xed, 0x2b, 0xea, 0x20, 0xdc, 0xc0, 0xff, 0x8c, 0xba, + 0xb7, 0xfe, 0x38, 0x17, 0x6a, 0x9c, 0x13, 0xcc, 0x93, 0x53, 0x1d, 0xe6, + 0x33, 0xdf, 0x30, 0xcf, 0x3b, 0xc0, 0x0e, 0x03, 0x38, 0xf3, 0x20, 0x29, + 0x8b, 0xcf, 0x59, 0xc7, 0x68, 0x6b, 0xb9, 0x59, 0x5f, 0x7d, 0x9b, 0x7d, + 0x10, 0x1c, 0xf3, 0x88, 0x08, 0x1c, 0xb2, 0x71, 0x47, 0x40, 0x5e, 0x3c, + 0x30, 0xe3, 0x1f, 0xad, 0x73, 0xaa, 0x36, 0xf3, 0x89, 0x4f, 0xbe, 0x85, + 0x0c, 0x67, 0x7f, 0x2c, 0x7c, 0xe6, 0x4b, 0xa0, 0x90, 0xb9, 0x92, 0xbf, + 0xc5, 0x6a, 0xa4, 0xdd, 0x9e, 0xb9, 0xc0, 0x24, 0xb6, 0xcb, 0xd0, 0x85, + 0x31, 0x23, 0xc9, 0xd9, 0x54, 0xe0, 0x01, 0x58, 0x46, 0x6c, 0x00, 0x40, + 0x91, 0x00, 0x49, 0xd2, 0x08, 0xb8, 0xad, 0xcc, 0xf3, 0xfe, 0x3f, 0x49, + 0x21, 0x75, 0x43, 0xa0, 0xd0, 0x02, 0x85, 0xf7, 0x9e, 0xbc, 0xa0, 0x15, + 0xa4, 0x67, 0x85, 0x98, 0xcc, 0xd3, 0xda, 0x74, 0x99, 0x68, 0x9c, 0x0c, + 0x0b, 0x7e, 0xa3, 0xa8, 0x3f, 0x07, 0x63, 0x4c, 0xf8, 0x93, 0x8f, 0xf1, + 0xa1, 0x5d, 0x22, 0x47, 0x9c, 0x31, 0xdf, 0x2a, 0x9d, 0xe2, 0x2b, 0xa3, + 0x4c, 0x53, 0x84, 0xcc, 0x37, 0xc6, 0x76, 0xe5, 0xac, 0x60, 0x3b, 0x21, + 0xbc, 0xdf, 0x0b, 0x30, 0x84, 0x20, 0x85, 0x93, 0x44, 0x0f, 0xa6, 0x25, + 0x66, 0x67, 0x02, 0x2c, 0xe2, 0x01, 0x5c, 0x38, 0xf9, 0x90, 0x40, 0x44, + 0x91, 0x39, 0x3d, 0xd9, 0xa2, 0xc8, 0x61, 0x73, 0x9b, 0x2b, 0x71, 0xc2, + 0x2b, 0xfc, 0x73, 0x8e, 0x1c, 0xb6, 0xef, 0x24, 0xa0, 0x6a, 0x92, 0xee, + 0xb4, 0x32, 0x64, 0x47, 0xc9, 0x34, 0x99, 0x87, 0x98, 0x65, 0x98, 0xf5, + 0x42, 0x7a, 0x86, 0x0a, 0x52, 0x3f, 0x94, 0x11, 0x08, 0x9a, 0xc9, 0x62, + 0x22, 0x06, 0xdf, 0x1e, 0x29, 0x18, 0x9b, 0x16, 0x62, 0xdf, 0x2f, 0xcc, + 0x83, 0xab, 0x6c, 0xc9, 0xd9, 0xcc, 0x47, 0x59, 0x71, 0x55, 0xe4, 0x19, + 0xc2, 0x31, 0xe9, 0x27, 0x82, 0x0a, 0x78, 0x31, 0x19, 0x50, 0x88, 0x27, + 0x77, 0x8d, 0xe3, 0xe0, 0xdc, 0x73, 0x8d, 0xf9, 0x49, 0x4d, 0x41, 0x03, + 0xcd, 0xa9, 0x60, 0x5e, 0x0c, 0x9d, 0x5a, 0x33, 0x26, 0x07, 0x90, 0x89, + 0x03, 0x5b, 0xe0, 0xc2, 0x40, 0x08, 0x62, 0x2c, 0x9f, 0x0b, 0xa6, 0xc4, + 0x2e, 0x29, 0xab, 0x16, 0x01, 0x49, 0xe8, 0xed, 0xca, 0x2d, 0x0c, 0xda, + 0xec, 0xed, 0xbf, 0x10, 0x83, 0x89, 0x43, 0x71, 0xe6, 0x2b, 0x86, 0xa5, + 0x00, 0x50, 0x40, 0x68, 0x35, 0x5b, 0xe4, 0x1a, 0x71, 0xf0, 0x41, 0x65, + 0xea, 0x8b, 0xf3, 0x01, 0x7d, 0x64, 0x34, 0xa2, 0xd9, 0x19, 0xb9, 0x37, + 0x67, 0x6e, 0x91, 0xdc, 0x94, 0x14, 0xa8, 0x75, 0x26, 0x44, 0x7b, 0x67, + 0xef, 0xd3, 0x97, 0x07, 0x5a, 0x2e, 0xbb, 0x74, 0xc8, 0xb7, 0x19, 0xc3, + 0xe0, 0x6a, 0xe7, 0xaa, 0x8a, 0x80, 0x83, 0x4a, 0xbb, 0x0a, 0x67, 0x8e, + 0x60, 0x8e, 0xb9, 0x0d, 0x99, 0x8b, 0x64, 0x0c, 0x6c, 0x85, 0xc3, 0xfd, + 0xac, 0x36, 0x27, 0xd8, 0x48, 0x06, 0x85, 0xd4, 0x19, 0x99, 0x64, 0x9c, + 0xc6, 0x70, 0xa4, 0x2c, 0x54, 0xaf, 0xcb, 0x0a, 0xb7, 0x05, 0x42, 0x5f, + 0x98, 0x92, 0xee, 0x64, 0x94, 0x89, 0x2b, 0x08, 0xfa, 0x3b, 0xd9, 0x09, + 0x73, 0x6c, 0xd2, 0x48, 0x44, 0x00, 0x68, 0x1c, 0x7a, 0xbc, 0x87, 0xe9, + 0x59, 0x28, 0xa2, 0x33, 0x78, 0xd0, 0xfb, 0x29, 0x73, 0x84, 0xe0, 0x4a, + 0x33, 0x1d, 0x59, 0xe9, 0x29, 0x2d, 0x33, 0x25, 0x1d, 0x7f, 0x77, 0x93, + 0x1f, 0xde, 0x48, 0x8b, 0xd2, 0x55, 0x48, 0x5e, 0x51, 0x94, 0xea, 0x69, + 0xad, 0x54, 0x69, 0x0f, 0x9d, 0xb5, 0x62, 0x1e, 0x4e, 0x73, 0x48, 0x8f, + 0xb7, 0x73, 0x7b, 0xeb, 0xfa, 0xdb, 0x20, 0x0a, 0x17, 0x03, 0x3f, 0xb0, + 0x48, 0x03, 0x59, 0x0f, 0x1b, 0xe3, 0xfe, 0x0d, 0x23, 0x69, 0x91, 0xce, + 0xc6, 0xa9, 0x1e, 0x4b, 0x99, 0xd2, 0x12, 0xcc, 0x60, 0x0e, 0x5f, 0x1e, + 0x04, 0xc3, 0x71, 0x78, 0xe4, 0xde, 0x18, 0x14, 0x3b, 0xb7, 0x8a, 0x78, + 0xeb, 0x73, 0x0a, 0xdf, 0x70, 0x91, 0x36, 0xb2, 0x88, 0x37, 0xec, 0xd1, + 0xcb, 0x6c, 0xb8, 0x70, 0x3e, 0x78, 0xb4, 0xe7, 0xdc, 0xa4, 0x12, 0x2e, + 0xc0, 0x1c, 0x4f, 0xdf, 0xc1, 0x8d, 0x70, 0x21, 0x60, 0xed, 0x00, 0x4e, + 0x67, 0xcc, 0xec, 0xe3, 0x35, 0xdd, 0xf3, 0x55, 0x23, 0x13, 0x4d, 0x09, + 0x4f, 0x93, 0xd9, 0x72, 0x71, 0xe1, 0xb9, 0xa2, 0x84, 0xe3, 0xa1, 0x41, + 0xf0, 0x31, 0xac, 0x45, 0x8c, 0xb8, 0x6f, 0x2d, 0x84, 0x1f, 0x04, 0x4b, + 0xea, 0xc4, 0x13, 0x10, 0x78, 0xe7, 0xa2, 0xfa, 0x44, 0x38, 0x0d, 0xb6, + 0xca, 0x0f, 0xf0, 0x89, 0x68, 0xae, 0xc5, 0xe5, 0x56, 0x16, 0x1b, 0xec, + 0x22, 0xb7, 0xd7, 0xc9, 0x35, 0xd6, 0xdd, 0xcb, 0x58, 0x06, 0x99, 0x8a, + 0x1f, 0xaf, 0xb5, 0x69, 0x80, 0x87, 0xed, 0xed, 0x5d, 0x83, 0xc2, 0xb1, + 0x6b, 0x30, 0x76, 0xec, 0x1a, 0x44, 0x8e, 0x5d, 0x83, 0x1f, 0xe7, 0x96, + 0x81, 0xd8, 0x2c, 0xe8, 0xbc, 0x6e, 0x07, 0x87, 0x05, 0xdc, 0x48, 0xdf, + 0x02, 0xb6, 0x84, 0x8d, 0xb7, 0x47, 0x90, 0x72, 0x25, 0x1e, 0xb5, 0x2e, + 0xb6, 0x8b, 0xd0, 0xad, 0xdf, 0x45, 0xd8, 0x79, 0xed, 0xba, 0x14, 0xb6, + 0x60, 0xa6, 0xc6, 0xef, 0x0d, 0x53, 0x43, 0xbc, 0x55, 0x4f, 0x31, 0x13, + 0x50, 0xb9, 0x4d, 0x5a, 0x6d, 0x5a, 0x75, 0x67, 0x19, 0xac, 0x73, 0xc8, + 0xae, 0x0d, 0x50, 0x81, 0x58, 0x86, 0xed, 0xeb, 0xf7, 0xfa, 0x39, 0x74, + 0xcd, 0xa1, 0x39, 0x0b, 0x04, 0xfb, 0x02, 0x9e, 0x23, 0xad, 0x93, 0x78, + 0xe2, 0x78, 0x6a, 0x9f, 0xd2, 0x74, 0x9e, 0x78, 0xe6, 0x87, 0xe6, 0x2b, + 0x46, 0x50, 0xb0, 0x98, 0xa6, 0x74, 0x8a, 0x82, 0xaf, 0xc8, 0xc2, 0xe0, + 0x00, 0xfc, 0xb5, 0x07, 0x0b, 0xfd, 0x47, 0x3b, 0x16, 0x52, 0xc3, 0x9a, + 0x8f, 0xf7, 0x8b, 0xdb, 0x3e, 0xb4, 0xa3, 0xc7, 0xe5, 0x97, 0x2d, 0xe7, + 0x7a, 0x50, 0x7e, 0x21, 0x35, 0xf8, 0x00, 0x1f, 0x45, 0x0f, 0x66, 0xa3, + 0x32, 0xc7, 0x47, 0x7d, 0xed, 0xf0, 0xfd, 0x82, 0x88, 0x04, 0xba, 0xde, + 0x46, 0xe6, 0x5d, 0xfb, 0x39, 0x39, 0xd5, 0xbc, 0xd7, 0xc8, 0xec, 0x71, + 0x38, 0xd6, 0x85, 0x16, 0x9e, 0x5b, 0xef, 0x6f, 0xc8, 0x8c, 0x3c, 0x66, + 0x2a, 0x90, 0x63, 0xca, 0xb6, 0xcc, 0xcb, 0x98, 0x47, 0x2c, 0xe6, 0x8d, + 0x17, 0x79, 0x9d, 0x8e, 0x0f, 0x24, 0x67, 0xe2, 0x26, 0xb9, 0x53, 0x21, + 0xee, 0x5d, 0xc2, 0x36, 0xeb, 0x65, 0x68, 0x3b, 0xdc, 0x5c, 0xff, 0x7e, + 0xf7, 0x48, 0x9d, 0x9a, 0x4d, 0x5e, 0x60, 0xc2, 0x52, 0x54, 0xad, 0xa4, + 0xb9, 0xb0, 0x83, 0xb0, 0xe6, 0x36, 0x5b, 0xfc, 0xde, 0x92, 0x7c, 0x16, + 0xfe, 0xa3, 0xef, 0x5f, 0x1b, 0x42, 0xff, 0x2e, 0xa0, 0xea, 0xce, 0xb8, + 0x61, 0x7a, 0x30, 0x61, 0x23, 0x7e, 0x27, 0xdc, 0x75, 0xb4, 0x3e, 0x04, + 0x0f, 0x72, 0x2e, 0xa5, 0x30, 0xe1, 0xde, 0x1a, 0x2a, 0xce, 0xb1, 0x4f, + 0xa8, 0x6f, 0x11, 0x72, 0x87, 0xc2, 0xde, 0x27, 0x24, 0x0d, 0x98, 0x4d, + 0xe9, 0x5c, 0x20, 0x9c, 0xb8, 0x47, 0x43, 0x64, 0x39, 0x43, 0x63, 0x35, + 0x60, 0xe6, 0xa8, 0x7c, 0x44, 0x85, 0x9b, 0xcb, 0x9f, 0xee, 0x1f, 0x28, + 0xbd, 0xa8, 0xfd, 0x27, 0x53, 0xe6, 0x4a, 0xe5, 0x89, 0x37, 0x4b, 0xc3, + 0x71, 0x9e, 0x81, 0x1f, 0x20, 0x1d, 0x00, 0xa7, 0x87, 0xe5, 0x52, 0xb4, + 0xa4, 0xcd, 0x44, 0x92, 0x21, 0xbc, 0xa4, 0x8d, 0x26, 0x27, 0x0e, 0xce, + 0x79, 0xce, 0x7e, 0x90, 0xf1, 0xd3, 0x93, 0xeb, 0x57, 0xdc, 0x71, 0x34, + 0xb5, 0x98, 0xf9, 0xe1, 0xaf, 0xfb, 0x1b, 0xb2, 0xab, 0xb9, 0x63, 0x1e, + 0x7c, 0x7e, 0x55, 0x3e, 0xa2, 0x33, 0x06, 0x3c, 0x3e, 0x30, 0xf9, 0x05, + 0x6c, 0xea, 0x1a, 0x2d, 0x74, 0x78, 0x61, 0x35, 0xe4, 0xb5, 0x2b, 0x59, + 0xcb, 0x7b, 0x6b, 0xe9, 0x16, 0x7b, 0x71, 0x6f, 0x04, 0x5f, 0x8b, 0xa0, + 0x34, 0x79, 0x66, 0x82, 0xe5, 0xe5, 0xbb, 0xed, 0x36, 0x9f, 0xd5, 0x1f, + 0x91, 0x77, 0x31, 0x75, 0x9b, 0xf1, 0x90, 0xb9, 0x8c, 0x49, 0x6f, 0x45, + 0x06, 0x5f, 0xe1, 0xe8, 0xdf, 0x8b, 0x03, 0x73, 0x05, 0x15, 0x6b, 0xe8, + 0xd6, 0x06, 0xfd, 0x66, 0xae, 0x71, 0xd5, 0xec, 0x18, 0x31, 0xb7, 0x3c, + 0x82, 0x7d, 0x26, 0xb1, 0xbe, 0x43, 0x4a, 0x68, 0xee, 0xf9, 0xb6, 0xe5, + 0xfe, 0xc0, 0x78, 0x2c, 0x78, 0x9c, 0xc4, 0x8a, 0xdf, 0x93, 0xe2, 0xad, + 0x9a, 0x58, 0xc5, 0x35, 0x03, 0xce, 0x50, 0xe0, 0x7c, 0x32, 0xb1, 0xa1, + 0xfa, 0x2a, 0xb8, 0xa0, 0x92, 0x32, 0x33, 0x56, 0x83, 0xc9, 0x44, 0xd6, + 0xa6, 0xa8, 0x00, 0x3f, 0xe5, 0x5f, 0xb2, 0xce, 0x1d, 0x27, 0xd8, 0x3b, + 0x3d, 0xe4, 0xac, 0xb7, 0xce, 0xb4, 0x09, 0x86, 0xe7, 0x30, 0x33, 0xe8, + 0x8a, 0xa8, 0x08, 0xe1, 0x70, 0x06, 0x5c, 0xda, 0xd0, 0xa2, 0xfd, 0x31, + 0x57, 0xcd, 0x8b, 0x96, 0x09, 0x85, 0x6a, 0x7e, 0xef, 0xc9, 0x0b, 0x41, + 0x5c, 0xda, 0xd3, 0x05, 0xa6, 0x48, 0xb4, 0x08, 0x53, 0x1f, 0x1c, 0x06, + 0x08, 0xe5, 0x05, 0x1f, 0xb2, 0x7a, 0x1b, 0xee, 0xc0, 0x11, 0x0e, 0xba, + 0x4f, 0xd4, 0xe8, 0xc3, 0xb5, 0xfe, 0x18, 0x2f, 0xa0, 0xf6, 0x21, 0x5e, + 0xf6, 0xba, 0x8e, 0x6b, 0xb0, 0xa2, 0xe2, 0x96, 0x44, 0xaa, 0x40, 0x41, + 0x85, 0xc5, 0x34, 0x3c, 0x0e, 0xd3, 0x31, 0x2e, 0xb2, 0xe8, 0x24, 0xd3, + 0x05, 0x22, 0xcd, 0x1b, 0xcf, 0x21, 0x55, 0x98, 0x81, 0x41, 0xe8, 0x2b, + 0x62, 0xe7, 0x4d, 0xce, 0x02, 0x22, 0xc1, 0x2a, 0x8d, 0x1b, 0xf8, 0xd9, + 0xac, 0x45, 0x3a, 0x0b, 0xc2, 0x5f, 0xba, 0xaa, 0x32, 0x61, 0x76, 0x2a, + 0x30, 0xba, 0x00, 0x27, 0x52, 0x21, 0x4d, 0xd2, 0xc1, 0x80, 0x75, 0xd8, + 0x8b, 0xe7, 0x86, 0x03, 0xca, 0xc6, 0x44, 0xe7, 0x1f, 0xe6, 0xe4, 0xf9, + 0xfb, 0x10, 0xdd, 0xaa, 0x02, 0xd9, 0x78, 0x28, 0xee, 0xfb, 0xec, 0xba, + 0x1f, 0xc9, 0x1d, 0x0b, 0xc2, 0xc6, 0xd0, 0xb5, 0xe6, 0x44, 0x84, 0xde, + 0x6c, 0x76, 0xe3, 0xb5, 0xde, 0xbc, 0x21, 0x3c, 0x8d, 0x86, 0x79, 0x4d, + 0x2a, 0x84, 0x00, 0xc6, 0x24, 0xcc, 0xdf, 0x06, 0xf0, 0xd0, 0x52, 0x4c, + 0x61, 0x1a, 0xba, 0x7d, 0x42, 0x15, 0xb4, 0x9c, 0x11, 0x81, 0xb8, 0xcf, + 0xa8, 0x78, 0x23, 0x92, 0x06, 0xf1, 0x34, 0x93, 0x15, 0xcc, 0xc1, 0x44, + 0x8c, 0x47, 0xc9, 0xee, 0xad, 0x21, 0x1b, 0x00, 0x91, 0xc9, 0x5b, 0x37, + 0x4b, 0x00, 0x75, 0x1d, 0xa1, 0xfc, 0x1c, 0x01, 0x30, 0xb7, 0x11, 0xc6, + 0x49, 0xdd, 0x37, 0x6f, 0x98, 0x24, 0x30, 0x22, 0x80, 0x6a, 0x78, 0xf3, + 0x86, 0x24, 0x42, 0xa7, 0x89, 0x3a, 0x6b, 0x65, 0x85, 0x53, 0xb5, 0xb3, + 0x2c, 0x76, 0x78, 0x50, 0x9c, 0x98, 0xd7, 0x77, 0x3d, 0xdb, 0xfc, 0x19, + 0xa6, 0x01, 0xc4, 0x27, 0x1f, 0x1c, 0x3e, 0x7a, 0xfa, 0x34, 0xf0, 0xa4, + 0x4f, 0x00, 0xa7, 0xe6, 0xcd, 0x1b, 0x10, 0x4a, 0x7b, 0x6e, 0x60, 0xf9, + 0x34, 0x6e, 0x54, 0xb5, 0xf9, 0xee, 0x2e, 0x45, 0x14, 0xcd, 0xe0, 0x63, + 0x5d, 0xa4, 0x87, 0x2b, 0x52, 0xb9, 0x76, 0xac, 0xb5, 0x08, 0x05, 0x13, + 0xd8, 0x27, 0x39, 0x85, 0xdf, 0x4f, 0xf1, 0x3e, 0x0e, 0xfb, 0x94, 0xf3, + 0x4b, 0xec, 0xf0, 0x7c, 0x8c, 0x95, 0xe2, 0x80, 0x89, 0xef, 0xd3, 0x47, + 0xae, 0xf0, 0xc6, 0x65, 0x18, 0xe8, 0x74, 0x21, 0x88, 0xda, 0x36, 0x0c, + 0x82, 0x9a, 0xeb, 0xe8, 0x9a, 0x75, 0x5e, 0x4d, 0x16, 0x00, 0xb7, 0x71, + 0xf4, 0x74, 0x01, 0x1e, 0x33, 0x5b, 0xb3, 0xb2, 0x09, 0x38, 0x75, 0x26, + 0x0c, 0x78, 0x67, 0x1a, 0xd0, 0xaa, 0xb9, 0x9a, 0x74, 0xad, 0x64, 0x89, + 0xa7, 0xaf, 0x8d, 0x4c, 0x34, 0x4b, 0x30, 0xde, 0x31, 0xf1, 0x4c, 0x3c, + 0x92, 0xa9, 0xc9, 0x4c, 0xf0, 0x99, 0xc8, 0xe0, 0xa0, 0xd9, 0xdf, 0x15, + 0xe3, 0xbb, 0x3a, 0x8f, 0xdf, 0xc0, 0x6f, 0x9e, 0x13, 0x7d, 0xd5, 0x3c, + 0x3e, 0xb6, 0xe7, 0xf1, 0xb2, 0xa6, 0x91, 0xf2, 0x00, 0xfc, 0x0c, 0xa6, + 0xb1, 0xad, 0xa5, 0x9d, 0xb3, 0xa6, 0x6f, 0x91, 0x8f, 0x9a, 0x72, 0x72, + 0x57, 0xcc, 0x20, 0x25, 0x00, 0x3b, 0xc0, 0xf4, 0x6d, 0xdb, 0x64, 0xcb, + 0x6e, 0x7f, 0x96, 0xe6, 0x8b, 0x70, 0xcc, 0x7e, 0x85, 0x73, 0x36, 0x64, + 0xdc, 0x07, 0xa6, 0xb4, 0x60, 0xce, 0xd0, 0x00, 0x1b, 0xf4, 0x01, 0x4f, + 0x93, 0x6b, 0x53, 0x5b, 0x4b, 0x0d, 0x67, 0x3c, 0x46, 0x09, 0x2d, 0xbb, + 0x6e, 0x34, 0x24, 0x78, 0x9e, 0x74, 0x5d, 0x5c, 0xfc, 0x9a, 0x9c, 0x07, + 0x19, 0x76, 0x8c, 0x3b, 0x73, 0x6e, 0x64, 0x5f, 0x32, 0xeb, 0x5c, 0x3d, + 0xe2, 0x65, 0xbd, 0xaf, 0x65, 0xbd, 0xab, 0xe5, 0x79, 0x9c, 0xcb, 0xf3, + 0xa4, 0x97, 0x7e, 0xf3, 0x70, 0xb7, 0x7a, 0x19, 0xb1, 0x2d, 0x7d, 0x66, + 0xf9, 0x72, 0x55, 0x36, 0x2b, 0x29, 0x29, 0x79, 0x53, 0xcd, 0x65, 0x8b, + 0xe0, 0x4e, 0xe6, 0x69, 0x21, 0xda, 0xc0, 0xbf, 0x37, 0xf8, 0xb3, 0x56, + 0xea, 0x8b, 0x35, 0x40, 0x55, 0x4a, 0x2e, 0x82, 0xf5, 0x10, 0x28, 0x96, + 0x1c, 0xe3, 0x1c, 0x3b, 0x2f, 0x39, 0xd6, 0xde, 0x9b, 0x14, 0x29, 0x10, + 0x39, 0x71, 0xf8, 0xd0, 0x5b, 0xf5, 0x73, 0x5a, 0x3b, 0x0d, 0xf2, 0x16, + 0x22, 0xce, 0x87, 0x96, 0x4e, 0xaf, 0x34, 0x0b, 0x4a, 0x55, 0xa0, 0x67, + 0xc8, 0xe4, 0x85, 0x22, 0x41, 0xa6, 0x26, 0xc0, 0x26, 0x80, 0xc8, 0xb5, + 0xe9, 0x1a, 0xa2, 0x06, 0xa7, 0x97, 0x48, 0x70, 0x23, 0xcd, 0x27, 0xc1, + 0xc9, 0x2c, 0x9f, 0xc6, 0x2c, 0x68, 0x00, 0xf8, 0x09, 0x00, 0xf4, 0xcc, + 0x24, 0x58, 0xe4, 0x9e, 0x1d, 0x93, 0xcc, 0x35, 0xd3, 0x53, 0x93, 0x84, + 0xb2, 0x4e, 0x14, 0x48, 0xa8, 0xeb, 0x44, 0x01, 0xa4, 0x4b, 0x42, 0xd5, + 0xb0, 0xa5, 0xd5, 0xff, 0x97, 0xc9, 0xb2, 0x90, 0x3a, 0xc9, 0xf8, 0x97, + 0xe6, 0x49, 0xe4, 0xce, 0x71, 0x7e, 0x6c, 0xb9, 0x47, 0xbc, 0x5a, 0x4d, + 0xd4, 0x0e, 0xc7, 0x31, 0x5f, 0x72, 0x6c, 0xce, 0x29, 0xa9, 0x29, 0xa6, + 0x41, 0x26, 0x83, 0xf7, 0x38, 0x35, 0x5c, 0xd1, 0x6a, 0x63, 0x01, 0x6b, + 0x52, 0x1b, 0x0f, 0x83, 0x9a, 0x83, 0x34, 0x50, 0x26, 0x64, 0x4e, 0x7b, + 0xa8, 0xe3, 0x92, 0x6c, 0x2a, 0xe1, 0x19, 0xf1, 0x00, 0x51, 0xbf, 0x32, + 0xcb, 0xb2, 0xc1, 0x75, 0x66, 0xd9, 0xaa, 0xe5, 0xc8, 0x7b, 0x69, 0x41, + 0xe8, 0x19, 0x30, 0xf9, 0x92, 0x1b, 0x19, 0xf7, 0x94, 0x0d, 0x16, 0xd0, + 0x2f, 0x2d, 0xe3, 0xba, 0x08, 0xf0, 0x94, 0x94, 0x1e, 0x97, 0x44, 0x45, + 0x00, 0x5a, 0x19, 0x78, 0xfe, 0x7a, 0x63, 0xa1, 0xe4, 0xa1, 0x63, 0x5a, + 0x01, 0x79, 0x56, 0x54, 0xda, 0x4a, 0x61, 0x78, 0x9a, 0xfa, 0xdd, 0x67, + 0x66, 0xb9, 0x7f, 0xd3, 0x59, 0x76, 0x87, 0xc3, 0x56, 0xf0, 0x75, 0x70, + 0xbd, 0x5f, 0x5b, 0xbb, 0xfb, 0x5a, 0x74, 0x58, 0x6b, 0x9e, 0x15, 0xd8, + 0x89, 0xfe, 0xb4, 0x3a, 0x60, 0x1f, 0xf0, 0x35, 0xb9, 0xa6, 0xd9, 0xb6, + 0xbe, 0x6c, 0x9b, 0xb8, 0xb1, 0x84, 0x92, 0x16, 0x6d, 0x54, 0xf4, 0x60, + 0xe5, 0x7e, 0xf7, 0xd2, 0xd1, 0x41, 0x41, 0x9f, 0x0d, 0xa7, 0xc6, 0x16, + 0x28, 0xd6, 0x66, 0x50, 0xae, 0xbf, 0x6d, 0x06, 0xd5, 0xb3, 0xa1, 0xea, + 0x9c, 0xc8, 0xe5, 0x61, 0x43, 0x4b, 0x0d, 0x6b, 0x71, 0x47, 0x35, 0xc5, + 0x62, 0x45, 0x50, 0x09, 0x50, 0x23, 0xf3, 0xd2, 0x03, 0xf2, 0x6b, 0x0d, + 0xa6, 0xf4, 0xc0, 0xf0, 0xa4, 0xbe, 0x4e, 0x91, 0xd7, 0x1b, 0xaa, 0x01, + 0xf8, 0xf5, 0x4a, 0x88, 0xdf, 0x98, 0x33, 0x76, 0x31, 0x92, 0x2b, 0x79, + 0xd4, 0x29, 0x4e, 0x52, 0x29, 0x8d, 0x58, 0x41, 0x39, 0xfa, 0x57, 0x24, + 0xc9, 0xc5, 0x5f, 0xdc, 0x00, 0x85, 0x7c, 0x41, 0x8c, 0x1d, 0x5f, 0xab, + 0xbd, 0x4c, 0xa8, 0xc7, 0xaf, 0xfa, 0x97, 0x60, 0x6c, 0x62, 0x96, 0x4a, + 0x21, 0x4e, 0xa5, 0x12, 0x27, 0x56, 0xf3, 0xf3, 0xf2, 0x35, 0xaf, 0x2c, + 0xed, 0x55, 0xa8, 0x4d, 0x29, 0x77, 0xd9, 0x3f, 0xbc, 0x36, 0x03, 0x93, + 0x08, 0x96, 0xba, 0xe1, 0x4a, 0x28, 0x3e, 0x5f, 0xca, 0x9d, 0xcd, 0x9c, + 0x7e, 0xe2, 0xee, 0xa6, 0xfe, 0xbb, 0x7a, 0x35, 0x8a, 0x0e, 0xe8, 0x03, + 0x06, 0x2f, 0x85, 0x8e, 0xe0, 0xda, 0xf1, 0xac, 0x84, 0x95, 0x07, 0xcf, + 0xb5, 0x6b, 0x64, 0x82, 0xc3, 0xee, 0xda, 0x5e, 0x8a, 0x82, 0xa0, 0x69, + 0x8b, 0xb5, 0x6a, 0x9c, 0x4e, 0x83, 0x2c, 0x5e, 0x4c, 0x68, 0x53, 0x9e, + 0x44, 0x96, 0xff, 0xee, 0xab, 0x17, 0x2c, 0x78, 0x05, 0xc9, 0xba, 0x0a, + 0xab, 0x00, 0xde, 0x8a, 0xf1, 0xbc, 0xd0, 0x1e, 0x65, 0xb0, 0x6f, 0x36, + 0x04, 0x88, 0x78, 0x24, 0x40, 0xfc, 0xe6, 0xb9, 0xed, 0x67, 0xca, 0x4d, + 0x6e, 0x84, 0x51, 0xce, 0xbc, 0x95, 0x22, 0x69, 0x38, 0x21, 0x31, 0x0a, + 0xc1, 0xa0, 0x36, 0x77, 0x7a, 0x9d, 0x4e, 0x67, 0xb6, 0x74, 0x43, 0x15, + 0x98, 0x1d, 0x62, 0x05, 0x10, 0x9d, 0xac, 0x67, 0x60, 0x5e, 0x08, 0x7e, + 0x0a, 0xbf, 0x0e, 0x24, 0x9b, 0x85, 0x31, 0xe4, 0x9f, 0x04, 0x18, 0x37, + 0x04, 0xbc, 0x96, 0x70, 0x84, 0x39, 0x32, 0x98, 0x17, 0x46, 0x09, 0xfc, + 0x31, 0xe8, 0xcb, 0x7c, 0x20, 0x46, 0x1a, 0x4f, 0x1d, 0xbc, 0xb2, 0x23, + 0xee, 0xe7, 0x36, 0xa6, 0xd9, 0xd4, 0x43, 0x0e, 0xc6, 0x15, 0xc0, 0x3d, + 0x36, 0x24, 0xc9, 0xa7, 0x98, 0x0b, 0xc6, 0x1e, 0x7c, 0x22, 0xf2, 0x87, + 0xe5, 0xcb, 0xf0, 0xe8, 0x93, 0x70, 0x92, 0x34, 0x1b, 0x51, 0x36, 0x28, + 0x1b, 0x2d, 0xc6, 0x80, 0x90, 0x73, 0x23, 0x61, 0xbd, 0x63, 0xae, 0xd9, + 0xa0, 0x29, 0xe7, 0x96, 0x23, 0xa9, 0xb2, 0x09, 0xf0, 0x05, 0xff, 0xb3, + 0x6f, 0xf1, 0xa8, 0xfa, 0xce, 0xbd, 0x61, 0xf2, 0x60, 0x9f, 0xc3, 0x36, + 0xce, 0x49, 0x36, 0x7f, 0x4b, 0xf1, 0xce, 0xd9, 0x3c, 0x9d, 0x84, 0xf3, + 0x52, 0x7b, 0x89, 0x8b, 0xfd, 0xdf, 0xaf, 0xbb, 0x5d, 0x0a, 0x5d, 0x64, + 0xd3, 0x4d, 0xf6, 0x37, 0xe6, 0xa3, 0xc9, 0xe1, 0xe1, 0xc9, 0xc5, 0x78, + 0x40, 0x4f, 0xeb, 0x15, 0xf3, 0xf1, 0xe6, 0xa3, 0x20, 0x9d, 0xe2, 0x1d, + 0x67, 0xef, 0x41, 0x42, 0xe8, 0xa5, 0x9f, 0xff, 0x59, 0x93, 0x43, 0xce, + 0xd7, 0x9c, 0xdb, 0x6d, 0x89, 0xb0, 0x44, 0xa9, 0xd9, 0x52, 0x0b, 0x47, + 0x32, 0x49, 0x19, 0x27, 0x43, 0x23, 0x0d, 0xaa, 0xc7, 0xcb, 0xc4, 0x8c, + 0xe0, 0x1b, 0x0b, 0x7c, 0x1f, 0x4e, 0x7c, 0x83, 0x3f, 0xe0, 0x99, 0x2b, + 0x2e, 0x4f, 0xec, 0x97, 0x51, 0x4c, 0x97, 0x7b, 0x1d, 0x05, 0x90, 0x6f, + 0x5c, 0x90, 0x87, 0x1c, 0xd4, 0x0e, 0xb5, 0xc9, 0xd5, 0x0b, 0x35, 0x8d, + 0xe7, 0x8e, 0x27, 0x09, 0x63, 0x82, 0xa6, 0xb5, 0x12, 0x05, 0x38, 0x54, + 0xf9, 0x82, 0x84, 0xd6, 0x35, 0x5e, 0xa2, 0x7d, 0x39, 0x6d, 0xd7, 0x69, + 0x5f, 0x65, 0xd4, 0xea, 0x64, 0x5d, 0x32, 0xf5, 0xbd, 0xec, 0xb5, 0x83, + 0x92, 0xfd, 0x5b, 0xf6, 0x14, 0x81, 0xb3, 0xa5, 0xc8, 0x1f, 0x99, 0x2d, + 0x7b, 0xe2, 0xaf, 0x52, 0x7e, 0x2b, 0xc5, 0xb7, 0x62, 0x32, 0xe3, 0x7f, + 0x2d, 0xf9, 0xbf, 0xa5, 0xf8, 0x3d, 0xe6, 0x7f, 0x84, 0x98, 0x9a, 0xc5, + 0x58, 0x39, 0x85, 0xed, 0x29, 0x15, 0xf3, 0xb2, 0x2b, 0x35, 0x99, 0x28, + 0xdb, 0x5a, 0x76, 0xfb, 0xbc, 0xb0, 0xe7, 0x28, 0xec, 0xf1, 0xc2, 0xd2, + 0x51, 0xb3, 0x14, 0x35, 0x4b, 0x47, 0xcd, 0xb2, 0xc7, 0x25, 0x02, 0xba, + 0x03, 0x10, 0x77, 0x01, 0x89, 0x16, 0x9a, 0x98, 0x80, 0xca, 0xc9, 0x44, + 0x03, 0xa2, 0xfd, 0x4c, 0x74, 0x47, 0xf6, 0x76, 0x22, 0x9f, 0x10, 0xe0, + 0x55, 0x4a, 0x55, 0x05, 0x1b, 0xce, 0x4a, 0x55, 0xa5, 0x34, 0xaa, 0x9c, + 0x6a, 0x3d, 0x58, 0x62, 0x0f, 0x18, 0xca, 0x0f, 0x3f, 0x24, 0xb0, 0x7b, + 0x88, 0xea, 0x02, 0x1d, 0x3a, 0xd5, 0x1e, 0x3d, 0x2a, 0x79, 0x3f, 0x60, + 0x61, 0xa4, 0x2e, 0xea, 0x0b, 0x62, 0x10, 0xc8, 0x5c, 0xf3, 0xf8, 0x43, + 0x73, 0x90, 0xc6, 0xd2, 0x22, 0x13, 0x3d, 0x2d, 0x79, 0xd7, 0xba, 0xfa, + 0xcb, 0x04, 0x4b, 0xb3, 0x27, 0xa7, 0x0e, 0xf8, 0x9e, 0x01, 0x3f, 0x36, + 0xc7, 0x22, 0x2a, 0xf0, 0x5d, 0xf8, 0x25, 0xf4, 0x72, 0x39, 0xb6, 0x16, + 0x5d, 0x8d, 0x75, 0xb4, 0x25, 0x76, 0x2b, 0x63, 0x1a, 0xe5, 0x0a, 0xe5, + 0xf1, 0xb1, 0x1f, 0x4b, 0xb0, 0x61, 0xc9, 0x62, 0x76, 0x61, 0xe8, 0x1b, + 0xf5, 0x74, 0x53, 0xa8, 0x06, 0x30, 0xd4, 0x92, 0x0f, 0xd5, 0x80, 0xad, + 0x89, 0xcd, 0x2e, 0x0f, 0xe4, 0x3d, 0xeb, 0xca, 0x30, 0xa4, 0x55, 0xa1, + 0xd3, 0xee, 0x54, 0x9f, 0xf5, 0x3a, 0x79, 0xf0, 0x4b, 0x19, 0x56, 0xc6, + 0xaa, 0xcf, 0xc2, 0x62, 0x04, 0xd1, 0xb4, 0x26, 0x68, 0x84, 0x0e, 0xea, + 0x15, 0xed, 0x7b, 0x3a, 0xc5, 0xef, 0x7e, 0x6f, 0x87, 0xf4, 0x19, 0xb2, + 0xbf, 0xc2, 0xd4, 0x93, 0x98, 0x7a, 0x06, 0xa6, 0xde, 0x6a, 0x4c, 0x66, + 0x6f, 0x21, 0xa8, 0xc5, 0x46, 0xb1, 0x1b, 0x90, 0xda, 0xda, 0xe5, 0xaa, + 0x6b, 0x97, 0xab, 0xaf, 0x5d, 0x68, 0xe0, 0x54, 0xea, 0x1a, 0x94, 0x6d, + 0xc5, 0xae, 0x24, 0x47, 0x82, 0xf5, 0x50, 0x86, 0x96, 0x06, 0x61, 0x84, + 0xfc, 0x10, 0xa0, 0x90, 0x66, 0xec, 0xb3, 0xa0, 0xa0, 0x2e, 0xc6, 0xf2, + 0x25, 0x30, 0x94, 0x60, 0x12, 0x60, 0x2e, 0xbf, 0x8a, 0xe7, 0xd7, 0x6c, + 0xf4, 0x54, 0xda, 0xb2, 0x25, 0xb5, 0x46, 0xf2, 0x6a, 0x89, 0xab, 0x26, + 0xac, 0x3e, 0x51, 0x55, 0x82, 0xa7, 0xcb, 0xe9, 0x52, 0x6b, 0xf6, 0xd4, + 0x86, 0xd3, 0xe4, 0x13, 0xb1, 0x8a, 0xce, 0x9e, 0x6e, 0xac, 0x14, 0xcc, + 0xaa, 0xa0, 0xa1, 0x50, 0x56, 0x25, 0x83, 0xa7, 0xb8, 0xf5, 0x0b, 0xe7, + 0x87, 0xf7, 0xb8, 0x23, 0x59, 0x0f, 0xf6, 0x35, 0x73, 0x7b, 0x11, 0x2c, + 0xb8, 0x7b, 0x37, 0xb8, 0xa3, 0xf9, 0xba, 0x5e, 0x99, 0xd4, 0x5a, 0x76, + 0xc9, 0x99, 0x14, 0xa6, 0x66, 0x68, 0xbb, 0xb3, 0x4d, 0xbb, 0xa5, 0x96, + 0x7a, 0xa7, 0xdf, 0x21, 0x98, 0xbc, 0xcc, 0xdb, 0x1a, 0xa7, 0x4c, 0xc8, + 0x13, 0x95, 0x69, 0x8e, 0x01, 0x32, 0x55, 0x09, 0x19, 0xb8, 0x94, 0x34, + 0x48, 0x69, 0x29, 0x7b, 0xd6, 0xf7, 0xb3, 0x0b, 0xea, 0x85, 0x64, 0xd3, + 0xac, 0xcc, 0x67, 0x45, 0xf8, 0x81, 0xdc, 0x6a, 0xb8, 0x40, 0x9c, 0xe8, + 0x68, 0x1e, 0x46, 0x6b, 0xdb, 0x24, 0xe8, 0xf8, 0x35, 0x1a, 0xdc, 0xae, + 0x88, 0x16, 0x43, 0xfd, 0x67, 0x3c, 0x5a, 0x65, 0x88, 0xa0, 0xac, 0xfd, + 0x49, 0x37, 0x7c, 0x4f, 0xba, 0x41, 0xc5, 0xe1, 0x4c, 0x39, 0xd1, 0x4d, + 0x0a, 0x80, 0x81, 0x27, 0x08, 0x83, 0x86, 0xbe, 0x80, 0xc3, 0xc4, 0x5e, + 0x53, 0x47, 0xe5, 0x10, 0x19, 0x33, 0xbd, 0xd3, 0xa9, 0x7a, 0x7d, 0x4b, + 0xb7, 0x33, 0x18, 0xb8, 0x5e, 0x1b, 0xb8, 0x84, 0xd5, 0x66, 0x5f, 0xfb, + 0x06, 0x46, 0xfd, 0xbd, 0x35, 0x51, 0x9d, 0xc3, 0xaa, 0x96, 0x00, 0x5f, + 0x9a, 0xbf, 0x4a, 0xe9, 0x58, 0x72, 0x0b, 0x46, 0xa4, 0x0f, 0xd8, 0xc4, + 0xc3, 0x6b, 0x37, 0xbe, 0x98, 0x36, 0xe4, 0x3c, 0xc1, 0x8e, 0xef, 0x30, + 0x38, 0x49, 0x1a, 0xf3, 0x04, 0xf7, 0xa0, 0x79, 0x52, 0x78, 0x38, 0x79, + 0xcf, 0x37, 0xc2, 0x11, 0x06, 0x48, 0x02, 0x1e, 0x3a, 0xec, 0x04, 0x86, + 0x03, 0x38, 0xc2, 0x31, 0x4d, 0x4e, 0x28, 0xd1, 0x13, 0x27, 0x2b, 0x4e, + 0x0b, 0x08, 0x01, 0xb1, 0x1b, 0x86, 0x26, 0xe4, 0x9c, 0x1a, 0xa4, 0x76, + 0xd9, 0x46, 0x10, 0xe3, 0xbb, 0x62, 0x53, 0x96, 0xe4, 0x87, 0xfd, 0xff, + 0xad, 0x1c, 0xf7, 0xdb, 0x98, 0x94, 0x6e, 0xaa, 0xbd, 0xb6, 0xca, 0xcb, + 0x4d, 0x1b, 0x6b, 0x85, 0x2c, 0xde, 0x26, 0x65, 0x75, 0x67, 0x2b, 0x39, + 0x6e, 0x43, 0xc2, 0x55, 0xf5, 0x96, 0x12, 0x64, 0x5f, 0xc5, 0x99, 0x7e, + 0xdb, 0x80, 0x98, 0x8e, 0xfc, 0xf9, 0x61, 0xc3, 0x08, 0x9b, 0x0d, 0x12, + 0x78, 0x3c, 0xa3, 0xe4, 0xee, 0x8c, 0xca, 0x6e, 0x2e, 0xe1, 0x67, 0x66, + 0xf5, 0xd7, 0x66, 0x75, 0x72, 0xec, 0xc4, 0x39, 0x19, 0x7c, 0x84, 0xb4, + 0xe1, 0x45, 0x15, 0xd7, 0xd5, 0xa5, 0xa8, 0x87, 0xb3, 0xf2, 0x7d, 0x8c, + 0x10, 0x80, 0x40, 0xc3, 0x2f, 0xc6, 0xf9, 0x8d, 0x3b, 0x12, 0x13, 0x22, + 0x0f, 0xae, 0xc1, 0x3f, 0x86, 0xd4, 0x5d, 0xf9, 0x06, 0xa9, 0x41, 0xc5, + 0x77, 0xfa, 0xbe, 0x56, 0x61, 0x9b, 0xb5, 0x41, 0x94, 0xf3, 0xf5, 0x7a, + 0x5a, 0xd7, 0x6b, 0xdc, 0x60, 0x86, 0x87, 0x81, 0xfc, 0xa3, 0x3e, 0x58, + 0x59, 0x5f, 0xe4, 0xa6, 0xf2, 0xe3, 0xd8, 0xad, 0xa5, 0x5c, 0x36, 0x99, + 0xc0, 0xce, 0x37, 0xdc, 0x53, 0xf6, 0xa3, 0xf8, 0xdc, 0x42, 0xa1, 0xf6, + 0x34, 0xf5, 0x27, 0x16, 0xdc, 0xec, 0x56, 0xdd, 0x74, 0x33, 0xd8, 0x8d, + 0x62, 0xb7, 0xc6, 0x33, 0x65, 0x1b, 0x9a, 0x90, 0x68, 0x51, 0x5d, 0x9d, + 0x93, 0xa6, 0x26, 0x63, 0x7d, 0x22, 0xfb, 0x27, 0x22, 0x22, 0x50, 0x17, + 0x1b, 0x87, 0xea, 0xb2, 0x45, 0x43, 0xd7, 0xcb, 0xda, 0x5f, 0x2c, 0x3b, + 0xd7, 0x01, 0x01, 0x48, 0x7a, 0x0c, 0xe1, 0x8e, 0x01, 0xa2, 0x12, 0x61, + 0x4a, 0xc7, 0x76, 0x51, 0xdf, 0x94, 0x64, 0xbe, 0x11, 0x78, 0x4f, 0xdf, + 0x48, 0xd7, 0xad, 0xae, 0xe0, 0x59, 0x3a, 0x49, 0xe3, 0xe0, 0x38, 0x9d, + 0x04, 0x51, 0x32, 0x0a, 0xd9, 0x7c, 0xcd, 0x75, 0xab, 0xa3, 0xd4, 0x57, + 0x72, 0xfe, 0xe5, 0x5a, 0x60, 0x46, 0x6d, 0x5b, 0xc1, 0x76, 0xd0, 0x63, + 0x56, 0x8d, 0xf7, 0xc9, 0xb7, 0x55, 0x0b, 0x3a, 0x2a, 0x0a, 0x9a, 0xda, + 0x77, 0x7a, 0x15, 0xfe, 0x70, 0x11, 0x1b, 0x40, 0xd3, 0xd3, 0x62, 0xcb, + 0x5e, 0x6c, 0xac, 0xed, 0x27, 0xeb, 0x98, 0x40, 0xcd, 0x6e, 0x5c, 0xcd, + 0xde, 0x9b, 0xc0, 0xef, 0x78, 0xb9, 0x57, 0x9b, 0xa7, 0xee, 0x0d, 0x63, + 0x9e, 0x16, 0xe7, 0x9e, 0xa7, 0xce, 0xb9, 0xa6, 0x87, 0x19, 0x60, 0xfc, + 0xcb, 0xa6, 0x7f, 0x7a, 0x3a, 0x97, 0x39, 0x25, 0x9b, 0x3f, 0xfe, 0x39, + 0xe9, 0xdc, 0x34, 0xe6, 0x64, 0xb8, 0xde, 0x9c, 0xd8, 0x03, 0x75, 0xd1, + 0xe6, 0x07, 0x1e, 0x57, 0xcf, 0x18, 0x57, 0x74, 0xbe, 0x71, 0xd9, 0x13, + 0xf8, 0x23, 0x18, 0x9a, 0xb5, 0xa6, 0x33, 0xa9, 0x8a, 0x3e, 0x7f, 0x60, + 0xbc, 0xd2, 0xbd, 0x7a, 0x84, 0xe5, 0xe6, 0xa6, 0x2d, 0x5b, 0xcc, 0xe0, + 0xe9, 0x58, 0x63, 0x28, 0xf5, 0x68, 0x55, 0x85, 0x32, 0xdd, 0xef, 0x8b, + 0x89, 0x1d, 0x22, 0xe6, 0x3e, 0x3e, 0x02, 0x47, 0xd2, 0xd6, 0x26, 0xe3, + 0x57, 0x0e, 0x32, 0x3e, 0x3c, 0x2b, 0x19, 0x85, 0xbd, 0xaa, 0x91, 0xf1, + 0xbe, 0xb6, 0xcb, 0xea, 0xa0, 0xa7, 0xc1, 0x4e, 0x3e, 0xda, 0xfe, 0x78, + 0x48, 0xab, 0xed, 0x38, 0xae, 0xcf, 0xa1, 0x23, 0x07, 0x69, 0x1f, 0x1b, + 0xa4, 0x95, 0x3b, 0xb1, 0x4b, 0x8d, 0x9a, 0xcb, 0x0a, 0x53, 0x2e, 0x1d, + 0x4c, 0xa9, 0x79, 0x5e, 0xe7, 0x20, 0xcf, 0x79, 0xcf, 0x96, 0x9c, 0x85, + 0x0d, 0xd7, 0xa6, 0xd3, 0xd8, 0x41, 0xa7, 0x47, 0x6b, 0xd0, 0xa9, 0xc2, + 0x75, 0x4b, 0xc9, 0x75, 0xb1, 0xf1, 0x86, 0xbb, 0x24, 0x98, 0xc3, 0x3d, + 0xfd, 0xa9, 0x13, 0xef, 0xd8, 0x24, 0x9e, 0xf2, 0xbc, 0x68, 0xaf, 0xb5, + 0x76, 0x4c, 0xda, 0x49, 0xa6, 0x66, 0x4d, 0x0f, 0xb5, 0x13, 0x42, 0xcd, + 0xb5, 0xfb, 0x55, 0x36, 0x2a, 0x9e, 0xa2, 0xab, 0x1f, 0x62, 0x5b, 0x59, + 0x6e, 0xa0, 0xf1, 0xc8, 0x4c, 0x93, 0x97, 0xdb, 0xb1, 0xd8, 0xad, 0xa5, + 0x90, 0x43, 0x7d, 0x57, 0xa6, 0xed, 0x83, 0x2e, 0xab, 0xd0, 0x3c, 0x72, + 0x24, 0x81, 0xc5, 0xb6, 0x5f, 0x93, 0xef, 0xc9, 0xd5, 0x0f, 0x5c, 0x5d, + 0x9d, 0xd3, 0x8e, 0xe2, 0xad, 0x4f, 0x95, 0xdf, 0x55, 0x59, 0x7d, 0x3d, + 0x3a, 0x79, 0x27, 0xc2, 0x37, 0x5f, 0x67, 0xed, 0xd9, 0x89, 0xd9, 0xb3, + 0x57, 0x86, 0xfc, 0x65, 0xb6, 0x00, 0xe2, 0x47, 0xb5, 0x30, 0xe8, 0x1f, + 0x07, 0xc6, 0x72, 0xc1, 0x77, 0xbd, 0x5c, 0x42, 0x6c, 0xae, 0x2d, 0xda, + 0xb7, 0xc8, 0xc2, 0x20, 0x0a, 0xf2, 0xf0, 0xe4, 0xcb, 0x7c, 0x16, 0xc6, + 0xe6, 0xc9, 0x18, 0x11, 0x10, 0xea, 0x9b, 0x4c, 0x55, 0xbd, 0x43, 0x59, + 0xc2, 0x45, 0xcb, 0x52, 0x46, 0x82, 0xf8, 0x59, 0x62, 0x23, 0xc2, 0x61, + 0x6f, 0xfe, 0xe0, 0x0d, 0x4a, 0x8a, 0x6b, 0xdc, 0xad, 0x04, 0x8c, 0x02, + 0xa3, 0x43, 0xe6, 0x2b, 0xed, 0x9a, 0xf7, 0x29, 0x81, 0xcc, 0xba, 0xc6, + 0x3b, 0xee, 0xfa, 0x5b, 0xd6, 0x52, 0xad, 0x99, 0xf1, 0x26, 0x5b, 0xb7, + 0x79, 0xd4, 0x99, 0x00, 0x96, 0x5e, 0x9c, 0x28, 0x86, 0xd0, 0x41, 0xed, + 0x70, 0x8c, 0x3d, 0x39, 0x42, 0x73, 0xed, 0x9a, 0x6f, 0x1d, 0x87, 0xff, + 0xa4, 0xf1, 0x64, 0x54, 0x88, 0x82, 0xfb, 0x4e, 0xf7, 0x91, 0xd7, 0x51, + 0x73, 0x6b, 0xbf, 0xd6, 0x1e, 0x54, 0x18, 0xc4, 0x43, 0x2a, 0x9d, 0x58, + 0xea, 0x2f, 0x5f, 0xac, 0xce, 0x08, 0x30, 0x69, 0x8b, 0x07, 0x04, 0xba, + 0xda, 0xca, 0x1e, 0xf1, 0xd9, 0xbd, 0x86, 0x2e, 0x2f, 0xa3, 0x96, 0xb6, + 0x8b, 0xbb, 0xf6, 0x7a, 0x91, 0x69, 0x0b, 0x46, 0x06, 0xd6, 0x19, 0x13, + 0x92, 0x8b, 0xd9, 0xbe, 0x91, 0x29, 0xac, 0x0f, 0x7f, 0x44, 0xc2, 0x7a, + 0x01, 0x89, 0xb4, 0x65, 0x7c, 0x09, 0xf7, 0xdc, 0x2d, 0xbe, 0xbd, 0x0f, + 0x6c, 0xab, 0xbe, 0xe1, 0x4b, 0x91, 0xf2, 0x7b, 0x45, 0xb4, 0xef, 0x1b, + 0x2e, 0xf2, 0x5a, 0x32, 0x6d, 0x88, 0x2c, 0x34, 0xd4, 0xc4, 0x2b, 0x1e, + 0xba, 0x96, 0xd0, 0x9a, 0xbf, 0xa6, 0x37, 0xdf, 0xb2, 0xb9, 0x5d, 0x13, + 0x65, 0x1f, 0x27, 0x9b, 0xea, 0x9b, 0xfe, 0xf3, 0xab, 0x15, 0x37, 0xeb, + 0x2f, 0x95, 0x20, 0x9a, 0x1a, 0x03, 0xad, 0x46, 0x43, 0xae, 0x95, 0x72, + 0x40, 0xc2, 0x56, 0x89, 0x01, 0x7c, 0x75, 0x45, 0xa9, 0x2c, 0x5b, 0x41, + 0x38, 0x35, 0x0e, 0xa1, 0xdd, 0xdc, 0xb4, 0x7c, 0x27, 0xf8, 0xaf, 0x34, + 0x29, 0xc0, 0xe1, 0xa2, 0x2a, 0x20, 0xa8, 0x06, 0x9b, 0x5a, 0x96, 0x46, + 0x72, 0x13, 0xf0, 0xe7, 0xae, 0x0a, 0x12, 0x53, 0x15, 0xec, 0x79, 0xec, + 0x66, 0xcc, 0x31, 0x70, 0xf6, 0x65, 0xd7, 0xb9, 0xf2, 0x00, 0xbb, 0xfd, + 0xb0, 0x0b, 0xaf, 0x21, 0x58, 0x0e, 0x19, 0xf2, 0x2c, 0xae, 0xa7, 0x97, + 0xd7, 0x03, 0x22, 0x0c, 0xac, 0xab, 0xf7, 0xef, 0xe9, 0x4a, 0xca, 0x54, + 0x48, 0x15, 0x85, 0x60, 0x2e, 0x99, 0x6b, 0xf2, 0xf3, 0xcf, 0xd7, 0x22, + 0xf8, 0x93, 0xb8, 0xdb, 0xe2, 0xfe, 0x5b, 0x53, 0xdc, 0x3b, 0xfe, 0x95, + 0x5f, 0xf6, 0xd6, 0x01, 0xec, 0x88, 0x21, 0x38, 0xb6, 0x4b, 0x7e, 0xdb, + 0x58, 0x25, 0xd9, 0x8e, 0x91, 0x18, 0xab, 0xb9, 0xc1, 0x41, 0x67, 0x94, + 0x3a, 0x87, 0x00, 0xbd, 0x37, 0x9b, 0x59, 0x31, 0x86, 0xc1, 0x2f, 0xe7, + 0x9e, 0xeb, 0x1f, 0x3e, 0x2c, 0xf0, 0xc1, 0x6a, 0x93, 0xf0, 0x2c, 0xd3, + 0x69, 0x2c, 0x26, 0x26, 0xf5, 0x3c, 0xc6, 0xd6, 0xaa, 0xd9, 0x74, 0xd0, + 0x16, 0x14, 0x92, 0xc1, 0x1d, 0xb4, 0x57, 0x60, 0x28, 0x7b, 0x83, 0x05, + 0xc4, 0x5c, 0x4b, 0xb5, 0x7a, 0xaa, 0x2d, 0x5a, 0xb6, 0xf1, 0x63, 0xcf, + 0xf1, 0x4f, 0x78, 0x72, 0x8f, 0x4c, 0x25, 0xf0, 0x8b, 0x4b, 0x33, 0xff, + 0x05, 0x5d, 0xb4, 0x96, 0x5c, 0x2a, 0x43, 0xd3, 0x9e, 0xfe, 0xb8, 0xb8, + 0xc2, 0xdb, 0xf2, 0xab, 0x98, 0x5f, 0xac, 0xc2, 0x2f, 0x57, 0x9a, 0xba, + 0x38, 0xb1, 0xb6, 0xba, 0xd8, 0x7c, 0xf0, 0x03, 0xaa, 0xea, 0x8f, 0xcd, + 0x59, 0x7a, 0x66, 0xfe, 0xdc, 0x3f, 0xc7, 0xa4, 0x59, 0xe8, 0xd7, 0x9b, + 0x1a, 0x17, 0xd9, 0x9f, 0xad, 0x4f, 0x76, 0xbe, 0x53, 0xe7, 0xc7, 0xb5, + 0x7f, 0x8e, 0x29, 0xbc, 0xe0, 0xfc, 0x18, 0xb3, 0x92, 0x9d, 0x5b, 0xfa, + 0xa0, 0x66, 0x56, 0xba, 0xf7, 0x39, 0xcf, 0x29, 0x99, 0xef, 0xcc, 0x49, + 0x3e, 0xbd, 0x7c, 0xc7, 0x1c, 0x74, 0xaa, 0x02, 0x04, 0x4f, 0x0d, 0x5e, + 0x0d, 0x09, 0xb4, 0xbb, 0x93, 0x54, 0x32, 0x84, 0x2b, 0x23, 0x8e, 0xcf, + 0x90, 0x55, 0xeb, 0xcb, 0x34, 0x97, 0x0e, 0xe6, 0xa6, 0xd3, 0x2d, 0x80, + 0x8d, 0x7b, 0x7d, 0x50, 0x1f, 0x31, 0xb8, 0x60, 0x57, 0x6e, 0x2b, 0xd5, + 0x86, 0xe9, 0x52, 0x97, 0xed, 0xf1, 0xae, 0x61, 0x2e, 0x0d, 0x15, 0x5f, + 0xd1, 0xf0, 0x14, 0x11, 0x02, 0xec, 0x46, 0x06, 0x52, 0x46, 0xb6, 0x7b, + 0xeb, 0xe2, 0xc2, 0xd3, 0x0a, 0x7e, 0x9f, 0x99, 0x6a, 0x18, 0xa9, 0xbc, + 0xa1, 0xbb, 0x86, 0x81, 0xaa, 0x7b, 0xa2, 0xc6, 0x29, 0xe7, 0x8a, 0xbf, + 0x53, 0xe3, 0xeb, 0x70, 0x08, 0x99, 0x9b, 0x40, 0xbf, 0x7f, 0x49, 0x87, + 0xa9, 0xd2, 0xea, 0x61, 0x73, 0xf5, 0xc2, 0x95, 0xcb, 0xfc, 0x01, 0x08, + 0x7b, 0xfe, 0xee, 0xc1, 0x0c, 0xda, 0x36, 0x75, 0x65, 0x92, 0x3b, 0x6e, + 0x1b, 0x3a, 0xd0, 0xf9, 0xc7, 0x8e, 0x34, 0xd8, 0xc6, 0x96, 0x22, 0x7a, + 0x5a, 0xf5, 0x25, 0x2e, 0xab, 0xa3, 0x5d, 0xa3, 0xa3, 0xaa, 0x49, 0x07, + 0xb6, 0x4a, 0x00, 0x41, 0x70, 0x7c, 0x25, 0x64, 0x52, 0x8b, 0xa6, 0xd2, + 0x27, 0x11, 0x00, 0x1a, 0xe2, 0x01, 0x7f, 0x2f, 0xd2, 0xd5, 0x66, 0xe9, + 0xe9, 0x86, 0xc6, 0x8f, 0x88, 0xa7, 0x25, 0x40, 0xb5, 0x02, 0xa7, 0x84, + 0xb8, 0xb8, 0x74, 0xad, 0xe0, 0x8a, 0x4b, 0x68, 0xe0, 0x3f, 0xa4, 0x80, + 0xaf, 0x9f, 0x2b, 0xc4, 0xc9, 0x25, 0x9b, 0x67, 0x73, 0x02, 0x6b, 0x25, + 0x6c, 0x65, 0xf7, 0x6c, 0x8b, 0xfc, 0x0a, 0xa7, 0xe5, 0xbb, 0x35, 0xa8, + 0x68, 0xf2, 0x3e, 0xaa, 0x2c, 0xf9, 0x7b, 0x8d, 0x71, 0xfb, 0x0c, 0x10, + 0xaf, 0xdb, 0x6a, 0x74, 0xd6, 0xb9, 0x1a, 0xfe, 0xb4, 0xdc, 0xcd, 0x6d, + 0x73, 0x3d, 0xfb, 0xe8, 0xcc, 0xbb, 0x8b, 0xfc, 0xe4, 0x9a, 0x86, 0xb0, + 0xae, 0x6d, 0x7e, 0xec, 0xad, 0x3e, 0x15, 0x89, 0x3c, 0x0f, 0xb7, 0xde, + 0xd9, 0x4f, 0x63, 0x8f, 0x8d, 0x34, 0xb5, 0xba, 0x84, 0x2d, 0xf6, 0xc7, + 0x6a, 0xcf, 0xd0, 0xcc, 0x91, 0x08, 0x7c, 0xb8, 0xda, 0x49, 0x3e, 0x08, + 0xa0, 0xd6, 0x1c, 0xe5, 0x6b, 0xd5, 0x35, 0x2a, 0x57, 0x4b, 0x91, 0x8c, + 0x40, 0x90, 0x6c, 0x5e, 0x6a, 0x33, 0x7f, 0x05, 0x3f, 0xb4, 0xdc, 0xe6, + 0x8b, 0xf7, 0x0c, 0x9d, 0x1a, 0x8c, 0x64, 0xc5, 0xf7, 0x64, 0x7e, 0x78, + 0x8c, 0x0c, 0x9e, 0xe3, 0xbb, 0x5a, 0xb0, 0x3a, 0x1e, 0xe9, 0x38, 0x62, + 0x42, 0xc6, 0x06, 0xa6, 0x00, 0x12, 0x3f, 0x17, 0x70, 0x84, 0x5d, 0xa3, + 0x35, 0x1f, 0xf8, 0x47, 0x81, 0x36, 0x45, 0x90, 0xb2, 0x81, 0x7f, 0xdf, + 0x0d, 0xae, 0x58, 0x05, 0xbe, 0x00, 0xa6, 0x63, 0x41, 0x57, 0x6b, 0xf9, + 0xaa, 0x00, 0x86, 0xbd, 0xd6, 0xe3, 0xe4, 0xb9, 0x12, 0x2c, 0xd0, 0x7f, + 0xe4, 0xa6, 0x5e, 0x63, 0xa0, 0x66, 0x94, 0xa2, 0x12, 0xf4, 0x52, 0xae, + 0x34, 0x40, 0xcb, 0x53, 0xd6, 0x88, 0x9e, 0x59, 0x0b, 0xf6, 0x02, 0xe6, + 0xdb, 0x64, 0x70, 0xa0, 0xb9, 0xa7, 0xa1, 0x01, 0x76, 0x4e, 0xd5, 0x17, + 0xde, 0xef, 0xea, 0xe2, 0xee, 0x5f, 0x68, 0xd7, 0x8c, 0xd7, 0x55, 0x97, + 0x43, 0x51, 0xb2, 0x84, 0x83, 0xed, 0xa9, 0x62, 0x0d, 0x33, 0x9a, 0xe3, + 0x5c, 0x42, 0xb9, 0x83, 0xaf, 0x81, 0x5d, 0x59, 0xcc, 0x56, 0xad, 0x5d, + 0x9a, 0xe2, 0xae, 0xdc, 0xff, 0xaa, 0x4c, 0x11, 0x67, 0x66, 0xc7, 0xbc, + 0x88, 0x93, 0x00, 0xf0, 0xe6, 0x4b, 0x92, 0xe7, 0xe1, 0x51, 0xd2, 0x6c, + 0x70, 0xcd, 0x24, 0xb2, 0xdc, 0x07, 0x8f, 0x28, 0x38, 0x09, 0x39, 0xfa, + 0xc2, 0x22, 0x78, 0xf9, 0xfc, 0x60, 0xab, 0xd1, 0xd2, 0x71, 0x28, 0x51, + 0xb1, 0xa9, 0x69, 0xad, 0x5d, 0xd6, 0x6a, 0x7d, 0x36, 0x4b, 0xe1, 0xb2, + 0xc7, 0xf1, 0xf0, 0xf9, 0xcb, 0x97, 0xcf, 0x9f, 0x9d, 0x69, 0x28, 0x7e, + 0x92, 0xaf, 0xb1, 0xe4, 0x3b, 0x56, 0xfc, 0x52, 0x5e, 0x50, 0x42, 0x9c, + 0xb6, 0x37, 0x11, 0xa9, 0xa5, 0xd6, 0x41, 0x4c, 0x69, 0x2a, 0xe9, 0x46, + 0xc9, 0x3b, 0xab, 0xc7, 0x0c, 0x60, 0xd3, 0x13, 0x99, 0xf6, 0x06, 0xad, + 0xfd, 0xb3, 0xe4, 0xab, 0xc1, 0xc6, 0xe1, 0x36, 0x24, 0x74, 0x95, 0xef, + 0x89, 0x59, 0xaf, 0x6f, 0x46, 0xac, 0x30, 0x24, 0x2e, 0x6e, 0x4a, 0xa8, + 0xa1, 0x3b, 0x56, 0x1f, 0x07, 0x83, 0x5d, 0xfd, 0x24, 0x0b, 0x26, 0x61, + 0x11, 0x8f, 0x30, 0x8b, 0x29, 0x9b, 0xdd, 0xad, 0xab, 0x2d, 0xcd, 0x32, + 0xaa, 0x59, 0xe3, 0x56, 0xaf, 0xd7, 0x91, 0x7d, 0xc8, 0xe6, 0xd6, 0xb0, + 0x7a, 0xc8, 0xc6, 0x50, 0x72, 0xdc, 0x9f, 0xd0, 0xbb, 0x7e, 0x86, 0x3c, + 0x3b, 0x7a, 0xea, 0x19, 0x63, 0x25, 0x77, 0xdc, 0x78, 0x11, 0xe9, 0x78, + 0x14, 0x90, 0x91, 0x67, 0x46, 0xa0, 0x37, 0x96, 0x0e, 0x4e, 0x43, 0x6d, + 0x51, 0xb2, 0xd3, 0xea, 0xc8, 0xbd, 0x6f, 0x27, 0x4c, 0xa0, 0x6e, 0x1c, + 0xba, 0x71, 0x74, 0x5e, 0x8b, 0x03, 0x54, 0x0c, 0x11, 0xfe, 0xa5, 0x67, + 0xe5, 0x91, 0xd1, 0xd5, 0x6a, 0x80, 0xc4, 0x9f, 0x8c, 0xc5, 0x0d, 0x6f, + 0x07, 0x54, 0xdc, 0xd3, 0xa8, 0xcf, 0x4a, 0x57, 0x5c, 0x79, 0xb9, 0x7f, + 0x4f, 0xec, 0xfc, 0x8b, 0x0b, 0x30, 0xdf, 0x18, 0xc1, 0x95, 0xf3, 0xcc, + 0xd5, 0x35, 0x34, 0x22, 0xce, 0x3d, 0x31, 0x0a, 0xe7, 0x7b, 0xcc, 0x98, + 0x24, 0x3b, 0xb8, 0x6a, 0x6a, 0xd7, 0xc8, 0x90, 0xc4, 0x70, 0x55, 0x67, + 0x57, 0xac, 0x8f, 0xef, 0x7d, 0x76, 0xab, 0xc6, 0x3d, 0x4f, 0x97, 0xf8, + 0x48, 0xbe, 0x99, 0x70, 0x98, 0x14, 0x76, 0x6e, 0x44, 0x78, 0x50, 0x81, + 0xe9, 0x0d, 0x48, 0xce, 0xf3, 0x8e, 0xa7, 0x05, 0x81, 0xf7, 0xb7, 0x0f, + 0xe1, 0x0d, 0x89, 0x70, 0xac, 0xd5, 0x85, 0xeb, 0x3f, 0xfb, 0x60, 0xbe, + 0x3d, 0x9e, 0x87, 0x27, 0xb0, 0x4e, 0x31, 0x64, 0x98, 0x13, 0x64, 0x54, + 0x14, 0xb3, 0xdd, 0xed, 0xed, 0xe3, 0xa2, 0xdb, 0xe9, 0x6c, 0x4d, 0x93, + 0x62, 0x7b, 0x90, 0xc5, 0x39, 0xfe, 0xec, 0x6d, 0x2e, 0x8e, 0xb6, 0x0b, + 0xc8, 0x88, 0x79, 0x63, 0xb3, 0xbb, 0xb3, 0x35, 0x2a, 0x26, 0x98, 0xdd, + 0xfa, 0x41, 0x30, 0xce, 0xf0, 0x91, 0x65, 0xc8, 0x5e, 0x07, 0xef, 0x58, + 0xcd, 0x66, 0x39, 0x26, 0x11, 0x81, 0xd1, 0x01, 0x93, 0x62, 0x4a, 0xea, + 0x3c, 0x49, 0x82, 0x97, 0x7b, 0x2f, 0x9e, 0xdd, 0xc3, 0x3c, 0x95, 0xd8, + 0x52, 0x91, 0xe4, 0x90, 0x8d, 0x77, 0x37, 0x48, 0xe2, 0x51, 0x16, 0x6c, + 0x26, 0x4c, 0xf7, 0x30, 0xe9, 0x0f, 0xd9, 0xff, 0x7b, 0xd8, 0x80, 0xf2, + 0x97, 0x32, 0xe5, 0x6c, 0xb6, 0x28, 0x66, 0x8b, 0x22, 0xc8, 0xb3, 0x49, + 0x02, 0xef, 0x78, 0x41, 0xfa, 0xe5, 0x64, 0x42, 0xef, 0xcb, 0x67, 0xd3, + 0x21, 0xd3, 0x1a, 0x05, 0x25, 0x97, 0xe6, 0x39, 0x6c, 0x19, 0x99, 0x93, + 0x39, 0x3e, 0xb7, 0x14, 0x46, 0xd9, 0x71, 0xb2, 0xc5, 0xb1, 0x50, 0xa5, + 0x74, 0x4a, 0x66, 0xab, 0xa8, 0xa0, 0xa0, 0xa1, 0x2a, 0x26, 0xc4, 0x9e, + 0x2f, 0xa6, 0xf0, 0xee, 0x5e, 0x70, 0x5c, 0x40, 0x17, 0x83, 0x51, 0x76, + 0x02, 0x0f, 0x48, 0x6e, 0x89, 0x3e, 0x21, 0x09, 0x82, 0x28, 0x19, 0x67, + 0x27, 0xc1, 0x94, 0xfd, 0x6f, 0x01, 0xa3, 0xc6, 0x26, 0x1a, 0xb9, 0xe8, + 0x2a, 0xbe, 0xe9, 0x43, 0xf5, 0xb7, 0xaa, 0xb3, 0xb3, 0x75, 0xf8, 0x68, + 0xff, 0x31, 0x4c, 0x11, 0xe8, 0xfa, 0x66, 0x87, 0xcd, 0x76, 0xe3, 0x4d, + 0x63, 0x97, 0x8d, 0x7f, 0xd1, 0xbb, 0x11, 0xdf, 0x6c, 0xb4, 0xe1, 0x73, + 0xe3, 0xbb, 0xbf, 0xf9, 0x73, 0xd0, 0x2e, 0x8d, 0x50, 0x94, 0xdc, 0xe9, + 0x89, 0x92, 0xbf, 0xfe, 0x2b, 0x2c, 0x89, 0xa8, 0xa4, 0xd3, 0xe9, 0xdc, + 0xe1, 0x25, 0x5f, 0x14, 0x58, 0x10, 0xcb, 0x82, 0x58, 0x14, 0x0c, 0xb1, + 0x60, 0x20, 0x0b, 0x06, 0xa2, 0x60, 0x8e, 0x05, 0x89, 0x2c, 0x08, 0x45, + 0xc1, 0x14, 0x0b, 0x86, 0xa2, 0x20, 0xea, 0xf0, 0x82, 0xff, 0xf9, 0x17, + 0x2c, 0x38, 0x92, 0x05, 0x5d, 0x51, 0xf0, 0xaf, 0x58, 0x30, 0xe2, 0xfd, + 0xbd, 0xde, 0xbb, 0x2e, 0x50, 0xd1, 0x8f, 0xa0, 0xf9, 0xc9, 0x7e, 0x0b, + 0x20, 0x52, 0xd9, 0x58, 0x24, 0x20, 0x8e, 0xb1, 0xea, 0x57, 0x62, 0xa8, + 0xdd, 0xdb, 0x62, 0xa8, 0xdf, 0xfe, 0x2d, 0x96, 0xbc, 0x95, 0x25, 0x1d, + 0x59, 0xf2, 0x97, 0x58, 0x32, 0x16, 0x25, 0x72, 0xac, 0xdf, 0x7d, 0xfb, + 0x17, 0x58, 0x32, 0x91, 0x75, 0xae, 0xcb, 0x92, 0x6f, 0xb1, 0x64, 0x2a, + 0x4a, 0x76, 0x54, 0x9d, 0xff, 0xc2, 0x92, 0x8c, 0x97, 0xec, 0x44, 0x82, + 0x0e, 0xdf, 0xfd, 0xf1, 0x3f, 0xb0, 0x64, 0x26, 0x4b, 0x22, 0x59, 0xf2, + 0x9f, 0x58, 0xf2, 0x3b, 0xd9, 0x03, 0xd5, 0xb7, 0xff, 0x8f, 0x25, 0x73, + 0x59, 0x47, 0xb6, 0xf3, 0x47, 0x6a, 0x27, 0x97, 0x25, 0x03, 0x59, 0xf2, + 0xdf, 0x58, 0x52, 0xc8, 0x5e, 0xab, 0xbe, 0xfd, 0x1d, 0x96, 0x2c, 0x44, + 0x49, 0x4f, 0x8d, 0xe7, 0x1f, 0xb1, 0xe4, 0x58, 0x8e, 0x47, 0x95, 0xfc, + 0x1b, 0x96, 0x9c, 0xc8, 0x3a, 0x0a, 0xdb, 0x3f, 0x63, 0xc9, 0x52, 0xf6, + 0x5a, 0xb2, 0xd5, 0xb7, 0x7f, 0x86, 0x25, 0x25, 0x2f, 0xe9, 0xdd, 0x94, + 0xd8, 0xfe, 0x40, 0xed, 0xfc, 0x5e, 0x96, 0xdc, 0x90, 0x25, 0xff, 0x84, + 0x25, 0xef, 0xf8, 0x94, 0xee, 0xc4, 0x82, 0x06, 0xff, 0x4b, 0x24, 0xf8, + 0x5a, 0x56, 0x91, 0xc4, 0xf9, 0xc3, 0xdf, 0x63, 0xc9, 0xa9, 0xe0, 0x82, + 0x70, 0x47, 0x30, 0xd0, 0x3f, 0x60, 0xc1, 0x37, 0x92, 0xb3, 0x6e, 0x35, + 0x02, 0x2a, 0xf8, 0xf7, 0x86, 0x19, 0xde, 0x90, 0x82, 0xf4, 0xab, 0x5f, + 0x06, 0x94, 0x5c, 0x04, 0x1f, 0x0c, 0x69, 0x3e, 0x70, 0x81, 0x1c, 0x1a, + 0x20, 0x0f, 0x83, 0xe6, 0xaf, 0x0e, 0x31, 0x61, 0x75, 0xcb, 0x01, 0xfc, + 0x78, 0x51, 0x60, 0xa4, 0x44, 0xc1, 0x5f, 0x77, 0x40, 0x3d, 0x49, 0x99, + 0x82, 0xc8, 0x4d, 0xb8, 0x47, 0x90, 0x4f, 0xbf, 0x79, 0xc3, 0x05, 0x0d, + 0xda, 0xc5, 0x04, 0x7e, 0xe1, 0x05, 0x7b, 0x14, 0x4e, 0xc3, 0x41, 0x1a, + 0x4e, 0x0d, 0xf0, 0x4f, 0x1d, 0xe0, 0xbf, 0x60, 0x5f, 0x2c, 0xb0, 0x5f, + 0x3a, 0xc0, 0x9e, 0x16, 0xe1, 0xd8, 0x46, 0xf7, 0x1b, 0x07, 0xdc, 0x27, + 0xd9, 0xfc, 0x24, 0x39, 0x62, 0x90, 0x8f, 0xc3, 0xca, 0xd0, 0xf6, 0x70, + 0x68, 0x37, 0x5d, 0x7a, 0x6c, 0x56, 0x85, 0xfe, 0x7f, 0x2e, 0xb8, 0x93, + 0x64, 0x60, 0xc3, 0x7d, 0x8c, 0x58, 0x6f, 0x39, 0xa1, 0xd3, 0x3c, 0x37, + 0x60, 0xef, 0xb9, 0x46, 0x76, 0xf8, 0x7c, 0x1f, 0xd2, 0xb9, 0xeb, 0x80, + 0xdb, 0x0f, 0xe4, 0x32, 0xf9, 0x71, 0x32, 0x9e, 0x25, 0x73, 0xbe, 0x3e, + 0x8a, 0xc0, 0x57, 0x00, 0xb1, 0xaf, 0x31, 0x5b, 0x78, 0xcb, 0x59, 0xd2, + 0x0e, 0x46, 0x6c, 0x11, 0x1c, 0x27, 0xf3, 0x76, 0x10, 0x87, 0x33, 0x78, + 0x46, 0x96, 0x0c, 0xa4, 0x64, 0xbc, 0x15, 0x0e, 0x06, 0xf8, 0x36, 0xc7, + 0x7e, 0x9a, 0x17, 0xf0, 0xf2, 0x42, 0xd3, 0x0d, 0x0f, 0x76, 0x33, 0xae, + 0xcf, 0x90, 0x3a, 0x41, 0x6f, 0x64, 0x38, 0x5c, 0xa7, 0x95, 0x79, 0x32, + 0x61, 0xab, 0xd3, 0x45, 0x1a, 0xa2, 0x27, 0x55, 0x9a, 0xc9, 0xb1, 0x0a, + 0xe4, 0x25, 0xc7, 0x90, 0x18, 0x10, 0x70, 0x3e, 0x16, 0x6f, 0x16, 0x56, + 0x3e, 0x51, 0x18, 0x8f, 0x7d, 0x26, 0x1b, 0xe3, 0x33, 0x9e, 0x17, 0x4b, + 0x46, 0x9f, 0x38, 0x9e, 0xbc, 0xc8, 0x66, 0x07, 0xf3, 0x6c, 0x16, 0x1e, + 0xe1, 0x2b, 0xa5, 0x88, 0xc8, 0xfa, 0x26, 0x31, 0x51, 0x4f, 0x1e, 0x2e, + 0xa2, 0x68, 0xac, 0x9f, 0xc3, 0xb4, 0x8c, 0x18, 0xad, 0xeb, 0xe9, 0x74, + 0x94, 0xcc, 0xd3, 0x22, 0x6f, 0xc6, 0x90, 0x09, 0xad, 0x1d, 0x50, 0x82, + 0x36, 0x1a, 0x87, 0x04, 0x1a, 0x36, 0x8d, 0xa0, 0x20, 0x5b, 0xec, 0x73, + 0x86, 0x39, 0xa6, 0xe7, 0x99, 0xb0, 0x22, 0x99, 0x4b, 0xac, 0x8a, 0x8a, + 0x78, 0x06, 0xf7, 0x38, 0x32, 0xf5, 0x09, 0xa0, 0x10, 0xdc, 0x80, 0x9a, + 0x26, 0x27, 0xc1, 0x10, 0x7b, 0xc5, 0x38, 0x87, 0x8d, 0x39, 0x82, 0xe4, + 0x1f, 0xcc, 0x64, 0x89, 0xe6, 0xd9, 0xdb, 0x04, 0xde, 0xde, 0x4b, 0x80, + 0xc0, 0x0d, 0x7c, 0x42, 0x13, 0xec, 0x99, 0xb4, 0x10, 0x89, 0xf0, 0xc5, + 0xf3, 0x8b, 0x5b, 0xda, 0x78, 0xf2, 0x87, 0xac, 0xfa, 0x43, 0xac, 0xda, + 0x14, 0xc9, 0xe0, 0xa8, 0xf7, 0x64, 0x6f, 0x0f, 0xc0, 0xd9, 0x59, 0x37, + 0x4b, 0x5c, 0x9f, 0x57, 0x4b, 0xc6, 0x81, 0x3f, 0xcd, 0x5f, 0xce, 0x84, + 0x8f, 0x62, 0x0a, 0x8c, 0x99, 0x98, 0x46, 0x4a, 0xe6, 0x1f, 0xbf, 0x7c, + 0xb6, 0x0f, 0xfe, 0xcd, 0x28, 0x19, 0x8f, 0x33, 0x48, 0x02, 0x37, 0x1e, + 0xa0, 0xa7, 0x03, 0x78, 0x8d, 0xc4, 0x73, 0xc9, 0xb8, 0x25, 0x9a, 0x38, + 0x81, 0x2c, 0x16, 0x0c, 0x01, 0xb9, 0xc5, 0xaf, 0x20, 0x4d, 0x1f, 0x47, + 0x49, 0x49, 0xef, 0x86, 0xd9, 0xb4, 0x78, 0x25, 0x53, 0xf3, 0x01, 0x8d, + 0x1a, 0xb2, 0x6a, 0xcf, 0x59, 0x15, 0x5b, 0x23, 0xe6, 0x36, 0x5a, 0xe3, + 0xcc, 0xc0, 0x1a, 0x84, 0x78, 0xdc, 0x49, 0x0f, 0x49, 0x0f, 0x78, 0xe8, + 0xc1, 0x39, 0xe1, 0x4d, 0xd0, 0xaf, 0xfe, 0x06, 0xa5, 0x90, 0x13, 0x39, + 0xd7, 0x44, 0xa9, 0xfa, 0x22, 0x21, 0x9e, 0x42, 0xe4, 0xfc, 0x58, 0x25, + 0x0e, 0xd6, 0x3e, 0xf5, 0x0d, 0x8e, 0x1b, 0x24, 0xcb, 0xe7, 0xc3, 0x66, + 0x16, 0x7d, 0xd5, 0x66, 0xbd, 0x56, 0x73, 0x03, 0x7e, 0x0c, 0xfb, 0xa8, + 0xf9, 0x8f, 0x3c, 0x74, 0x99, 0xaa, 0xa4, 0xe9, 0x20, 0x12, 0x0c, 0x06, + 0x7d, 0x08, 0x88, 0xf9, 0x8d, 0x85, 0xfb, 0x4b, 0x71, 0xd6, 0x53, 0x35, + 0x3c, 0xd8, 0x21, 0x36, 0x18, 0x5d, 0x66, 0xaa, 0x90, 0x32, 0xca, 0x16, + 0x03, 0xf0, 0xc8, 0xbe, 0x58, 0x0c, 0x87, 0x1d, 0x38, 0x65, 0x66, 0x4a, + 0x89, 0xc4, 0x04, 0x70, 0xf7, 0x05, 0x5c, 0x17, 0x9d, 0x39, 0xad, 0x66, + 0x94, 0x34, 0x5a, 0xdc, 0x51, 0x81, 0x70, 0xbb, 0x06, 0x1b, 0xf7, 0x6c, + 0xd8, 0xf8, 0x96, 0x17, 0x36, 0xac, 0xc0, 0x0e, 0x7d, 0xb0, 0x83, 0x0a, + 0xde, 0x81, 0x17, 0xef, 0xa0, 0x82, 0x77, 0x10, 0xfb, 0x60, 0x93, 0x8e, + 0x0d, 0x9b, 0xdc, 0xf4, 0xc2, 0xde, 0xae, 0xc0, 0x62, 0x06, 0x03, 0x9d, + 0xe2, 0x18, 0x28, 0xc1, 0xf4, 0x8f, 0xcd, 0x39, 0xf3, 0xc6, 0x8e, 0xd8, + 0xff, 0xa2, 0xae, 0x9a, 0xee, 0x51, 0x88, 0x0b, 0x11, 0x2b, 0x83, 0xac, + 0x41, 0xdd, 0x9b, 0x98, 0x46, 0xe8, 0x08, 0x7f, 0xdc, 0x86, 0xbf, 0xa3, + 0xae, 0x4c, 0x46, 0xa0, 0x30, 0x6d, 0x7d, 0x19, 0x87, 0xf1, 0x28, 0xf9, + 0x1c, 0x2a, 0x43, 0x3c, 0xd9, 0x48, 0x68, 0xc6, 0xe7, 0xcb, 0x03, 0x2d, + 0x3d, 0x3a, 0xdc, 0x10, 0x18, 0xa4, 0x43, 0x48, 0x4f, 0xf2, 0x74, 0x8a, + 0xef, 0xdd, 0x8a, 0xf4, 0x37, 0xe3, 0x14, 0xcf, 0x16, 0xf0, 0x5f, 0x18, + 0x14, 0xe7, 0x7f, 0xc7, 0xfc, 0xdf, 0xb9, 0x48, 0xe6, 0x77, 0x24, 0xfe, + 0x88, 0xc4, 0x1f, 0x80, 0x52, 0x7f, 0x33, 0x12, 0x82, 0xe9, 0x72, 0xb9, + 0x3c, 0x8e, 0xa1, 0x43, 0xb9, 0x2b, 0xae, 0x1e, 0xb3, 0x66, 0x6c, 0x38, + 0x99, 0x61, 0x78, 0x0e, 0xb2, 0x1d, 0xcb, 0xc4, 0x4c, 0x47, 0xf4, 0x53, + 0x64, 0x86, 0x89, 0xe8, 0x67, 0x4f, 0x44, 0xfb, 0xf9, 0xa8, 0x34, 0x0a, + 0xb0, 0xe5, 0xbe, 0x80, 0x35, 0x41, 0x9b, 0x02, 0x18, 0x04, 0xf4, 0x1f, + 0xba, 0xae, 0x6f, 0xd8, 0x51, 0x65, 0x73, 0x8f, 0x1a, 0x09, 0x92, 0x8a, + 0x60, 0x59, 0xf5, 0x6c, 0xaa, 0xac, 0x77, 0x97, 0x48, 0xaa, 0xd5, 0xe4, + 0x7d, 0x21, 0xaa, 0x54, 0xb1, 0xd9, 0x79, 0x53, 0x7c, 0x73, 0x0c, 0xd9, + 0x6d, 0x91, 0xaf, 0x2a, 0x00, 0x9a, 0x6f, 0xcd, 0x9d, 0x65, 0x36, 0xd4, + 0xf8, 0x2d, 0x53, 0x77, 0xf3, 0x21, 0xbc, 0x89, 0x1e, 0x67, 0x93, 0x6d, + 0xcc, 0xb3, 0x01, 0x4f, 0x80, 0x6d, 0x77, 0x6f, 0xee, 0xec, 0xdc, 0xee, + 0xdd, 0xde, 0x70, 0xd0, 0x46, 0xdf, 0x91, 0xf3, 0x90, 0x09, 0x87, 0xc5, + 0x7b, 0x8a, 0xe9, 0x08, 0x66, 0xd9, 0x49, 0x73, 0xa7, 0xc3, 0xec, 0x1b, + 0xe0, 0xdf, 0x4d, 0x06, 0xda, 0x6a, 0x07, 0x3d, 0x12, 0x96, 0x6b, 0x0a, + 0xe2, 0xc6, 0x1d, 0x80, 0x38, 0x02, 0x88, 0x23, 0x37, 0x44, 0xb7, 0x0b, + 0x10, 0x11, 0x40, 0x44, 0x04, 0x41, 0x41, 0x06, 0x29, 0x45, 0x09, 0x1b, + 0x2a, 0xe9, 0xca, 0xb4, 0x40, 0x53, 0x24, 0x9b, 0x2a, 0x0d, 0x06, 0xea, + 0x92, 0x71, 0xdb, 0x5e, 0x08, 0x6a, 0x4d, 0x24, 0xa0, 0x51, 0xdf, 0x9a, + 0xaa, 0x4a, 0x7f, 0xc3, 0x9d, 0x59, 0x5b, 0x53, 0xb8, 0x3a, 0x4f, 0x42, + 0x45, 0x66, 0x4c, 0x8c, 0xc7, 0xcd, 0x18, 0x9e, 0xbf, 0x25, 0x95, 0xcb, + 0xba, 0x80, 0x7f, 0x8a, 0xac, 0x23, 0x5a, 0x2f, 0xdf, 0x26, 0x65, 0x0e, + 0xbd, 0x51, 0x5d, 0x7b, 0x1e, 0x7d, 0x95, 0xc4, 0x05, 0x6c, 0x7b, 0xe6, + 0xb2, 0x6b, 0xda, 0xb7, 0xa6, 0xc0, 0x03, 0xfd, 0x61, 0x1f, 0x70, 0x1f, + 0x14, 0x8c, 0x4d, 0x4a, 0x37, 0x8c, 0x5d, 0x85, 0x90, 0x59, 0x8a, 0x03, + 0xd2, 0xd5, 0x3f, 0x47, 0xa2, 0x76, 0x56, 0x19, 0x9f, 0x3c, 0x3f, 0x99, + 0x82, 0x35, 0x94, 0xcc, 0x8b, 0x92, 0x7a, 0x8d, 0x04, 0x83, 0x9d, 0x55, + 0xc5, 0x90, 0x80, 0x9f, 0x9e, 0xc5, 0x10, 0xc9, 0x48, 0x04, 0x13, 0xca, + 0x99, 0x05, 0x10, 0x32, 0x44, 0xc8, 0x76, 0xdd, 0x5b, 0xce, 0xe0, 0x09, + 0x68, 0x33, 0xb4, 0x83, 0x86, 0xe2, 0x1e, 0x3e, 0x66, 0x06, 0xe6, 0x8f, + 0xfe, 0xb3, 0xaf, 0xa0, 0x84, 0x5d, 0x05, 0x0c, 0xcf, 0xff, 0xd4, 0x4a, + 0x31, 0xe9, 0x6f, 0x36, 0xd5, 0xbf, 0xa0, 0xb0, 0x64, 0x20, 0x2b, 0xca, + 0xc4, 0x46, 0x63, 0x0e, 0x24, 0x1c, 0xff, 0x60, 0x5c, 0x81, 0x71, 0x60, + 0x36, 0xe6, 0x6c, 0x08, 0x39, 0x63, 0x16, 0x6c, 0x71, 0xc4, 0xc4, 0x45, + 0x8b, 0x29, 0xbe, 0xdb, 0x9d, 0x0c, 0x78, 0x6c, 0x91, 0xca, 0xb6, 0x92, + 0x25, 0x3e, 0x41, 0xaa, 0xa9, 0x17, 0x36, 0x38, 0x15, 0xe2, 0xc7, 0x45, + 0x5a, 0xbe, 0xc4, 0x6d, 0x00, 0x6d, 0x6c, 0x9c, 0xb6, 0x88, 0x90, 0x56, + 0x8a, 0x55, 0x2d, 0xc3, 0x0b, 0x2e, 0x09, 0xbc, 0x33, 0xf4, 0x16, 0x91, + 0xdd, 0x99, 0xe0, 0x23, 0x51, 0xb0, 0x1b, 0x1c, 0x8d, 0xb3, 0x28, 0x04, + 0xfb, 0xe3, 0xb4, 0x09, 0x69, 0x18, 0xee, 0x6e, 0xc3, 0x2b, 0xda, 0xb3, + 0xe2, 0xfe, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x61, 0xc5, 0xc0, 0xc4, + 0x28, 0x4a, 0x02, 0x00, + })) + + if err != nil { + panic("Decompression failed: " + err.Error()) + } + defer func() { _ = gz.Close() }() //nolint:errcheck + + // TODO: We should consider how best to present this. + //nolint:gosec + return io.Copy(w, gz) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/ui_unix.go b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_unix.go new file mode 100644 index 00000000..601963ab --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_unix.go @@ -0,0 +1,16 @@ +//go:build !windows +// +build !windows + +package dmsgpty + +import ( + "github.com/creack/pty" +) + +func (ui *UI) uiStartSize(ptyC *PtyClient) error { + winSize, err := NewWinSize(&pty.Winsize{Rows: wsRows, Cols: wsCols}) + if err != nil { + return err + } + return ptyC.StartWithSize(ui.conf.CmdName, ui.conf.CmdArgs, winSize) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/ui_windows.go b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_windows.go new file mode 100644 index 00000000..7c985ba6 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/ui_windows.go @@ -0,0 +1,17 @@ +//go:build windows +// +build windows + +package dmsgpty + +import "golang.org/x/sys/windows" + +func (ui *UI) uiStartSize(ptyC *PtyClient) error { + ws, err := NewWinSize(&windows.Coord{ + X: wsCols, + Y: wsRows, + }) + if err != nil { + return err + } + return ptyC.StartWithSize(ui.conf.CmdName, ui.conf.CmdArgs, ws) +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist.go b/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist.go new file mode 100644 index 00000000..027cd27c --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist.go @@ -0,0 +1,256 @@ +package dmsgpty + +import ( + "errors" + "fmt" + "io/fs" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + "sync" + + jsoniter "github.com/json-iterator/go" + + "github.com/skycoin/dmsg/cipher" +) + +var ( + json = jsoniter.ConfigFastest + wl cipher.PubKeys +) + +// Whitelist represents a whitelist of public keys. +type Whitelist interface { + Get(pk cipher.PubKey) (bool, error) + All() (map[cipher.PubKey]bool, error) + Add(pks ...cipher.PubKey) error + Remove(pks ...cipher.PubKey) error +} + +// conf to update whitelists +var conf = Config{} + +// NewConfigWhitelist creates a config file implementation of a whitelist. +func NewConfigWhitelist(confPath string) (Whitelist, error) { + confPath, err := filepath.Abs(confPath) + if err != nil { + return nil, err + } + if err = os.MkdirAll(filepath.Dir(confPath), 0750); err != nil { + return nil, err + } + + return &configWhitelist{confPath: confPath}, nil +} + +type configWhitelist struct { + confPath string +} + +func (w *configWhitelist) Get(pk cipher.PubKey) (bool, error) { + var ok bool + err := w.open() + if err != nil { + return ok, err + } + for _, k := range wl { + if k == pk { + ok = true + } + } + return ok, nil +} + +func (w *configWhitelist) All() (map[cipher.PubKey]bool, error) { + err := w.open() + if err != nil { + return nil, err + } + out := make(map[cipher.PubKey]bool) + for _, k := range wl { + out[k] = true + } + return out, nil +} + +func (w *configWhitelist) Add(pks ...cipher.PubKey) error { + err := w.open() + if err != nil { + return err + } + // duplicate flag + var dFlag bool + + // append new pks to the whitelist slice within the config file + // for each pk to be added + var pke []string + for _, k := range pks { + + dFlag = false + // check if the pk already exists + for _, p := range wl { + + // if it does + if p == k { + // flag it + dFlag = true + pke = append(pke, p.String()) + fmt.Printf("skipping append for %v. Already exists", k) + break + } + } + + // if pk does already not exist + if !dFlag { + // append it + wl = append(wl, k) + conf.WL = append(conf.WL, k.Hex()) + } + + } + + // write the changes back to the config file + err = updateFile(w.confPath) + if err != nil { + log.Println("unable to update config file") + return err + } + if len(pke) != 0 { + return errors.New("skipping append for " + strings.Join(pke, ",") + ". Already exists") + } + return nil +} + +func (w *configWhitelist) Remove(pks ...cipher.PubKey) error { + err := w.open() + if err != nil { + return err + } + + // for each pubkey to be removed + for _, k := range pks { + + // find occurrence of pubkey in config whitelist + for i := 0; i < len(wl); i++ { + + // if an occurrence is found + if k == wl[i] { + // remove element + wl = append(wl[:i], wl[i+1:]...) + conf.WL = append(conf.WL[:i], conf.WL[i+1:]...) + break + } + } + } + // write changes back to the config file + err = updateFile(w.confPath) + if err != nil { + log.Println("unable to update config file") + return err + } + return nil +} + +func (w *configWhitelist) open() error { + info, err := os.Stat(w.confPath) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + _, err = os.Create(w.confPath) + if err != nil { + return err + } + } + return err + } + + if info.Size() == 0 { + if err = updateFile(w.confPath); err != nil { + return err + } + } + + // read file using ioutil + file, err := ioutil.ReadFile(w.confPath) + if err != nil { + return err + } + // store config.json into conf to manipulate whitelists + err = json.Unmarshal(file, &conf) + if err != nil { + return err + } + // convert []string to cipher.PubKeys + if len(conf.WL) > 0 { + ustString := strings.Join(conf.WL, ",") + if err := wl.Set(ustString); err != nil { + return err + } + } + return nil +} + +// updateFile writes changes to config file +func updateFile(confPath string) error { + + // marshal content + b, err := json.MarshalIndent(conf, "", " ") + if err != nil { + return err + } + // write to config file + err = ioutil.WriteFile(confPath, b, 0600) + if err != nil { + return err + } + + return nil +} + +// NewMemoryWhitelist creates a memory implementation of a whitelist. +func NewMemoryWhitelist() Whitelist { + return &memoryWhitelist{ + m: make(map[cipher.PubKey]struct{}), + } +} + +type memoryWhitelist struct { + m map[cipher.PubKey]struct{} + mux sync.RWMutex +} + +func (w *memoryWhitelist) Get(pk cipher.PubKey) (bool, error) { + w.mux.RLock() + _, ok := w.m[pk] + w.mux.RUnlock() + return ok, nil +} + +func (w *memoryWhitelist) All() (map[cipher.PubKey]bool, error) { + out := make(map[cipher.PubKey]bool) + w.mux.RLock() + for k := range w.m { + out[k] = true + } + w.mux.RUnlock() + return out, nil +} + +func (w *memoryWhitelist) Add(pks ...cipher.PubKey) error { + w.mux.Lock() + for _, pk := range pks { + w.m[pk] = struct{}{} + } + w.mux.Unlock() + return nil +} + +func (w *memoryWhitelist) Remove(pks ...cipher.PubKey) error { + w.mux.Lock() + for _, pk := range pks { + delete(w.m, pk) + } + w.mux.Unlock() + return nil +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist_client.go b/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist_client.go new file mode 100644 index 00000000..76d33018 --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist_client.go @@ -0,0 +1,45 @@ +package dmsgpty + +import ( + "io" + "net/rpc" + + "github.com/skycoin/dmsg/cipher" +) + +// WhitelistClient interacts with a whitelist's API. +type WhitelistClient struct { + c *rpc.Client +} + +// NewWhitelistClient creates a new whitelist client. +func NewWhitelistClient(conn io.ReadWriteCloser) (*WhitelistClient, error) { + if err := writeRequest(conn, WhitelistURI); err != nil { + return nil, err + } + if err := readResponse(conn); err != nil { + return nil, err + } + return &WhitelistClient{c: rpc.NewClient(conn)}, nil +} + +// ViewWhitelist obtains the whitelist entries from host. +func (wc WhitelistClient) ViewWhitelist() ([]cipher.PubKey, error) { + var pks []cipher.PubKey + err := wc.c.Call(wc.rpcMethod("Whitelist"), &empty, &pks) + return pks, err +} + +// WhitelistAdd adds a whitelist entry to host. +func (wc WhitelistClient) WhitelistAdd(pks ...cipher.PubKey) error { + return wc.c.Call(wc.rpcMethod("WhitelistAdd"), &pks, &empty) +} + +// WhitelistRemove removes a whitelist entry from host. +func (wc WhitelistClient) WhitelistRemove(pks ...cipher.PubKey) error { + return wc.c.Call(wc.rpcMethod("WhitelistRemove"), &pks, &empty) +} + +func (*WhitelistClient) rpcMethod(m string) string { + return WhitelistRPCName + "." + m +} diff --git a/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist_gateway.go b/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist_gateway.go new file mode 100644 index 00000000..c326fd5d --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/dmsgpty/whitelist_gateway.go @@ -0,0 +1,40 @@ +package dmsgpty + +import ( + "github.com/skycoin/dmsg/cipher" +) + +// WhitelistGateway is the configuration gateway. +type WhitelistGateway struct { + wl Whitelist +} + +// NewWhitelistGateway creates a new configuration gateway. +func NewWhitelistGateway(auth Whitelist) *WhitelistGateway { + return &WhitelistGateway{wl: auth} +} + +// Whitelist obtains the whitelist entries. +func (g *WhitelistGateway) Whitelist(_ *struct{}, out *[]cipher.PubKey) error { + pks, err := g.wl.All() + if err != nil { + return err + } + *out = make([]cipher.PubKey, 0, len(pks)) + for pk, ok := range pks { + if ok { + *out = append(*out, pk) + } + } + return nil +} + +// WhitelistAdd adds a whitelist entry. +func (g *WhitelistGateway) WhitelistAdd(in *[]cipher.PubKey, _ *struct{}) error { + return g.wl.Add(*in...) +} + +// WhitelistRemove removes a whitelist entry. +func (g *WhitelistGateway) WhitelistRemove(in *[]cipher.PubKey, _ *struct{}) error { + return g.wl.Remove(*in...) +} diff --git a/vendor/github.com/skycoin/dmsg/entity_common.go b/vendor/github.com/skycoin/dmsg/entity_common.go index ec5410f8..b43780cc 100644 --- a/vendor/github.com/skycoin/dmsg/entity_common.go +++ b/vendor/github.com/skycoin/dmsg/entity_common.go @@ -12,6 +12,8 @@ import ( "github.com/skycoin/dmsg/cipher" "github.com/skycoin/dmsg/disc" "github.com/skycoin/dmsg/netutil" + + "github.com/skycoin/skycoin/src/util/logging" ) // EntityCommon contains the common fields and methods for server and client entities. @@ -28,7 +30,8 @@ type EntityCommon struct { updateInterval time.Duration // Minimum duration between discovery entry updates. - log logrus.FieldLogger + log logrus.FieldLogger + mlog *logging.MasterLogger setSessionCallback func(ctx context.Context) error delSessionCallback func(ctx context.Context) error @@ -60,6 +63,13 @@ func (c *EntityCommon) Logger() logrus.FieldLogger { return c.log } // This should be called before we serve. func (c *EntityCommon) SetLogger(log logrus.FieldLogger) { c.log = log } +// MasterLogger obtains the master logger. +func (c *EntityCommon) MasterLogger() *logging.MasterLogger { return c.mlog } + +// SetMasterLogger sets the internal master logger. +// This should be called before we serve. +func (c *EntityCommon) SetMasterLogger(mlog *logging.MasterLogger) { c.mlog = mlog } + func (c *EntityCommon) session(pk cipher.PubKey) (*SessionCommon, bool) { c.sessionsMx.Lock() dSes, ok := c.sessions[pk] diff --git a/vendor/github.com/skycoin/skywire/internal/httpauth/client.go b/vendor/github.com/skycoin/skywire/internal/httpauth/client.go index ea4a8250..e10082f1 100644 --- a/vendor/github.com/skycoin/skywire/internal/httpauth/client.go +++ b/vendor/github.com/skycoin/skywire/internal/httpauth/client.go @@ -23,8 +23,6 @@ const ( invalidNonceErrorMessage = "SW-Nonce does not match" ) -var log = logging.MustGetLogger("httpauth") - // NextNonceResponse represents a ServeHTTP response for json encoding type NextNonceResponse struct { Edge cipher.PubKey `json:"edge"` @@ -47,14 +45,16 @@ type HTTPError struct { // As Client needs to dial both with reusing address and without it, it uses two http clients: reuseClient and client. type Client struct { // atomic requires 64-bit alignment for struct field access - nonce uint64 - mu sync.Mutex - reqMu sync.Mutex - client *http.Client - reuseClient *http.Client - key cipher.PubKey - sec cipher.SecKey - addr string // sanitized address of the client, which may differ from addr used in NewClient + nonce uint64 + mu sync.Mutex + reqMu sync.Mutex + client *http.Client + reuseClient *http.Client + key cipher.PubKey + sec cipher.SecKey + addr string // sanitized address of the client, which may differ from addr used in NewClient + clientPublicIP string // public ip of the local client needed as a header for dmsghttp + log *logging.Logger } // NewClient creates a new client setting a public key to the client to be used for Auth. @@ -63,13 +63,16 @@ type Client struct { // * SW-Public: The specified public key // * SW-Nonce: The nonce for that public key // * SW-Sig: The signature of the payload + the nonce -func NewClient(ctx context.Context, addr string, key cipher.PubKey, sec cipher.SecKey, client *http.Client) (*Client, error) { +func NewClient(ctx context.Context, addr string, key cipher.PubKey, sec cipher.SecKey, client *http.Client, clientPublicIP string, + mLog *logging.MasterLogger) (*Client, error) { c := &Client{ - client: client, - reuseClient: client, - key: key, - sec: sec, - addr: sanitizedAddr(addr), + client: client, + reuseClient: client, + key: key, + sec: sec, + addr: sanitizedAddr(addr), + clientPublicIP: clientPublicIP, + log: mLog.PackageLogger("httpauth"), } // request server for a nonce @@ -97,6 +100,9 @@ func (c *Client) Header() (http.Header, error) { header.Set("SW-Nonce", strconv.FormatUint(uint64(nonce), 10)) header.Set("SW-Sig", sign.Hex()) header.Set("SW-Public", c.key.Hex()) + if c.clientPublicIP != "" { + header.Set("SW-PublicIP", c.clientPublicIP) + } return header, nil } @@ -118,7 +124,7 @@ func (c *Client) do(client *http.Client, req *http.Request) (*http.Response, err return nil, err } if err := req.Body.Close(); err != nil { - log.WithError(err).Warn("Failed to close HTTP request body") + c.log.WithError(err).Warn("Failed to close HTTP request body") } req.Body = ioutil.NopCloser(bytes.NewBuffer(auxBody)) body = auxBody @@ -129,7 +135,7 @@ func (c *Client) do(client *http.Client, req *http.Request) (*http.Response, err return nil, err } - isNonceValid, err := isNonceValid(resp) + resp, isNonceValid, err := isNonceValid(resp) if err != nil { return nil, err } @@ -142,7 +148,7 @@ func (c *Client) do(client *http.Client, req *http.Request) (*http.Response, err c.SetNonce(nonce) if err := resp.Body.Close(); err != nil { - log.WithError(err).Warn("Failed to close HTTP response body") + c.log.WithError(err).Warn("Failed to close HTTP response body") } req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) @@ -178,7 +184,7 @@ func (c *Client) Nonce(ctx context.Context, key cipher.PubKey) (Nonce, error) { defer func() { if err := resp.Body.Close(); err != nil { - log.WithError(err).Warn("Failed to close HTTP response body") + c.log.WithError(err).Warn("Failed to close HTTP response body") } }() @@ -231,6 +237,9 @@ func (c *Client) doRequest(client *http.Client, req *http.Request, body []byte) req.Header.Set("SW-Nonce", strconv.FormatUint(uint64(nonce), 10)) req.Header.Set("SW-Sig", sign.Hex()) req.Header.Set("SW-Public", c.key.Hex()) + if c.clientPublicIP != "" { + req.Header.Set("SW-PublicIP", c.clientPublicIP) + } c.mu.Lock() defer c.mu.Unlock() @@ -250,26 +259,28 @@ func (c *Client) IncrementNonce() { // isNonceValid checks if `res` contains an invalid nonce error. // The error is occurred if status code equals to `http.StatusUnauthorized` // and body contains `invalidNonceErrorMessage`. -func isNonceValid(res *http.Response) (bool, error) { +func isNonceValid(res *http.Response) (*http.Response, bool, error) { var serverResponse HTTPResponse + var auxResp http.Response auxRespBody, err := ioutil.ReadAll(res.Body) if err != nil { - return false, err + return nil, false, err } if err := res.Body.Close(); err != nil { - return false, err + return nil, false, err } - res.Body = ioutil.NopCloser(bytes.NewBuffer(auxRespBody)) + auxResp = *res + auxResp.Body = ioutil.NopCloser(bytes.NewBuffer(auxRespBody)) if err := json.Unmarshal(auxRespBody, &serverResponse); err != nil || serverResponse.Error == nil { - return true, nil + return &auxResp, true, nil } isAuthorized := serverResponse.Error.Code != http.StatusUnauthorized hasValidNonce := serverResponse.Error.Message != invalidNonceErrorMessage - return isAuthorized && hasValidNonce, nil + return &auxResp, isAuthorized && hasValidNonce, nil } func sanitizedAddr(addr string) string { diff --git a/vendor/github.com/skycoin/skywire/internal/netutil/netutil.go b/vendor/github.com/skycoin/skywire/internal/netutil/netutil.go index 0c2e7bf4..98a84074 100644 --- a/vendor/github.com/skycoin/skywire/internal/netutil/netutil.go +++ b/vendor/github.com/skycoin/skywire/internal/netutil/netutil.go @@ -1,6 +1,10 @@ package netutil -import "net" +import ( + "io" + "net" + "net/http" +) // LocalAddresses returns a list of all local addresses func LocalAddresses() ([]string, error) { @@ -26,3 +30,19 @@ func LocalAddresses() ([]string, error) { return result, nil } + +// LocalProtocol check a condition to use dmsghttp or direct url +func LocalProtocol() bool { + resp, err := http.Get("https://ipinfo.io/country") + if err != nil { + return false + } + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return false + } + if string(respBody)[:2] == "CN" { + return true + } + return false +} diff --git a/vendor/github.com/skycoin/skywire/internal/packetfilter/address-filter.go b/vendor/github.com/skycoin/skywire/internal/packetfilter/address-filter.go index 50ff9d88..fb62f94e 100644 --- a/vendor/github.com/skycoin/skywire/internal/packetfilter/address-filter.go +++ b/vendor/github.com/skycoin/skywire/internal/packetfilter/address-filter.go @@ -13,9 +13,9 @@ type AddressFilter struct { } // NewAddressFilter returns a new AddressFilter. -func NewAddressFilter(addr net.Addr) *AddressFilter { +func NewAddressFilter(addr net.Addr, mLog *logging.MasterLogger) *AddressFilter { return &AddressFilter{ - log: logging.MustGetLogger("address-filter"), + log: mLog.PackageLogger("address-filter"), addr: addr, } } diff --git a/vendor/github.com/skycoin/skywire/internal/packetfilter/kcp-filter.go b/vendor/github.com/skycoin/skywire/internal/packetfilter/kcp-filter.go index 9036ef3a..0f42fb63 100644 --- a/vendor/github.com/skycoin/skywire/internal/packetfilter/kcp-filter.go +++ b/vendor/github.com/skycoin/skywire/internal/packetfilter/kcp-filter.go @@ -21,9 +21,9 @@ type KCPConversationFilter struct { } // NewKCPConversationFilter returns a new KCPConversationFilter. -func NewKCPConversationFilter() *KCPConversationFilter { +func NewKCPConversationFilter(mLog *logging.MasterLogger) *KCPConversationFilter { return &KCPConversationFilter{ - log: logging.MustGetLogger("kcp-filter"), + log: mLog.PackageLogger("kcp-filter"), } } diff --git a/vendor/github.com/skycoin/skywire/pkg/app/appcommon/log_store.go b/vendor/github.com/skycoin/skywire/pkg/app/appcommon/log_store.go index 2bdb2e9e..c6085768 100644 --- a/vendor/github.com/skycoin/skywire/pkg/app/appcommon/log_store.go +++ b/vendor/github.com/skycoin/skywire/pkg/app/appcommon/log_store.go @@ -21,13 +21,13 @@ const ( var re = regexp.MustCompile("[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))") // NewProcLogger returns a new proc logger. -func NewProcLogger(conf ProcConfig) (*logging.MasterLogger, LogStore) { +func NewProcLogger(conf ProcConfig, mLog *logging.MasterLogger) (log *logging.MasterLogger, db LogStore) { db, err := NewBBoltLogStore(conf.LogDBLoc, conf.AppName) if err != nil { panic(err) } + log = mLog - log := logging.NewMasterLogger() log.Logger.AddHook(db) return log, db diff --git a/vendor/github.com/skycoin/skywire/pkg/app/appdisc/factory.go b/vendor/github.com/skycoin/skywire/pkg/app/appdisc/factory.go index f015615e..ad0bc631 100644 --- a/vendor/github.com/skycoin/skywire/pkg/app/appdisc/factory.go +++ b/vendor/github.com/skycoin/skywire/pkg/app/appdisc/factory.go @@ -14,11 +14,13 @@ import ( // Factory creates appdisc.Updater instances based on the app name. type Factory struct { - Log logrus.FieldLogger - PK cipher.PubKey - SK cipher.SecKey - ServiceDisc string // Address of service-discovery - Client http.Client + Log logrus.FieldLogger + MLog *logging.MasterLogger + PK cipher.PubKey + SK cipher.SecKey + ServiceDisc string // Address of service-discovery + Client *http.Client + ClientPublicIP string } func (f *Factory) setDefaults() { @@ -46,7 +48,7 @@ func (f *Factory) VisorUpdater(port uint16) Updater { } return &serviceUpdater{ - client: servicedisc.NewClient(f.Log, conf, f.Client), + client: servicedisc.NewClient(f.Log, f.MLog, conf, f.Client, f.ClientPublicIP), } } @@ -77,11 +79,11 @@ func (f *Factory) AppUpdater(conf appcommon.ProcConfig) (Updater, bool) { switch conf.AppName { case skyenv.VPNServerName: return &serviceUpdater{ - client: servicedisc.NewClient(log, getServiceDiscConf(conf, servicedisc.ServiceTypeVPN), f.Client), + client: servicedisc.NewClient(log, f.MLog, getServiceDiscConf(conf, servicedisc.ServiceTypeVPN), f.Client, f.ClientPublicIP), }, true case skyenv.SkysocksName: return &serviceUpdater{ - client: servicedisc.NewClient(log, getServiceDiscConf(conf, servicedisc.ServiceTypeSkysocks), f.Client), + client: servicedisc.NewClient(log, f.MLog, getServiceDiscConf(conf, servicedisc.ServiceTypeSkysocks), f.Client, f.ClientPublicIP), }, true default: return &emptyUpdater{}, false diff --git a/vendor/github.com/skycoin/skywire/pkg/app/appevent/broadcaster.go b/vendor/github.com/skycoin/skywire/pkg/app/appevent/broadcaster.go index db97bf76..664bf271 100644 --- a/vendor/github.com/skycoin/skywire/pkg/app/appevent/broadcaster.go +++ b/vendor/github.com/skycoin/skywire/pkg/app/appevent/broadcaster.go @@ -69,11 +69,13 @@ func (mc *Broadcaster) Broadcast(ctx context.Context, e *Event) error { // Delete inactive clients and associated error channels. for client, errCh := range mc.clients { if err := <-errCh; err != nil { - mc.log. - WithError(err). - WithField("close_error", client.Close()). - WithField("hello", client.Hello().String()). - Warn("Events RPC client closed due to error.") + if err.Error() != "connection is shut down" { + mc.log. + WithError(err). + WithField("close_error", client.Close()). + WithField("hello", client.Hello().String()). + Warn("Events RPC client closed due to error.") + } delete(mc.clients, client) close(errCh) diff --git a/vendor/github.com/skycoin/skywire/pkg/app/appserver/proc.go b/vendor/github.com/skycoin/skywire/pkg/app/appserver/proc.go index 9a0cab4a..bb5acceb 100644 --- a/vendor/github.com/skycoin/skywire/pkg/app/appserver/proc.go +++ b/vendor/github.com/skycoin/skywire/pkg/app/appserver/proc.go @@ -7,16 +7,19 @@ import ( "net/rpc" "os" "os/exec" + "runtime" "strings" "sync" "sync/atomic" "time" + ipc "github.com/james-barrow/golang-ipc" "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/skywire/pkg/app/appcommon" "github.com/skycoin/skywire/pkg/app/appdisc" "github.com/skycoin/skywire/pkg/app/appnet" + "github.com/skycoin/skywire/pkg/skyenv" ) var ( @@ -28,9 +31,10 @@ var ( // communication. // TODO(evanlinjin): In the future, we will implement the ability to run multiple instances (procs) of a single app. type Proc struct { - disc appdisc.Updater // app discovery client - conf appcommon.ProcConfig - log *logging.Logger + ipcServer *ipc.Server + disc appdisc.Updater // app discovery client + conf appcommon.ProcConfig + log *logging.Logger logDB appcommon.LogStore @@ -76,11 +80,11 @@ func NewProc(mLog *logging.MasterLogger, conf appcommon.ProcConfig, disc appdisc cmd.Env = append(os.Environ(), envs...) cmd.Dir = conf.ProcWorkDir - appLog, appLogDB := appcommon.NewProcLogger(conf) + appLog, appLogDB := appcommon.NewProcLogger(conf, mLog) cmd.Stdout = appLog.WithField("_module", moduleName).WithField("func", "(STDOUT)").Writer() cmd.Stderr = appLog.WithField("_module", moduleName).WithField("func", "(STDERR)").Writer() - return &Proc{ + p := &Proc{ disc: disc, conf: conf, log: mLog.PackageLogger(moduleName), @@ -90,6 +94,7 @@ func NewProc(mLog *logging.MasterLogger, conf appcommon.ProcConfig, disc appdisc m: m, appName: appName, } + return p } // Logs obtains the log store. @@ -215,6 +220,16 @@ func (p *Proc) Start() error { p.disc.Start() defer p.disc.Stop() + if runtime.GOOS == "windows" { + ipcServer, err := ipc.StartServer(p.appName, nil) + if err != nil { + _ = p.cmd.Process.Kill() //nolint:errcheck + p.waitMx.Unlock() + return + } + p.ipcServer = ipcServer + } + // Wait for proc to exit. p.waitErr = <-waitErrCh @@ -239,9 +254,15 @@ func (p *Proc) Stop() error { } if p.cmd.Process != nil { - err := p.cmd.Process.Signal(os.Interrupt) - if err != nil { - return err + if runtime.GOOS != "windows" { + err := p.cmd.Process.Signal(os.Interrupt) + if err != nil { + return err + } + } else { + if err := p.ipcServer.Write(skyenv.IPCShutdownMessageType, []byte("")); err != nil { + return err + } } } @@ -251,6 +272,9 @@ func (p *Proc) Stop() error { // the lock will be acquired as soon as the cmd finishes its work p.waitMx.Lock() defer func() { + if p.ipcServer != nil { + p.ipcServer.Close() + } p.waitMx.Unlock() p.connOnce.Do(func() { close(p.connCh) }) }() diff --git a/vendor/github.com/skycoin/skywire/pkg/app/launcher/launcher.go b/vendor/github.com/skycoin/skywire/pkg/app/launcher/launcher.go index 87f89893..85763f57 100644 --- a/vendor/github.com/skycoin/skywire/pkg/app/launcher/launcher.go +++ b/vendor/github.com/skycoin/skywire/pkg/app/launcher/launcher.go @@ -356,12 +356,8 @@ func (l *Launcher) killHangingProcesses() error { if err != nil { return err } - defer func() { - if err := pidF.Close(); err != nil { - log.WithError(err).Warn("Error closing PID file.") - } - }() - log = log.WithField("pid_file", pidF.Name()) + filename := pidF.Name() + log = log.WithField("pid_file", filename) scan := bufio.NewScanner(pidF) for scan.Scan() { @@ -378,9 +374,12 @@ func (l *Launcher) killHangingProcesses() error { l.killHangingProc(appInfo[0], pid) } + if err = pidF.Close(); err != nil { + log.WithError(err).Error("Failed to close file") + } // empty file - if err := pathutil.AtomicWriteFile(pidF.Name(), []byte{}); err != nil { + if err = pathutil.AtomicWriteFile(filename, []byte{}); err != nil { log.WithError(err).Error("Failed to empty pid file.") } diff --git a/vendor/github.com/skycoin/skywire/pkg/dmsgc/dmsgc.go b/vendor/github.com/skycoin/skywire/pkg/dmsgc/dmsgc.go index 7eeb35dc..25a36420 100644 --- a/vendor/github.com/skycoin/skywire/pkg/dmsgc/dmsgc.go +++ b/vendor/github.com/skycoin/skywire/pkg/dmsgc/dmsgc.go @@ -20,7 +20,7 @@ type DmsgConfig struct { } // New makes new dmsg client from configuration -func New(pk cipher.PubKey, sk cipher.SecKey, eb *appevent.Broadcaster, conf *DmsgConfig, httpC http.Client) *dmsg.Client { +func New(pk cipher.PubKey, sk cipher.SecKey, eb *appevent.Broadcaster, conf *DmsgConfig, httpC *http.Client, masterLogger *logging.MasterLogger) *dmsg.Client { dmsgConf := &dmsg.Config{ MinSessions: conf.SessionsCount, Callbacks: &dmsg.ClientCallbacks{ @@ -38,8 +38,8 @@ func New(pk cipher.PubKey, sk cipher.SecKey, eb *appevent.Broadcaster, conf *Dms }, }, } - - dmsgC := dmsg.NewClient(pk, sk, disc.NewHTTP(conf.Discovery, httpC), dmsgConf) - dmsgC.SetLogger(logging.MustGetLogger("dmsgC")) + dmsgC := dmsg.NewClient(pk, sk, disc.NewHTTP(conf.Discovery, httpC, masterLogger.PackageLogger("dmsgC:disc")), dmsgConf) + dmsgC.SetLogger(masterLogger.PackageLogger("dmsgC")) + dmsgC.SetMasterLogger(masterLogger) return dmsgC } diff --git a/vendor/github.com/skycoin/skywire/pkg/restart/restart.go b/vendor/github.com/skycoin/skywire/pkg/restart/restart.go index 66d7bcec..672467d5 100644 --- a/vendor/github.com/skycoin/skywire/pkg/restart/restart.go +++ b/vendor/github.com/skycoin/skywire/pkg/restart/restart.go @@ -9,7 +9,6 @@ import ( "os/signal" "strings" "sync/atomic" - "syscall" "time" "github.com/shirou/gopsutil/v3/process" @@ -111,11 +110,9 @@ func (c *Context) Systemd() bool { // Restart restarts an executable using Context. // If the process is supervised by systemd, it lets systemd restart the process. func (c *Context) Restart() (err error) { - // SIGTTIN and SIGTTOU need to be ignored to make Foreground flag of syscall.SysProcAttr work. - // https://github.com/golang/go/issues/37217 - signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU) + c.ignoreSignals() - if err := c.start(); err != nil { + if err = c.start(); err != nil { return err } diff --git a/vendor/github.com/skycoin/skywire/pkg/restart/restart_unix.go b/vendor/github.com/skycoin/skywire/pkg/restart/restart_unix.go index 996efb01..0b4b70f1 100644 --- a/vendor/github.com/skycoin/skywire/pkg/restart/restart_unix.go +++ b/vendor/github.com/skycoin/skywire/pkg/restart/restart_unix.go @@ -6,6 +6,7 @@ package restart import ( "os" "os/exec" + "os/signal" "syscall" ) @@ -80,3 +81,9 @@ func pgidExists(pgid int) bool { n, err := syscall.Getpgid(pgid) return err == nil && n >= 0 } + +func (c *Context) ignoreSignals() { + // SIGTTIN and SIGTTOU need to be ignored to make Foreground flag of syscall.SysProcAttr work. + // https://github.com/golang/go/issues/37217 + signal.Ignore(syscall.SIGTTIN, syscall.SIGTTOU) +} diff --git a/vendor/github.com/skycoin/skywire/pkg/restart/restart_windows.go b/vendor/github.com/skycoin/skywire/pkg/restart/restart_windows.go index 5215e77a..1f68093b 100644 --- a/vendor/github.com/skycoin/skywire/pkg/restart/restart_windows.go +++ b/vendor/github.com/skycoin/skywire/pkg/restart/restart_windows.go @@ -3,10 +3,13 @@ package restart -import "os/exec" +import ( + "os/exec" +) -func attachTTY(*exec.Cmd) { +func attachTTY(_ *exec.Cmd) { // not used for Windows +} - return +func (c *Context) ignoreSignals() { } diff --git a/vendor/github.com/skycoin/skywire/pkg/routefinder/rfclient/client.go b/vendor/github.com/skycoin/skywire/pkg/routefinder/rfclient/client.go index 700c83e2..36bffad2 100644 --- a/vendor/github.com/skycoin/skywire/pkg/routefinder/rfclient/client.go +++ b/vendor/github.com/skycoin/skywire/pkg/routefinder/rfclient/client.go @@ -20,8 +20,6 @@ import ( const defaultContextTimeout = 10 * time.Second -var log = logging.MustGetLogger("routefinder") - // ErrTransportNotFound is returned when transport is not found. var ErrTransportNotFound = errors.New("transport not found") @@ -57,20 +55,25 @@ type Client interface { // APIClient implements Client interface type apiClient struct { addr string - client http.Client + client *http.Client apiTimeout time.Duration + log *logging.Logger } // NewHTTP constructs new Client that communicates over http. -func NewHTTP(addr string, apiTimeout time.Duration, client http.Client) Client { +func NewHTTP(addr string, apiTimeout time.Duration, client *http.Client, mlogger *logging.MasterLogger) Client { if apiTimeout == 0 { apiTimeout = defaultContextTimeout } - + log := logging.MustGetLogger("routefinder") + if mlogger != nil { + log = mlogger.PackageLogger("routefinder") + } return &apiClient{ addr: sanitizedAddr(addr), client: client, apiTimeout: apiTimeout, + log: log, } } @@ -102,7 +105,7 @@ func (c *apiClient) FindRoutes(ctx context.Context, rts []routing.PathEdges, opt if res != nil { defer func() { if err := res.Body.Close(); err != nil { - log.WithError(err).Warn("Failed to close HTTP response body") + c.log.WithError(err).Warn("Failed to close HTTP response body") } }() } diff --git a/vendor/github.com/skycoin/skywire/pkg/router/route_group.go b/vendor/github.com/skycoin/skywire/pkg/router/route_group.go index 6920d996..50abd8a3 100644 --- a/vendor/github.com/skycoin/skywire/pkg/router/route_group.go +++ b/vendor/github.com/skycoin/skywire/pkg/router/route_group.go @@ -116,14 +116,17 @@ type RouteGroup struct { } // NewRouteGroup creates a new RouteGroup. -func NewRouteGroup(cfg *RouteGroupConfig, rt routing.Table, desc routing.RouteDescriptor) *RouteGroup { +func NewRouteGroup(cfg *RouteGroupConfig, rt routing.Table, desc routing.RouteDescriptor, mLoggger *logging.MasterLogger) *RouteGroup { if cfg == nil { cfg = DefaultRouteGroupConfig() } - + logger := logging.MustGetLogger(fmt.Sprintf("RouteGroup %s", desc.String())) + if mLoggger != nil { + logger = mLoggger.PackageLogger(fmt.Sprintf("RouteGroup %s", desc.String())) + } rg := &RouteGroup{ cfg: cfg, - logger: logging.MustGetLogger(fmt.Sprintf("RouteGroup %s", desc.String())), + logger: logger, desc: desc, rt: rt, tps: make([]*transport.ManagedTransport, 0), diff --git a/vendor/github.com/skycoin/skywire/pkg/router/router.go b/vendor/github.com/skycoin/skywire/pkg/router/router.go index 08fad385..44604ef0 100644 --- a/vendor/github.com/skycoin/skywire/pkg/router/router.go +++ b/vendor/github.com/skycoin/skywire/pkg/router/router.go @@ -52,9 +52,17 @@ var ( ErrNoTransportFound = errors.New("no transport found") ) +// RouteSetupHook is an alias for a function that takes remote public key +// and a reference to transport manager in order to setup i.e: +// 1. If the remote is either available stcpr or sudph, establish the transport to the remote and then continue with the route creation process. +// 2. If neither of these direct transports is available, check if automatic transports are currently active. If they are continue with route creation. +// 3. If none of the first two checks was successful, establish a dmsg transport and then continue with route creation. +type RouteSetupHook func(cipher.PubKey, *transport.Manager) error + // Config configures Router. type Config struct { Logger *logging.Logger + MasterLogger *logging.MasterLogger PubKey cipher.PubKey SecKey cipher.SecKey TransportManager *transport.Manager @@ -143,24 +151,27 @@ type Router interface { // communicating with setup nodes, forward packets according to local // rules and manages route groups for apps. type router struct { - mx sync.Mutex - conf *Config - logger *logging.Logger - sl *dmsg.Listener - dmsgC *dmsg.Client - trustedVisors map[cipher.PubKey]struct{} - tm *transport.Manager - rt routing.Table - rgsNs map[routing.RouteDescriptor]*NoiseRouteGroup // Noise-wrapped route groups to push incoming reads from transports. - rgsRaw map[routing.RouteDescriptor]*RouteGroup // Not-yet-noise-wrapped route groups. when one of these gets wrapped, it gets removed from here - rpcSrv *rpc.Server - accept chan routing.EdgeRules - done chan struct{} - once sync.Once + mx sync.Mutex + conf *Config + logger *logging.Logger + mLogger *logging.MasterLogger + sl *dmsg.Listener + dmsgC *dmsg.Client + trustedVisors map[cipher.PubKey]struct{} + tm *transport.Manager + rt routing.Table + rgsNs map[routing.RouteDescriptor]*NoiseRouteGroup // Noise-wrapped route groups to push incoming reads from transports. + rgsRaw map[routing.RouteDescriptor]*RouteGroup // Not-yet-noise-wrapped route groups. when one of these gets wrapped, it gets removed from here + rpcSrv *rpc.Server + accept chan routing.EdgeRules + done chan struct{} + once sync.Once + routeSetupHookMu sync.Mutex + routeSetupHooks []RouteSetupHook // see RouteSetupHook description } // New constructs a new Router. -func New(dmsgC *dmsg.Client, config *Config) (Router, error) { +func New(dmsgC *dmsg.Client, config *Config, routeSetupHooks []RouteSetupHook) (Router, error) { config.SetDefaults() sl, err := dmsgC.Listen(skyenv.DmsgAwaitSetupPort) @@ -173,30 +184,44 @@ func New(dmsgC *dmsg.Client, config *Config) (Router, error) { trustedVisors[node] = struct{}{} } + if routeSetupHooks == nil { + routeSetupHooks = []RouteSetupHook{} + } + r := &router{ - conf: config, - logger: config.Logger, - tm: config.TransportManager, - rt: routing.NewTable(), - sl: sl, - dmsgC: dmsgC, - rgsNs: make(map[routing.RouteDescriptor]*NoiseRouteGroup), - rgsRaw: make(map[routing.RouteDescriptor]*RouteGroup), - rpcSrv: rpc.NewServer(), - accept: make(chan routing.EdgeRules, acceptSize), - done: make(chan struct{}), - trustedVisors: trustedVisors, + conf: config, + logger: config.Logger, + mLogger: config.MasterLogger, + tm: config.TransportManager, + rt: routing.NewTable(), + sl: sl, + dmsgC: dmsgC, + rgsNs: make(map[routing.RouteDescriptor]*NoiseRouteGroup), + rgsRaw: make(map[routing.RouteDescriptor]*RouteGroup), + rpcSrv: rpc.NewServer(), + accept: make(chan routing.EdgeRules, acceptSize), + done: make(chan struct{}), + trustedVisors: trustedVisors, + routeSetupHooks: routeSetupHooks, } go r.rulesGCLoop() - if err := r.rpcSrv.Register(NewRPCGateway(r)); err != nil { + if err := r.rpcSrv.Register(NewRPCGateway(r, config.MasterLogger)); err != nil { return nil, fmt.Errorf("failed to register RPC server") } return r, nil } +// RegisterSetupHooks takes variadic RouteSetupHook to add to router's setup functions +// currently not in use +func (r *router) RegisterSetupHooks(rshooks ...RouteSetupHook) { + r.routeSetupHookMu.Lock() + r.routeSetupHooks = append(r.routeSetupHooks, rshooks...) + r.routeSetupHookMu.Unlock() +} + // DialRoutes dials to a given visor of 'rPK'. // 'lPort'/'rPort' specifies the local/remote ports respectively. // A nil 'opts' input results in a value of '1' for all DialOptions fields. @@ -221,6 +246,17 @@ func (r *router) DialRoutes( lPK := r.conf.PubKey forwardDesc := routing.NewRouteDescriptor(lPK, rPK, lPort, rPort) + r.routeSetupHookMu.Lock() + defer r.routeSetupHookMu.Unlock() + if len(r.routeSetupHooks) != 0 { + for _, rsf := range r.routeSetupHooks { + if err := rsf(rPK, r.tm); err != nil { + return nil, err + } + } + } + + // check if transports are available ok := r.checkIfTransportAvalailable() if !ok { return nil, ErrNoTransportFound @@ -268,7 +304,7 @@ func (r *router) DialRoutes( return nrg, nil } -// AcceptsRoutes should block until we receive an AddRules packet from SetupNode +// AcceptRoutes should block until we receive an AddRules packet from SetupNode // that contains ConsumeRule(s) or ForwardRule(s). // Then the following should happen: // - Save to routing.Table and internal RouteGroup map. @@ -398,7 +434,7 @@ func (r *router) saveRouteGroupRules(rules routing.EdgeRules, nsConf noise.Confi nrg, ok := r.rgsNs[rules.Desc] r.logger.Infof("Creating new route group rule with desc: %s", &rules.Desc) - rg := NewRouteGroup(DefaultRouteGroupConfig(), r.rt, rules.Desc) + rg := NewRouteGroup(DefaultRouteGroupConfig(), r.rt, rules.Desc, r.mLogger) rg.appendRules(rules.Forward, rules.Reverse, r.tm.Transport(rules.Forward.NextTransportID())) // we put raw rg so it can be accessible to the router when handshake packets come in r.rgsRaw[rules.Desc] = rg @@ -1042,7 +1078,7 @@ func (r *router) removeRouteGroupOfRule(rule routing.Rule) { func (r *router) checkIfTransportAvalailable() (ok bool) { r.tm.WalkTransports(func(tp *transport.ManagedTransport) bool { ok = true - return true + return ok }) return ok } diff --git a/vendor/github.com/skycoin/skywire/pkg/router/rpc_gateway.go b/vendor/github.com/skycoin/skywire/pkg/router/rpc_gateway.go index 1ad26fc3..defd1d33 100644 --- a/vendor/github.com/skycoin/skywire/pkg/router/rpc_gateway.go +++ b/vendor/github.com/skycoin/skywire/pkg/router/rpc_gateway.go @@ -13,9 +13,9 @@ type RPCGateway struct { } // NewRPCGateway creates a new RPCGateway. -func NewRPCGateway(router Router) *RPCGateway { +func NewRPCGateway(router Router, mLog *logging.MasterLogger) *RPCGateway { return &RPCGateway{ - logger: logging.MustGetLogger("router-gateway"), + logger: mLog.PackageLogger("router-gateway"), router: router, } } diff --git a/vendor/github.com/skycoin/skywire/pkg/servicedisc/autoconnect.go b/vendor/github.com/skycoin/skywire/pkg/servicedisc/autoconnect.go index 90a501ef..26f5aa25 100644 --- a/vendor/github.com/skycoin/skywire/pkg/servicedisc/autoconnect.go +++ b/vendor/github.com/skycoin/skywire/pkg/servicedisc/autoconnect.go @@ -2,9 +2,12 @@ package servicedisc import ( "context" + "errors" + "io" "net/http" "time" + "github.com/sirupsen/logrus" "github.com/skycoin/dmsg/cipher" "github.com/skycoin/skycoin/src/util/logging" @@ -38,9 +41,10 @@ type autoconnector struct { // MakeConnector returns a new connector that will try to connect to at most maxConns // services -func MakeConnector(conf Config, maxConns int, tm *transport.Manager, httpC http.Client, log *logging.Logger) Autoconnector { +func MakeConnector(conf Config, maxConns int, tm *transport.Manager, httpC *http.Client, clientPublicIP string, + log *logging.Logger, mLog *logging.MasterLogger) Autoconnector { connector := &autoconnector{} - connector.client = NewClient(log, conf, httpC) + connector.client = NewClient(log, mLog, conf, httpC, clientPublicIP) connector.maxConns = maxConns connector.log = log connector.tm = tm @@ -78,17 +82,28 @@ func (a *autoconnector) Run(ctx context.Context) (err error) { if !ok || val < maxFailedAddressRetryAttempt { a.log.WithField("pk", pk).WithField("attempt", val).Debugln("Trying to add transport to public visor") logger := a.log.WithField("pk", pk).WithField("type", string(network.STCPR)) - if _, err := a.tm.SaveTransport(ctx, pk, network.STCPR, transport.LabelAutomatic); err != nil { - logger.WithError(err).Warnln("Failed to add transport to public visor") + if err = a.tryEstablishTransport(ctx, pk, logger); err != nil { + if !errors.Is(err, io.ErrClosedPipe) { + logger.WithError(err).Warnln("Failed to add transport to public visor") + } failedAddresses[pk]++ continue } - logger.Infoln("Added transport to public visor") } } } } +// tryEstablish transport will try to establish transport to the remote pk via STCPR or SUDPH, if both failed, return error. +func (a *autoconnector) tryEstablishTransport(ctx context.Context, pk cipher.PubKey, logger *logrus.Entry) error { + if _, err := a.tm.SaveTransport(ctx, pk, network.STCPR, transport.LabelAutomatic); err != nil { + return err + } + + logger.Debugln("Added transport to public visor") + return nil +} + func (a *autoconnector) fetchPubAddresses(ctx context.Context) ([]cipher.PubKey, error) { retrier := netutil.NewRetrier(fetchServicesDelay, 5, 3, a.log) var services []Service diff --git a/vendor/github.com/skycoin/skywire/pkg/servicedisc/client.go b/vendor/github.com/skycoin/skywire/pkg/servicedisc/client.go index 892c83fc..14443991 100644 --- a/vendor/github.com/skycoin/skywire/pkg/servicedisc/client.go +++ b/vendor/github.com/skycoin/skywire/pkg/servicedisc/client.go @@ -16,6 +16,7 @@ import ( "github.com/sirupsen/logrus" "github.com/skycoin/dmsg/buildinfo" "github.com/skycoin/dmsg/cipher" + "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/skywire/internal/httpauth" nu "github.com/skycoin/skywire/internal/netutil" @@ -42,24 +43,28 @@ type Config struct { // HTTPClient is responsible for interacting with the service-discovery type HTTPClient struct { - log logrus.FieldLogger - conf Config - entry Service - entryMx sync.Mutex // only used if RegisterEntry && DeleteEntry functions are used. - client http.Client + log logrus.FieldLogger + mLog *logging.MasterLogger + conf Config + entry Service + entryMx sync.Mutex // only used if RegisterEntry && DeleteEntry functions are used. + client *http.Client + clientPublicIP string } // NewClient creates a new HTTPClient. -func NewClient(log logrus.FieldLogger, conf Config, client http.Client) *HTTPClient { +func NewClient(log logrus.FieldLogger, mLog *logging.MasterLogger, conf Config, client *http.Client, clientPublicIP string) *HTTPClient { return &HTTPClient{ log: log, + mLog: mLog, conf: conf, entry: Service{ Addr: NewSWAddr(conf.PK, conf.Port), Type: conf.Type, Version: buildinfo.Version(), }, - client: client, + client: client, + clientPublicIP: clientPublicIP, } } @@ -96,7 +101,7 @@ func (c *HTTPClient) Auth(ctx context.Context) (*httpauth.Client, error) { return auth, nil } - auth, err := httpauth.NewClient(ctx, c.conf.DiscAddr, c.conf.PK, c.conf.SK, &c.client) + auth, err := httpauth.NewClient(ctx, c.conf.DiscAddr, c.conf.PK, c.conf.SK, c.client, c.clientPublicIP, c.mLog) if err != nil { return nil, err } diff --git a/vendor/github.com/skycoin/skywire/pkg/skyenv/values.go b/vendor/github.com/skycoin/skywire/pkg/skyenv/values.go index f3cc8345..0259eb61 100644 --- a/vendor/github.com/skycoin/skywire/pkg/skyenv/values.go +++ b/vendor/github.com/skycoin/skywire/pkg/skyenv/values.go @@ -5,6 +5,7 @@ import ( "time" "github.com/skycoin/dmsg/cipher" + "github.com/skycoin/dmsg/dmsgpty" ) // Constants for skywire root directories. @@ -61,9 +62,8 @@ const ( // Default dmsgpty constants. const ( - DmsgPtyPort uint16 = 22 - DefaultDmsgPtyCLINet = "unix" - DefaultDmsgPtyCLIAddr = "/tmp/dmsgpty.sock" + DmsgPtyPort uint16 = 22 + DefaultDmsgPtyCLINet = "unix" ) // Default Skywire-TCP constants. @@ -71,6 +71,11 @@ const ( DefaultSTCPAddr = ":7777" ) +// DefaultDmsgPtyCLIAddr determines default CLI address per each platform +func DefaultDmsgPtyCLIAddr() string { + return dmsgpty.DefaultCLIAddr() +} + // Default skywire app constants. const ( SkychatName = "skychat" @@ -134,13 +139,18 @@ const ( // Default hypervisor constants const ( DefaultHypervisorDB = ".skycoin/hypervisor/users.db" - DefaultEnableAuth = true - DefaultPackageEnableAuth = false + DefaultEnableAuth = false + DefaultPackageEnableAuth = true DefaultEnableTLS = false DefaultTLSKey = DefaultSkywirePath + "/ssl/key.pem" DefaultTLSCert = DefaultSkywirePath + "/ssl/cert.pem" ) +const ( + // IPCShutdownMessageType sends IPC shutdown message type + IPCShutdownMessageType = 68 +) + // PackageLocalPath is the path to local directory func PackageLocalPath() string { return filepath.Join(PackageSkywirePath(), "local") diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/handshake.go b/vendor/github.com/skycoin/skywire/pkg/transport/handshake.go index 40d84d76..7ab1fa16 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/handshake.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/handshake.go @@ -10,6 +10,7 @@ import ( "github.com/skycoin/dmsg/cipher" "github.com/skycoin/dmsg/httputil" + "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/skywire/pkg/transport/network" ) @@ -93,7 +94,7 @@ func (hs SettlementHS) Do(ctx context.Context, dc DiscoveryClient, transport net // MakeSettlementHS creates a settlement handshake. // `init` determines whether the local side is initiating or responding. // The handshake logic only REGISTERS the transport, and does not update the status of the transport. -func MakeSettlementHS(init bool) SettlementHS { +func MakeSettlementHS(init bool, log *logging.Logger) SettlementHS { // initiating logic. initHS := func(ctx context.Context, dc DiscoveryClient, transport network.Transport, sk cipher.SecKey) (err error) { entry := makeEntryFromTransport(transport) diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/log.go b/vendor/github.com/skycoin/skywire/pkg/transport/log.go index e802ea3a..3705f9d2 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/log.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/log.go @@ -13,6 +13,7 @@ import ( "sync/atomic" "github.com/google/uuid" + "github.com/skycoin/skycoin/src/util/logging" ) // LogEntry represents a logging entry for a given Transport. @@ -111,6 +112,7 @@ func (tls *inMemoryTransportLogStore) Record(id uuid.UUID, entry *LogEntry) erro type fileTransportLogStore struct { dir string + log *logging.Logger } // FileTransportLogStore implements file TransportLogStore. @@ -118,7 +120,8 @@ func FileTransportLogStore(dir string) (LogStore, error) { if err := os.MkdirAll(dir, 0707); err != nil { return nil, err } - return &fileTransportLogStore{dir}, nil + log := logging.MustGetLogger("transport") + return &fileTransportLogStore{dir, log}, nil } func (tls *fileTransportLogStore) Entry(id uuid.UUID) (*LogEntry, error) { @@ -128,7 +131,7 @@ func (tls *fileTransportLogStore) Entry(id uuid.UUID) (*LogEntry, error) { } defer func() { if err := f.Close(); err != nil { - log.WithError(err).Warn("Failed to close file") + tls.log.WithError(err).Warn("Failed to close file") } }() @@ -147,7 +150,7 @@ func (tls *fileTransportLogStore) Record(id uuid.UUID, entry *LogEntry) error { } defer func() { if err := f.Close(); err != nil { - log.WithError(err).Warn("Failed to close file") + tls.log.WithError(err).Warn("Failed to close file") } }() diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/managed_transport.go b/vendor/github.com/skycoin/skywire/pkg/transport/managed_transport.go index 8bf6cfa0..b599dbe7 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/managed_transport.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/managed_transport.go @@ -46,6 +46,7 @@ type ManagedTransportConfig struct { RemotePK cipher.PubKey TransportLabel Label InactiveTimeout time.Duration + mlog *logging.MasterLogger } // ManagedTransport manages a direct line of communication between two visor nodes. @@ -76,8 +77,13 @@ type ManagedTransport struct { // NewManagedTransport creates a new ManagedTransport. func NewManagedTransport(conf ManagedTransportConfig) *ManagedTransport { aPK, bPK := conf.client.PK(), conf.RemotePK + log := logging.MustGetLogger(fmt.Sprintf("tp:%s", conf.RemotePK.String()[:6])) + if conf.mlog != nil { + log = conf.mlog.PackageLogger(fmt.Sprintf("tp:%s", conf.RemotePK.String()[:6])) + } + mt := &ManagedTransport{ - log: logging.MustGetLogger(fmt.Sprintf("tp:%s", conf.RemotePK.String()[:6])), + log: log, rPK: conf.RemotePK, dc: conf.DC, ls: conf.LS, @@ -202,7 +208,7 @@ func (mt *ManagedTransport) close() { close(mt.transportCh) if mt.transport != nil { if err := mt.transport.Close(); err != nil { - log.WithError(err).Warn("Failed to close underlying transport.") + mt.log.WithError(err).Warn("Failed to close underlying transport.") } mt.transport = nil } @@ -233,7 +239,7 @@ func (mt *ManagedTransport) Accept(ctx context.Context, transport network.Transp defer cancel() mt.log.Debug("Performing settlement handshake...") - if err := MakeSettlementHS(false).Do(ctx, mt.dc, transport, mt.client.SK()); err != nil { + if err := MakeSettlementHS(false, mt.log).Do(ctx, mt.dc, transport, mt.client.SK()); err != nil { return fmt.Errorf("settlement handshake failed: %w", err) } @@ -271,7 +277,7 @@ func (mt *ManagedTransport) dial(ctx context.Context) error { ctx, cancel := context.WithTimeout(ctx, time.Second*20) defer cancel() - if err := MakeSettlementHS(true).Do(ctx, mt.dc, transport, mt.client.SK()); err != nil { + if err := MakeSettlementHS(true, mt.log).Do(ctx, mt.dc, transport, mt.client.SK()); err != nil { return fmt.Errorf("settlement handshake failed: %w", err) } @@ -309,14 +315,14 @@ func (mt *ManagedTransport) setTransport(newTransport network.Transport) error { if mt.isLeastSignificantEdge() { mt.log.Debug("Underlying transport already exists, closing new transport.") if err := newTransport.Close(); err != nil { - log.WithError(err).Warn("Failed to close new transport.") + mt.log.WithError(err).Warn("Failed to close new transport.") } return ErrTransportAlreadyExists } mt.log.Debug("Underlying transport already exists, closing old transport.") if err := mt.transport.Close(); err != nil { - log.WithError(err).Warn("Failed to close old transport.") + mt.log.WithError(err).Warn("Failed to close old transport.") } mt.transport = nil } @@ -447,7 +453,7 @@ func (mt *ManagedTransport) recordLog() { return } if err := mt.ls.Record(mt.Entry.ID, mt.LogEntry); err != nil { - log.WithError(err).Warn("Failed to record log entry.") + mt.log.WithError(err).Warn("Failed to record log entry.") } } diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/manager.go b/vendor/github.com/skycoin/skywire/pkg/transport/manager.go index 0e73c847..1824e8d0 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/manager.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/manager.go @@ -301,6 +301,7 @@ func (tm *Manager) acceptTransport(ctx context.Context, lis network.Listener) er RemotePK: transport.RemotePK(), TransportLabel: LabelUser, ebc: tm.ebc, + mlog: tm.factory.MLogger, }) go func() { @@ -427,6 +428,7 @@ func (tm *Manager) saveTransport(ctx context.Context, remote cipher.PubKey, netT LS: tm.Conf.LogStore, RemotePK: remote, TransportLabel: label, + mlog: tm.factory.MLogger, }) tm.Logger.Debugf("Dialing transport to %v via %v", mTp.Remote(), mTp.client.Type()) diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/network/addrresolver/client.go b/vendor/github.com/skycoin/skywire/pkg/transport/network/addrresolver/client.go index b59ed40e..9857c700 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/network/addrresolver/client.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/network/addrresolver/client.go @@ -24,6 +24,7 @@ import ( "github.com/skycoin/skywire/internal/httpauth" "github.com/skycoin/skywire/internal/netutil" "github.com/skycoin/skywire/internal/packetfilter" + pkgnetutil "github.com/skycoin/skywire/pkg/util/netutil" ) const ( @@ -43,6 +44,8 @@ var ( ErrNoEntry = errors.New("no entry for this PK") // ErrNotReady is returned when address resolver is not ready. ErrNotReady = errors.New("address resolver is not ready") + // ErrNoTransportsFound returned when no transports are found. + ErrNoTransportsFound = errors.New("failed to get response data from AR transports endpoint") ) // Error is the object returned to the client when there's an error. @@ -57,6 +60,7 @@ type APIClient interface { BindSTCPR(ctx context.Context, port string) error BindSUDPH(filter *pfilter.PacketFilter, handshake Handshake) (<-chan RemoteVisor, error) Resolve(ctx context.Context, netType string, pk cipher.PubKey) (VisorData, error) + Transports(ctx context.Context) (map[cipher.PubKey][]string, error) Close() error } @@ -70,12 +74,14 @@ type VisorData struct { // httpClient implements APIClient for address resolver API. type httpClient struct { log *logging.Logger + mLog *logging.MasterLogger httpClient *httpauth.Client pk cipher.PubKey sk cipher.SecKey remoteHTTPAddr string remoteUDPAddr string sudphConn net.PacketConn + clientPublicIP string ready chan struct{} closed chan struct{} delBindSudphWg sync.WaitGroup @@ -87,7 +93,8 @@ type httpClient struct { // * SW-Public: The specified public key. // * SW-Nonce: The nonce for that public key. // * SW-Sig: The signature of the payload + the nonce. -func NewHTTP(remoteAddr string, pk cipher.PubKey, sk cipher.SecKey, httpC http.Client, log *logging.Logger) (APIClient, error) { +func NewHTTP(remoteAddr string, pk cipher.PubKey, sk cipher.SecKey, httpC *http.Client, clientPublicIP string, log *logging.Logger, + mLog *logging.MasterLogger) (APIClient, error) { remoteURL, err := url.Parse(remoteAddr) if err != nil { return nil, fmt.Errorf("parse URL: %w", err) @@ -100,10 +107,12 @@ func NewHTTP(remoteAddr string, pk cipher.PubKey, sk cipher.SecKey, httpC http.C client := &httpClient{ log: log, + mLog: mLog, pk: pk, sk: sk, remoteHTTPAddr: remoteAddr, remoteUDPAddr: remoteUDP, + clientPublicIP: clientPublicIP, ready: make(chan struct{}), closed: make(chan struct{}), } @@ -115,17 +124,17 @@ func NewHTTP(remoteAddr string, pk cipher.PubKey, sk cipher.SecKey, httpC http.C return client, nil } -func (c *httpClient) initHTTPClient(httpC http.Client) { - httpAuthClient, err := httpauth.NewClient(context.Background(), c.remoteHTTPAddr, c.pk, c.sk, &httpC) +func (c *httpClient) initHTTPClient(httpC *http.Client) { + httpAuthClient, err := httpauth.NewClient(context.Background(), c.remoteHTTPAddr, c.pk, c.sk, httpC, c.clientPublicIP, c.mLog) if err != nil { c.log.WithError(err). Warnf("Failed to connect to address resolver. STCPR/SUDPH services are temporarily unavailable. Retrying...") - retryLog := logging.MustGetLogger("snet.arclient.retrier") + retryLog := c.mLog.PackageLogger("network.arclient.retrier") retry := dmsgnetutil.NewRetrier(retryLog, 1*time.Second, 10*time.Second, 0, 1) err := retry.Do(context.Background(), func() error { - httpAuthClient, err = httpauth.NewClient(context.Background(), c.remoteHTTPAddr, c.pk, c.sk, &httpC) + httpAuthClient, err = httpauth.NewClient(context.Background(), c.remoteHTTPAddr, c.pk, c.sk, httpC, c.clientPublicIP, c.mLog) return err }) @@ -190,7 +199,6 @@ func (c *httpClient) Delete(ctx context.Context, path string) (*http.Response, e if err != nil { return nil, err } - return c.httpClient.Do(req.WithContext(ctx)) } @@ -284,7 +292,7 @@ func (c *httpClient) BindSUDPH(filter *pfilter.PacketFilter, hs Handshake) (<-ch return nil, err } - c.sudphConn = filter.NewConn(sudphPriority, packetfilter.NewAddressFilter(rAddr)) + c.sudphConn = filter.NewConn(sudphPriority, packetfilter.NewAddressFilter(rAddr, c.mLog)) _, localPort, err := net.SplitHostPort(c.sudphConn.LocalAddr().String()) if err != nil { @@ -377,6 +385,58 @@ func (c *httpClient) Resolve(ctx context.Context, tType string, pk cipher.PubKey return resolveResp, nil } +// Transports query available transports. +func (c *httpClient) Transports(ctx context.Context) (map[cipher.PubKey][]string, error) { + resp, err := c.Get(ctx, "/transports") + if err != nil { + return nil, err + } + defer func() { + if err = resp.Body.Close(); err != nil { + c.log.WithError(err).Warn("Failed to close response body") + } + }() + + if resp.StatusCode != http.StatusOK { + c.log.Warn(ErrNoTransportsFound.Error()) + return nil, ErrNoTransportsFound + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + transportsMap := map[string][]string{} + if err = json.Unmarshal(body, &transportsMap); err != nil { + return nil, err + } + + results := map[cipher.PubKey][]string{} + + for k, pks := range transportsMap { + for _, pk := range pks { + rPK := cipher.PubKey{} + if err := rPK.Set(pk); err != nil { + c.log.WithError(err).Warn("unable to transform PK") + continue + } + + // Two kinds of network, SUDPH and STCPR + if _, ok := results[rPK]; ok { + if len(results[rPK]) == 1 && k != results[rPK][0] { + results[rPK] = append(results[rPK], k) + } + } else { + nTypeSlice := make([]string, 0, 2) + nTypeSlice = append(nTypeSlice, k) + results[rPK] = nTypeSlice + } + } + } + return results, nil +} + func (c *httpClient) isReady() bool { select { case <-c.ready: @@ -453,8 +513,14 @@ func (c *httpClient) Close() error { } } - if err := c.delBindSTCPR(context.Background()); err != nil { - c.log.WithError(err).Errorf("Failed to delete STCPR binding") + hasPublic, err := pkgnetutil.HasPublicIP() + if err != nil { + c.log.Errorf("Failed to check for public IP: %v", err) + } + if hasPublic { + if err := c.delBindSTCPR(context.Background()); err != nil { + c.log.WithError(err).Errorf("Failed to delete STCPR binding") + } } return nil diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/network/client.go b/vendor/github.com/skycoin/skywire/pkg/transport/network/client.go index 7c5fb47c..ba6bbf9c 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/network/client.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/network/client.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net" + "strings" "sync" "github.com/skycoin/dmsg" @@ -56,11 +57,16 @@ type ClientFactory struct { ARClient addrresolver.APIClient EB *appevent.Broadcaster DmsgC *dmsg.Client + MLogger *logging.MasterLogger } // MakeClient creates a new client of specified type func (f *ClientFactory) MakeClient(netType Type) (Client, error) { log := logging.MustGetLogger(string(netType)) + if f.MLogger != nil { + log = f.MLogger.PackageLogger(string(netType)) + } + p := porter.New(porter.MinEphemeral) generic := &genericClient{} @@ -68,6 +74,7 @@ func (f *ClientFactory) MakeClient(netType Type) (Client, error) { generic.done = make(chan struct{}) generic.listeners = make(map[uint16]*listener) generic.log = log + generic.mLog = f.MLogger generic.porter = p generic.eb = f.EB generic.lPK = f.PK @@ -103,6 +110,7 @@ type genericClient struct { netType Type log *logging.Logger + mLog *logging.MasterLogger porter *porter.Porter eb *appevent.Broadcaster @@ -143,6 +151,12 @@ func (c *genericClient) acceptTransports(lis net.Listener) { if errors.Is(err, io.EOF) { continue // likely it's a dummy connection from service discovery } + + if c.isClosed() && (errors.Is(err, io.ErrClosedPipe) || strings.Contains(err.Error(), "use of closed network connection")) { + c.log.Info("Cleanly stopped serving.") + return + } + c.log.Warnf("failed to accept incoming connection: %v", err) if !handshake.IsHandshakeError(err) { c.log.Warnf("stopped serving") @@ -312,6 +326,7 @@ func (c *resolvedClient) dialVisor(ctx context.Context, rPK cipher.PubKey, dial if err != nil { return nil, fmt.Errorf("resolve PK: %w", err) } + c.log.Infof("Resolved PK %v to visor data %v", rPK, visorData) if visorData.IsLocal { for _, host := range visorData.Addresses { diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/network/stcpr.go b/vendor/github.com/skycoin/skywire/pkg/transport/network/stcpr.go index 8313c31b..db1a47b6 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/network/stcpr.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/network/stcpr.go @@ -2,7 +2,6 @@ package network import ( "context" - "fmt" "io" "net" @@ -27,11 +26,6 @@ func (c *stcprClient) Dial(ctx context.Context, rPK cipher.PubKey, rPort uint16) return nil, io.ErrClosedPipe } c.log.Infof("Dialing PK %v", rPK) - visorData, err := c.ar.Resolve(ctx, string(STCPR), rPK) - if err != nil { - return nil, fmt.Errorf("resolve PK: %w", err) - } - c.log.Infof("Resolved PK %v to visor data %v", rPK, visorData) conn, err := c.dialVisor(ctx, rPK, c.dial) if err != nil { return nil, err diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/network/sudph.go b/vendor/github.com/skycoin/skywire/pkg/transport/network/sudph.go index 83cd4f0f..8e73a2e4 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/network/sudph.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/network/sudph.go @@ -156,7 +156,7 @@ func (c *sudphClient) dial(remoteAddr string) (net.Conn, error) { return nil, fmt.Errorf("net.ResolveUDPAddr (remote): %w", err) } - dialConn := c.filter.NewConn(dialConnPriority, packetfilter.NewKCPConversationFilter()) + dialConn := c.filter.NewConn(dialConnPriority, packetfilter.NewKCPConversationFilter(c.mLog)) if _, err := dialConn.WriteTo([]byte(holePunchMessage), rAddr); err != nil { return nil, fmt.Errorf("dialConn.WriteTo: %w", err) diff --git a/vendor/github.com/skycoin/skywire/pkg/transport/transport.go b/vendor/github.com/skycoin/skywire/pkg/transport/transport.go index 679d017f..3aa1c50e 100644 --- a/vendor/github.com/skycoin/skywire/pkg/transport/transport.go +++ b/vendor/github.com/skycoin/skywire/pkg/transport/transport.go @@ -8,13 +8,10 @@ import ( "github.com/google/uuid" "github.com/skycoin/dmsg/cipher" - "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/skywire/pkg/transport/network" ) -var log = logging.MustGetLogger("transport") - // MakeTransportID generates uuid.UUID from pair of keys + type + public // Generated uuid is: // - always the same for a given pair diff --git a/vendor/github.com/skycoin/skywire/pkg/util/netutil/net_windows.go b/vendor/github.com/skycoin/skywire/pkg/util/netutil/net_windows.go index cb81b16a..bf617924 100644 --- a/vendor/github.com/skycoin/skywire/pkg/util/netutil/net_windows.go +++ b/vendor/github.com/skycoin/skywire/pkg/util/netutil/net_windows.go @@ -28,8 +28,8 @@ func DefaultNetworkInterface() (string, error) { var ips []string if len(splitLines) > 0 { - re := regexp.MustCompile("\\s+") - for i, line := range splitLines { + re := regexp.MustCompile(`\s+`) + for _, line := range splitLines { ipAddr := re.Split(strings.TrimSpace(line), -1) if len(ipAddr) > 2 { @@ -47,7 +47,7 @@ func DefaultNetworkInterface() (string, error) { // get default network interface based on its ip findInterfaceCmd := fmt.Sprintf("Get-NetIpAddress -IPAddress '%s' | %%{$_.InterfaceAlias}", ips[0]) - cmd = exec.Command("powershell", findInterfaceCmd) + cmd = exec.Command("powershell", findInterfaceCmd) // nolint:gosec output, err = cmd.Output() if err != nil { return "", fmt.Errorf("unable to get default interface: %v", err) diff --git a/vendor/github.com/skycoin/skywire/pkg/visor/visorconfig/config.go b/vendor/github.com/skycoin/skywire/pkg/visor/visorconfig/config.go index 0d4755f1..5fd4b9f8 100644 --- a/vendor/github.com/skycoin/skywire/pkg/visor/visorconfig/config.go +++ b/vendor/github.com/skycoin/skywire/pkg/visor/visorconfig/config.go @@ -1,8 +1,6 @@ package visorconfig import ( - "runtime" - "github.com/skycoin/dmsg/cipher" "github.com/skycoin/dmsg/disc" "github.com/skycoin/skycoin/src/util/logging" @@ -80,7 +78,7 @@ func defaultConfigFromCommon(cc *Common, hypervisor bool) (*V1, error) { conf.Dmsgpty = &V1Dmsgpty{ DmsgPort: skyenv.DmsgPtyPort, CLINet: skyenv.DefaultDmsgPtyCLINet, - CLIAddr: skyenv.DefaultDmsgPtyCLIAddr, + CLIAddr: skyenv.DefaultDmsgPtyCLIAddr(), } conf.STCP = &network.STCPConfig{ @@ -130,7 +128,7 @@ func MakePackageConfig(log *logging.MasterLogger, confPath string, sk *cipher.Se conf.Dmsgpty = &V1Dmsgpty{ DmsgPort: skyenv.DmsgPtyPort, CLINet: skyenv.DefaultDmsgPtyCLINet, - CLIAddr: skyenv.DefaultDmsgPtyCLIAddr, + CLIAddr: skyenv.DefaultDmsgPtyCLIAddr(), } conf.LocalPath = skyenv.PackageAppLocalPath() conf.Launcher.BinPath = skyenv.PackageAppBinPath() @@ -146,31 +144,6 @@ func MakePackageConfig(log *logging.MasterLogger, confPath string, sk *cipher.Se return conf, nil } -// MakeSkybianConfig acts like MakeDefaultConfig but uses default paths, etc. as found in skybian / produced by skyimager -func MakeSkybianConfig(log *logging.MasterLogger, confPath string, sk *cipher.SecKey, hypervisor bool) (*V1, error) { - conf, err := MakeDefaultConfig(log, confPath, sk, hypervisor) - if err != nil { - return nil, err - } - - conf.Dmsgpty = &V1Dmsgpty{ - DmsgPort: skyenv.DmsgPtyPort, - CLINet: skyenv.DefaultDmsgPtyCLINet, - CLIAddr: skyenv.SkybianDmsgPtyCLIAddr, - } - conf.LocalPath = skyenv.SkybianLocalPath - conf.Launcher.BinPath = skyenv.SkybianAppBinPath - - if conf.Hypervisor != nil { - conf.Hypervisor.EnableAuth = skyenv.DefaultEnableAuth - conf.Hypervisor.EnableTLS = skyenv.SkybianEnableTLS - conf.Hypervisor.TLSKeyFile = skyenv.SkybianTLSKey - conf.Hypervisor.TLSCertFile = skyenv.SkybianTLSCert - conf.Hypervisor.DBPath = skyenv.SkybianDBPath - } - return conf, nil -} - // SetDefaultTestingValues mutates configuration to use testing values func SetDefaultTestingValues(conf *V1) { conf.Dmsg.Discovery = skyenv.TestDmsgDiscAddr @@ -205,22 +178,6 @@ func makeDefaultLauncherAppsConfig() []launcher.AppConfig { AutoStart: false, Port: routing.Port(skyenv.VPNClientPort), }, - } - - switch runtime.GOOS { - case "linux": - return launcherAddAllApps(defaultConfig) - case "darwin": - return defaultConfig - case "windows": - return defaultConfig - default: - return defaultConfig - } -} - -func launcherAddAllApps(launcherCfg []launcher.AppConfig) []launcher.AppConfig { - launcherCfg = append(launcherCfg, []launcher.AppConfig{ { Name: skyenv.SkychatName, AutoStart: true, @@ -242,8 +199,8 @@ func launcherAddAllApps(launcherCfg []launcher.AppConfig) []launcher.AppConfig { AutoStart: false, Port: routing.Port(skyenv.VPNServerPort), }, - }...) - return launcherCfg + } + return defaultConfig } // DmsgHTTPServers struct use to unmarshal dmsghttp file diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index dc200395..41649d26 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -13,12 +13,42 @@ const ( compareGreater ) +var ( + intType = reflect.TypeOf(int(1)) + int8Type = reflect.TypeOf(int8(1)) + int16Type = reflect.TypeOf(int16(1)) + int32Type = reflect.TypeOf(int32(1)) + int64Type = reflect.TypeOf(int64(1)) + + uintType = reflect.TypeOf(uint(1)) + uint8Type = reflect.TypeOf(uint8(1)) + uint16Type = reflect.TypeOf(uint16(1)) + uint32Type = reflect.TypeOf(uint32(1)) + uint64Type = reflect.TypeOf(uint64(1)) + + float32Type = reflect.TypeOf(float32(1)) + float64Type = reflect.TypeOf(float64(1)) + + stringType = reflect.TypeOf("") +) + func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { + obj1Value := reflect.ValueOf(obj1) + obj2Value := reflect.ValueOf(obj2) + + // throughout this switch we try and avoid calling .Convert() if possible, + // as this has a pretty big performance impact switch kind { case reflect.Int: { - intobj1 := obj1.(int) - intobj2 := obj2.(int) + intobj1, ok := obj1.(int) + if !ok { + intobj1 = obj1Value.Convert(intType).Interface().(int) + } + intobj2, ok := obj2.(int) + if !ok { + intobj2 = obj2Value.Convert(intType).Interface().(int) + } if intobj1 > intobj2 { return compareGreater, true } @@ -31,8 +61,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int8: { - int8obj1 := obj1.(int8) - int8obj2 := obj2.(int8) + int8obj1, ok := obj1.(int8) + if !ok { + int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) + } + int8obj2, ok := obj2.(int8) + if !ok { + int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) + } if int8obj1 > int8obj2 { return compareGreater, true } @@ -45,8 +81,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int16: { - int16obj1 := obj1.(int16) - int16obj2 := obj2.(int16) + int16obj1, ok := obj1.(int16) + if !ok { + int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) + } + int16obj2, ok := obj2.(int16) + if !ok { + int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) + } if int16obj1 > int16obj2 { return compareGreater, true } @@ -59,8 +101,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int32: { - int32obj1 := obj1.(int32) - int32obj2 := obj2.(int32) + int32obj1, ok := obj1.(int32) + if !ok { + int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) + } + int32obj2, ok := obj2.(int32) + if !ok { + int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) + } if int32obj1 > int32obj2 { return compareGreater, true } @@ -73,8 +121,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Int64: { - int64obj1 := obj1.(int64) - int64obj2 := obj2.(int64) + int64obj1, ok := obj1.(int64) + if !ok { + int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) + } + int64obj2, ok := obj2.(int64) + if !ok { + int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) + } if int64obj1 > int64obj2 { return compareGreater, true } @@ -87,8 +141,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint: { - uintobj1 := obj1.(uint) - uintobj2 := obj2.(uint) + uintobj1, ok := obj1.(uint) + if !ok { + uintobj1 = obj1Value.Convert(uintType).Interface().(uint) + } + uintobj2, ok := obj2.(uint) + if !ok { + uintobj2 = obj2Value.Convert(uintType).Interface().(uint) + } if uintobj1 > uintobj2 { return compareGreater, true } @@ -101,8 +161,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint8: { - uint8obj1 := obj1.(uint8) - uint8obj2 := obj2.(uint8) + uint8obj1, ok := obj1.(uint8) + if !ok { + uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) + } + uint8obj2, ok := obj2.(uint8) + if !ok { + uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) + } if uint8obj1 > uint8obj2 { return compareGreater, true } @@ -115,8 +181,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint16: { - uint16obj1 := obj1.(uint16) - uint16obj2 := obj2.(uint16) + uint16obj1, ok := obj1.(uint16) + if !ok { + uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) + } + uint16obj2, ok := obj2.(uint16) + if !ok { + uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) + } if uint16obj1 > uint16obj2 { return compareGreater, true } @@ -129,8 +201,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint32: { - uint32obj1 := obj1.(uint32) - uint32obj2 := obj2.(uint32) + uint32obj1, ok := obj1.(uint32) + if !ok { + uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) + } + uint32obj2, ok := obj2.(uint32) + if !ok { + uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) + } if uint32obj1 > uint32obj2 { return compareGreater, true } @@ -143,8 +221,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Uint64: { - uint64obj1 := obj1.(uint64) - uint64obj2 := obj2.(uint64) + uint64obj1, ok := obj1.(uint64) + if !ok { + uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) + } + uint64obj2, ok := obj2.(uint64) + if !ok { + uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) + } if uint64obj1 > uint64obj2 { return compareGreater, true } @@ -157,8 +241,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Float32: { - float32obj1 := obj1.(float32) - float32obj2 := obj2.(float32) + float32obj1, ok := obj1.(float32) + if !ok { + float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) + } + float32obj2, ok := obj2.(float32) + if !ok { + float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) + } if float32obj1 > float32obj2 { return compareGreater, true } @@ -171,8 +261,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.Float64: { - float64obj1 := obj1.(float64) - float64obj2 := obj2.(float64) + float64obj1, ok := obj1.(float64) + if !ok { + float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) + } + float64obj2, ok := obj2.(float64) + if !ok { + float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) + } if float64obj1 > float64obj2 { return compareGreater, true } @@ -185,8 +281,14 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { } case reflect.String: { - stringobj1 := obj1.(string) - stringobj2 := obj2.(string) + stringobj1, ok := obj1.(string) + if !ok { + stringobj1 = obj1Value.Convert(stringType).Interface().(string) + } + stringobj2, ok := obj2.(string) + if !ok { + stringobj2 = obj2Value.Convert(stringType).Interface().(string) + } if stringobj1 > stringobj2 { return compareGreater, true } @@ -240,6 +342,24 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs) } +// Positive asserts that the specified element is positive +// +// assert.Positive(t, 1) +// assert.Positive(t, 1.23) +func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { + zero := reflect.Zero(reflect.TypeOf(e)) + return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs) +} + +// Negative asserts that the specified element is negative +// +// assert.Negative(t, -1) +// assert.Negative(t, -1.23) +func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { + zero := reflect.Zero(reflect.TypeOf(e)) + return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs) +} + func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 49370eb1..4dfd1229 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -114,6 +114,24 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { return Error(t, err, append([]interface{}{msg}, args...)...) } +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...) +} + // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // @@ -321,6 +339,54 @@ func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsil return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } +// IsDecreasingf asserts that the collection is decreasing +// +// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsDecreasing(t, object, append([]interface{}{msg}, args...)...) +} + +// IsIncreasingf asserts that the collection is increasing +// +// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsIncreasing(t, object, append([]interface{}{msg}, args...)...) +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...) +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) +} + // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -375,6 +441,17 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args . return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) } +// Negativef asserts that the specified element is negative +// +// assert.Negativef(t, -1, "error message %s", "formatted") +// assert.Negativef(t, -1.23, "error message %s", "formatted") +func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Negative(t, e, append([]interface{}{msg}, args...)...) +} + // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -476,6 +553,15 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") @@ -572,6 +658,17 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) } +// Positivef asserts that the specified element is positive +// +// assert.Positivef(t, 1, "error message %s", "formatted") +// assert.Positivef(t, 1.23, "error message %s", "formatted") +func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Positive(t, e, append([]interface{}{msg}, args...)...) +} + // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index 9db88942..25337a6f 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -204,6 +204,42 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { return Error(a.t, err, msgAndArgs...) } +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorAs(a.t, err, target, msgAndArgs...) +} + +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorAsf(a.t, err, target, msg, args...) +} + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorIs(a.t, err, target, msgAndArgs...) +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ErrorIsf(a.t, err, target, msg, args...) +} + // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() @@ -631,6 +667,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } +// IsDecreasing asserts that the collection is decreasing +// +// a.IsDecreasing([]int{2, 1, 0}) +// a.IsDecreasing([]float{2, 1}) +// a.IsDecreasing([]string{"b", "a"}) +func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsDecreasing(a.t, object, msgAndArgs...) +} + +// IsDecreasingf asserts that the collection is decreasing +// +// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") +// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsDecreasingf(a.t, object, msg, args...) +} + +// IsIncreasing asserts that the collection is increasing +// +// a.IsIncreasing([]int{1, 2, 3}) +// a.IsIncreasing([]float{1, 2}) +// a.IsIncreasing([]string{"a", "b"}) +func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsIncreasing(a.t, object, msgAndArgs...) +} + +// IsIncreasingf asserts that the collection is increasing +// +// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") +// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsIncreasingf(a.t, object, msg, args...) +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// a.IsNonDecreasing([]int{1, 1, 2}) +// a.IsNonDecreasing([]float{1, 2}) +// a.IsNonDecreasing([]string{"a", "b"}) +func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonDecreasing(a.t, object, msgAndArgs...) +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonDecreasingf(a.t, object, msg, args...) +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// a.IsNonIncreasing([]int{2, 1, 1}) +// a.IsNonIncreasing([]float{2, 1}) +// a.IsNonIncreasing([]string{"b", "a"}) +func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonIncreasing(a.t, object, msgAndArgs...) +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsNonIncreasingf(a.t, object, msg, args...) +} + // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { @@ -739,6 +871,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i return Lessf(a.t, e1, e2, msg, args...) } +// Negative asserts that the specified element is negative +// +// a.Negative(-1) +// a.Negative(-1.23) +func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Negative(a.t, e, msgAndArgs...) +} + +// Negativef asserts that the specified element is negative +// +// a.Negativef(-1, "error message %s", "formatted") +// a.Negativef(-1.23, "error message %s", "formatted") +func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Negativef(a.t, e, msg, args...) +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -941,6 +1095,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str return NotEqualf(a.t, expected, actual, msg, args...) } +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotErrorIs(a.t, err, target, msgAndArgs...) +} + +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotErrorIsf(a.t, err, target, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1133,6 +1305,28 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b return Panicsf(a.t, f, msg, args...) } +// Positive asserts that the specified element is positive +// +// a.Positive(1) +// a.Positive(1.23) +func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Positive(a.t, e, msgAndArgs...) +} + +// Positivef asserts that the specified element is positive +// +// a.Positivef(1, "error message %s", "formatted") +// a.Positivef(1.23, "error message %s", "formatted") +func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Positivef(a.t, e, msg, args...) +} + // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go new file mode 100644 index 00000000..1c3b4718 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -0,0 +1,81 @@ +package assert + +import ( + "fmt" + "reflect" +) + +// isOrdered checks that collection contains orderable elements. +func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { + objKind := reflect.TypeOf(object).Kind() + if objKind != reflect.Slice && objKind != reflect.Array { + return false + } + + objValue := reflect.ValueOf(object) + objLen := objValue.Len() + + if objLen <= 1 { + return true + } + + value := objValue.Index(0) + valueInterface := value.Interface() + firstValueKind := value.Kind() + + for i := 1; i < objLen; i++ { + prevValue := value + prevValueInterface := valueInterface + + value = objValue.Index(i) + valueInterface = value.Interface() + + compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) + + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) + } + + if !containsValue(allowedComparesResults, compareResult) { + return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) + } + } + + return true +} + +// IsIncreasing asserts that the collection is increasing +// +// assert.IsIncreasing(t, []int{1, 2, 3}) +// assert.IsIncreasing(t, []float{1, 2}) +// assert.IsIncreasing(t, []string{"a", "b"}) +func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs) +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// assert.IsNonIncreasing(t, []int{2, 1, 1}) +// assert.IsNonIncreasing(t, []float{2, 1}) +// assert.IsNonIncreasing(t, []string{"b", "a"}) +func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs) +} + +// IsDecreasing asserts that the collection is decreasing +// +// assert.IsDecreasing(t, []int{2, 1, 0}) +// assert.IsDecreasing(t, []float{2, 1}) +// assert.IsDecreasing(t, []string{"b", "a"}) +func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs) +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// assert.IsNonDecreasing(t, []int{1, 1, 2}) +// assert.IsNonDecreasing(t, []float{1, 2}) +// assert.IsNonDecreasing(t, []string{"a", "b"}) +func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 914a10d8..bcac4401 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -172,8 +172,8 @@ func isTest(name, prefix string) bool { if len(name) == len(prefix) { // "Test" is ok return true } - rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(rune) + r, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(r) } func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { @@ -1622,6 +1622,7 @@ var spewConfig = spew.ConfigState{ DisableCapacities: true, SortKeys: true, DisableMethods: true, + MaxDepth: 10, } type tHelper interface { @@ -1693,3 +1694,81 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D } } } + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if errors.Is(err, target) { + return true + } + + var expectedText string + if target != nil { + expectedText = target.Error() + } + + chain := buildErrorChainString(err) + + return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ + "expected: %q\n"+ + "in chain: %s", expectedText, chain, + ), msgAndArgs...) +} + +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !errors.Is(err, target) { + return true + } + + var expectedText string + if target != nil { + expectedText = target.Error() + } + + chain := buildErrorChainString(err) + + return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ + "found: %q\n"+ + "in chain: %s", expectedText, chain, + ), msgAndArgs...) +} + +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if errors.As(err, target) { + return true + } + + chain := buildErrorChainString(err) + + return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ + "expected: %q\n"+ + "in chain: %s", target, chain, + ), msgAndArgs...) +} + +func buildErrorChainString(err error) string { + if err == nil { + return "" + } + + e := errors.Unwrap(err) + chain := fmt.Sprintf("%q", err.Error()) + for e != nil { + chain += fmt.Sprintf("\n\t%q", e.Error()) + e = errors.Unwrap(e) + } + return chain +} diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go index c6df4485..e2e6a2d2 100644 --- a/vendor/github.com/stretchr/testify/mock/mock.go +++ b/vendor/github.com/stretchr/testify/mock/mock.go @@ -297,25 +297,52 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, * return -1, expectedCall } +type matchCandidate struct { + call *Call + mismatch string + diffCount int +} + +func (c matchCandidate) isBetterMatchThan(other matchCandidate) bool { + if c.call == nil { + return false + } + if other.call == nil { + return true + } + + if c.diffCount > other.diffCount { + return false + } + if c.diffCount < other.diffCount { + return true + } + + if c.call.Repeatability > 0 && other.call.Repeatability <= 0 { + return true + } + return false +} + func (m *Mock) findClosestCall(method string, arguments ...interface{}) (*Call, string) { - var diffCount int - var closestCall *Call - var err string + var bestMatch matchCandidate for _, call := range m.expectedCalls() { if call.Method == method { errInfo, tempDiffCount := call.Arguments.Diff(arguments) - if tempDiffCount < diffCount || diffCount == 0 { - diffCount = tempDiffCount - closestCall = call - err = errInfo + tempCandidate := matchCandidate{ + call: call, + mismatch: errInfo, + diffCount: tempDiffCount, + } + if tempCandidate.isBetterMatchThan(bestMatch) { + bestMatch = tempCandidate } - } } - return closestCall, err + return bestMatch.call, bestMatch.mismatch } func callString(method string, arguments Arguments, includeArgumentValues bool) string { diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index ec4624b2..51820df2 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -256,6 +256,54 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) { t.FailNow() } +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorAs(t, err, target, msgAndArgs...) { + return + } + t.FailNow() +} + +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorAsf(t, err, target, msg, args...) { + return + } + t.FailNow() +} + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorIs(t, err, target, msgAndArgs...) { + return + } + t.FailNow() +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.ErrorIsf(t, err, target, msg, args...) { + return + } + t.FailNow() +} + // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() @@ -806,6 +854,126 @@ func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon fl t.FailNow() } +// IsDecreasing asserts that the collection is decreasing +// +// assert.IsDecreasing(t, []int{2, 1, 0}) +// assert.IsDecreasing(t, []float{2, 1}) +// assert.IsDecreasing(t, []string{"b", "a"}) +func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsDecreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsDecreasingf asserts that the collection is decreasing +// +// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsDecreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// IsIncreasing asserts that the collection is increasing +// +// assert.IsIncreasing(t, []int{1, 2, 3}) +// assert.IsIncreasing(t, []float{1, 2}) +// assert.IsIncreasing(t, []string{"a", "b"}) +func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsIncreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsIncreasingf asserts that the collection is increasing +// +// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsIncreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// assert.IsNonDecreasing(t, []int{1, 1, 2}) +// assert.IsNonDecreasing(t, []float{1, 2}) +// assert.IsNonDecreasing(t, []string{"a", "b"}) +func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonDecreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonDecreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// assert.IsNonIncreasing(t, []int{2, 1, 1}) +// assert.IsNonIncreasing(t, []float{2, 1}) +// assert.IsNonIncreasing(t, []string{"b", "a"}) +func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonIncreasing(t, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.IsNonIncreasingf(t, object, msg, args...) { + return + } + t.FailNow() +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { @@ -944,6 +1112,34 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter t.FailNow() } +// Negative asserts that the specified element is negative +// +// assert.Negative(t, -1) +// assert.Negative(t, -1.23) +func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Negative(t, e, msgAndArgs...) { + return + } + t.FailNow() +} + +// Negativef asserts that the specified element is negative +// +// assert.Negativef(t, -1, "error message %s", "formatted") +// assert.Negativef(t, -1.23, "error message %s", "formatted") +func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Negativef(t, e, msg, args...) { + return + } + t.FailNow() +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -1200,6 +1396,30 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotErrorIs(t, err, target, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotErrorIsf(t, err, target, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) @@ -1446,6 +1666,34 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{} t.FailNow() } +// Positive asserts that the specified element is positive +// +// assert.Positive(t, 1) +// assert.Positive(t, 1.23) +func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Positive(t, e, msgAndArgs...) { + return + } + t.FailNow() +} + +// Positivef asserts that the specified element is positive +// +// assert.Positivef(t, 1, "error message %s", "formatted") +// assert.Positivef(t, 1.23, "error message %s", "formatted") +func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.Positivef(t, e, msg, args...) { + return + } + t.FailNow() +} + // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 103d7dcb..ed54a9d8 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -205,6 +205,42 @@ func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { Error(a.t, err, msgAndArgs...) } +// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorAs(a.t, err, target, msgAndArgs...) +} + +// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. +// This is a wrapper for errors.As. +func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorAsf(a.t, err, target, msg, args...) +} + +// ErrorIs asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorIs(a.t, err, target, msgAndArgs...) +} + +// ErrorIsf asserts that at least one of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + ErrorIsf(a.t, err, target, msg, args...) +} + // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() @@ -632,6 +668,102 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } +// IsDecreasing asserts that the collection is decreasing +// +// a.IsDecreasing([]int{2, 1, 0}) +// a.IsDecreasing([]float{2, 1}) +// a.IsDecreasing([]string{"b", "a"}) +func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsDecreasing(a.t, object, msgAndArgs...) +} + +// IsDecreasingf asserts that the collection is decreasing +// +// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") +// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsDecreasingf(a.t, object, msg, args...) +} + +// IsIncreasing asserts that the collection is increasing +// +// a.IsIncreasing([]int{1, 2, 3}) +// a.IsIncreasing([]float{1, 2}) +// a.IsIncreasing([]string{"a", "b"}) +func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsIncreasing(a.t, object, msgAndArgs...) +} + +// IsIncreasingf asserts that the collection is increasing +// +// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") +// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsIncreasingf(a.t, object, msg, args...) +} + +// IsNonDecreasing asserts that the collection is not decreasing +// +// a.IsNonDecreasing([]int{1, 1, 2}) +// a.IsNonDecreasing([]float{1, 2}) +// a.IsNonDecreasing([]string{"a", "b"}) +func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonDecreasing(a.t, object, msgAndArgs...) +} + +// IsNonDecreasingf asserts that the collection is not decreasing +// +// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") +func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonDecreasingf(a.t, object, msg, args...) +} + +// IsNonIncreasing asserts that the collection is not increasing +// +// a.IsNonIncreasing([]int{2, 1, 1}) +// a.IsNonIncreasing([]float{2, 1}) +// a.IsNonIncreasing([]string{"b", "a"}) +func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonIncreasing(a.t, object, msgAndArgs...) +} + +// IsNonIncreasingf asserts that the collection is not increasing +// +// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") +func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + IsNonIncreasingf(a.t, object, msg, args...) +} + // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { @@ -740,6 +872,28 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i Lessf(a.t, e1, e2, msg, args...) } +// Negative asserts that the specified element is negative +// +// a.Negative(-1) +// a.Negative(-1.23) +func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Negative(a.t, e, msgAndArgs...) +} + +// Negativef asserts that the specified element is negative +// +// a.Negativef(-1, "error message %s", "formatted") +// a.Negativef(-1.23, "error message %s", "formatted") +func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Negativef(a.t, e, msg, args...) +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // @@ -942,6 +1096,24 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str NotEqualf(a.t, expected, actual, msg, args...) } +// NotErrorIs asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotErrorIs(a.t, err, target, msgAndArgs...) +} + +// NotErrorIsf asserts that at none of the errors in err's chain matches target. +// This is a wrapper for errors.Is. +func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotErrorIsf(a.t, err, target, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1134,6 +1306,28 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa Panicsf(a.t, f, msg, args...) } +// Positive asserts that the specified element is positive +// +// a.Positive(1) +// a.Positive(1.23) +func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Positive(a.t, e, msgAndArgs...) +} + +// Positivef asserts that the specified element is positive +// +// a.Positivef(1, "error message %s", "formatted") +// a.Positivef(1.23, "error message %s", "formatted") +func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + Positivef(a.t, e, msg, args...) +} + // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") diff --git a/vendor/github.com/tjfoc/gmsm/sm4/sm4.go b/vendor/github.com/tjfoc/gmsm/sm4/sm4.go index d97f35c2..a8748408 100644 --- a/vendor/github.com/tjfoc/gmsm/sm4/sm4.go +++ b/vendor/github.com/tjfoc/gmsm/sm4/sm4.go @@ -12,20 +12,16 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -sm4 acceration +sm4 acceleration modified by Jack, 2017 Oct */ package sm4 import ( + "bytes" "crypto/cipher" - "crypto/rand" - "crypto/x509" - "encoding/pem" "errors" - "io/ioutil" - "os" "strconv" ) @@ -33,8 +29,6 @@ const BlockSize = 16 type SM4Key []byte -type KeySizeError int - // Cipher is an instance of SM4 encryption. type Sm4Cipher struct { subkeys []uint32 @@ -234,117 +228,260 @@ func generateSubKeys(key []byte) []uint32 { return subkeys } -func EncryptBlock(key SM4Key, dst, src []byte) { - subkeys := generateSubKeys(key) - cryptBlock(subkeys, make([]uint32, 4), make([]byte, 16), dst, src, false) +// NewCipher creates and returns a new cipher.Block. +func NewCipher(key []byte) (cipher.Block, error) { + if len(key) != BlockSize { + return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) + } + c := new(Sm4Cipher) + c.subkeys = generateSubKeys(key) + c.block1 = make([]uint32, 4) + c.block2 = make([]byte, 16) + return c, nil +} + +func (c *Sm4Cipher) BlockSize() int { + return BlockSize } -func DecryptBlock(key SM4Key, dst, src []byte) { - subkeys := generateSubKeys(key) - cryptBlock(subkeys, make([]uint32, 4), make([]byte, 16), dst, src, true) +func (c *Sm4Cipher) Encrypt(dst, src []byte) { + cryptBlock(c.subkeys, c.block1, c.block2, dst, src, false) } -func ReadKeyFromMem(data []byte, pwd []byte) (SM4Key, error) { - block, _ := pem.Decode(data) - if block == nil { - return nil, errors.New("SM4: pem decode failed") - } - if x509.IsEncryptedPEMBlock(block) { - if block.Type != "SM4 ENCRYPTED KEY" { - return nil, errors.New("SM4: unknown type") - } - if pwd == nil { - return nil, errors.New("SM4: need passwd") - } - data, err := x509.DecryptPEMBlock(block, pwd) - if err != nil { - return nil, err - } - return data, nil + + +func (c *Sm4Cipher) Decrypt(dst, src []byte) { + cryptBlock(c.subkeys, c.block1, c.block2, dst, src, true) +} + + + +func xor(in, iv []byte) (out []byte) { + if len(in) != len(iv) { + return nil } - if block.Type != "SM4 KEY" { - return nil, errors.New("SM4: unknown type") + + out = make([]byte, len(in)) + for i := 0; i < len(in); i++ { + out[i] = in[i] ^ iv[i] } - return block.Bytes, nil + return } -func ReadKeyFromPem(FileName string, pwd []byte) (SM4Key, error) { - data, err := ioutil.ReadFile(FileName) - if err != nil { - return nil, err - } - return ReadKeyFromMem(data, pwd) +func pkcs7Padding(src []byte) []byte { + padding := BlockSize - len(src)%BlockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(src, padtext...) } -func WriteKeytoMem(key SM4Key, pwd []byte) ([]byte, error) { - if pwd != nil { - block, err := x509.EncryptPEMBlock(rand.Reader, - "SM4 ENCRYPTED KEY", key, pwd, x509.PEMCipherAES256) - if err != nil { - return nil, err - } - return pem.EncodeToMemory(block), nil - } else { - block := &pem.Block{ - Type: "SM4 KEY", - Bytes: key, +func pkcs7UnPadding(src []byte) ([]byte, error) { + length := len(src) + unpadding := int(src[length-1]) + if unpadding > BlockSize || unpadding == 0 { + return nil, errors.New("Invalid pkcs7 padding (unpadding > BlockSize || unpadding == 0)") + } + + pad := src[len(src)-unpadding:] + for i := 0; i < unpadding; i++ { + if pad[i] != byte(unpadding) { + return nil, errors.New("Invalid pkcs7 padding (pad[i] != unpadding)") } - return pem.EncodeToMemory(block), nil } + + return src[:(length - unpadding)], nil } -func WriteKeyToPem(FileName string, key SM4Key, pwd []byte) (bool, error) { - var block *pem.Block +func Sm4Cbc(key []byte, in []byte, mode bool) (out []byte, err error) { + if len(key) != BlockSize { + return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) + } + var inData []byte + if mode { + inData = pkcs7Padding(in) + } else { + inData = in + } + + iv := make([]byte, BlockSize) - if pwd != nil { - var err error - block, err = x509.EncryptPEMBlock(rand.Reader, - "SM4 ENCRYPTED KEY", key, pwd, x509.PEMCipherAES256) - if err != nil { - return false, err + out = make([]byte, len(inData)) + c, err := NewCipher(key) + if err != nil { + panic(err) + } + if mode { + for i := 0; i < len(inData)/16; i++ { + in_tmp := xor(inData[i*16:i*16+16], iv) + out_tmp := make([]byte, 16) + c.Encrypt(out_tmp, in_tmp) + copy(out[i*16:i*16+16], out_tmp) + iv = out_tmp } } else { - block = &pem.Block{ - Type: "SM4 KEY", - Bytes: key, + for i := 0; i < len(inData)/16; i++ { + in_tmp := inData[i*16 : i*16+16] + out_tmp := make([]byte, 16) + c.Decrypt(out_tmp, in_tmp) + out_tmp = xor(out_tmp, iv) + copy(out[i*16:i*16+16], out_tmp) + iv = in_tmp } + out, _ = pkcs7UnPadding(out) } - file, err := os.Create(FileName) - if err != nil { - return false, err + + return out, nil +} +func Sm4Ecb(key []byte, in []byte, mode bool) (out []byte, err error) { + if len(key) != BlockSize { + return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) } - defer file.Close() - err = pem.Encode(file, block) + var inData []byte + if mode { + inData = pkcs7Padding(in) + } else { + inData = in + } + out = make([]byte, len(inData)) + c, err := NewCipher(key) if err != nil { - return false, nil + panic(err) + } + if mode { + for i := 0; i < len(inData)/16; i++ { + in_tmp := inData[i*16 : i*16+16] + out_tmp := make([]byte, 16) + c.Encrypt(out_tmp, in_tmp) + copy(out[i*16:i*16+16], out_tmp) + } + } else { + for i := 0; i < len(inData)/16; i++ { + in_tmp := inData[i*16 : i*16+16] + out_tmp := make([]byte, 16) + c.Decrypt(out_tmp, in_tmp) + copy(out[i*16:i*16+16], out_tmp) + } + out, _ = pkcs7UnPadding(out) } - return true, nil -} -func (k KeySizeError) Error() string { - return "SM4: invalid key size " + strconv.Itoa(int(k)) + return out, nil } -// NewCipher creates and returns a new cipher.Block. -func NewCipher(key []byte) (cipher.Block, error) { +//密码反馈模式(Cipher FeedBack (CFB)) +//https://blog.csdn.net/zy_strive_2012/article/details/102520356 +//https://blog.csdn.net/sinat_23338865/article/details/72869841 +func Sm4CFB(key []byte, in []byte, mode bool) (out []byte, err error) { if len(key) != BlockSize { - return nil, KeySizeError(len(key)) + return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) + } + var inData []byte + if mode { + inData = pkcs7Padding(in) + } else { + inData = in } - c := new(Sm4Cipher) - c.subkeys = generateSubKeys(key) - c.block1 = make([]uint32, 4) - c.block2 = make([]byte, 16) - return c, nil -} -func (c *Sm4Cipher) BlockSize() int { - return BlockSize -} + iv := make([]byte, BlockSize) + out = make([]byte, len(inData)) + c, err := NewCipher(key) + if err != nil { + panic(err) + } -func (c *Sm4Cipher) Encrypt(dst, src []byte) { - cryptBlock(c.subkeys, c.block1, c.block2, dst, src, false) + K := make([]byte, BlockSize) + cipherBlock := make([]byte, BlockSize) + plainBlock := make([]byte, BlockSize) + if mode { //加密 + for i := 0; i < len(inData)/16; i++ { + if i == 0 { + c.Encrypt(K, iv) + cipherBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) + copy(out[i*16:i*16+16], cipherBlock) + //copy(cipherBlock,out_tmp) + continue + } + c.Encrypt(K, cipherBlock) + cipherBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) + copy(out[i*16:i*16+16], cipherBlock) + //copy(cipherBlock,out_tmp) + } + + } else { //解密 + var i int = 0 + for ; i < len(inData)/16; i++ { + if i == 0 { + c.Encrypt(K, iv) //这里是加密,而不是调用解密方法Decrypt + plainBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) //获取明文分组 + copy(out[i*16:i*16+16], plainBlock) + continue + } + c.Encrypt(K, inData[(i-1)*16:(i-1)*16+16]) + plainBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) //获取明文分组 + copy(out[i*16:i*16+16], plainBlock) + + } + + out, _ = pkcs7UnPadding(out) + } + + return out, nil } -func (c *Sm4Cipher) Decrypt(dst, src []byte) { - cryptBlock(c.subkeys, c.block1, c.block2, dst, src, true) +//输出反馈模式(Output feedback, OFB) +//https://blog.csdn.net/chengqiuming/article/details/82390910 +//https://blog.csdn.net/sinat_23338865/article/details/72869841 +func Sm4OFB(key []byte, in []byte, mode bool) (out []byte, err error) { + if len(key) != BlockSize { + return nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) + } + var inData []byte + if mode { + inData = pkcs7Padding(in) + } else { + inData = in + } + + iv := make([]byte, BlockSize) + out = make([]byte, len(inData)) + c, err := NewCipher(key) + if err != nil { + panic(err) + } + + K := make([]byte, BlockSize) + cipherBlock := make([]byte, BlockSize) + plainBlock := make([]byte, BlockSize) + shiftIV := make([]byte, BlockSize) + if mode { //加密 + for i := 0; i < len(inData)/16; i++ { + if i == 0 { + c.Encrypt(K, iv) + cipherBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) + copy(out[i*16:i*16+16], cipherBlock) + copy(shiftIV, K[:BlockSize]) + continue + } + c.Encrypt(K, shiftIV) + cipherBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) + copy(out[i*16:i*16+16], cipherBlock) + copy(shiftIV, K[:BlockSize]) + } + + } else { //解密 + for i := 0; i < len(inData)/16; i++ { + if i == 0 { + c.Encrypt(K, iv) //这里是加密,而不是调用解密方法Decrypt + plainBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) //获取明文分组 + copy(out[i*16:i*16+16], plainBlock) + copy(shiftIV, K[:BlockSize]) + continue + } + c.Encrypt(K, shiftIV) + plainBlock = xor(K[:BlockSize], inData[i*16:i*16+16]) //获取明文分组 + copy(out[i*16:i*16+16], plainBlock) + copy(shiftIV, K[:BlockSize]) + } + out, _ = pkcs7UnPadding(out) + } + + return out, nil } diff --git a/vendor/github.com/tjfoc/gmsm/sm4/sm4_gcm.go b/vendor/github.com/tjfoc/gmsm/sm4/sm4_gcm.go new file mode 100644 index 00000000..40b73f8d --- /dev/null +++ b/vendor/github.com/tjfoc/gmsm/sm4/sm4_gcm.go @@ -0,0 +1,332 @@ +/* +Copyright Hyperledger-TWGC All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +writed by Zhiwei Yan, 2020 Oct +*/ +package sm4 + +import ( + "errors" + "strconv" +) + +//Paper: The Galois/Counter Mode of Operation (GCM) David A. Mcgrew,John Viega .2004. +func Sm4GCM(key []byte, IV ,in, A []byte, mode bool) ([]byte, []byte, error) { + if len(key) != BlockSize { + return nil,nil, errors.New("SM4: invalid key size " + strconv.Itoa(len(key))) + } + if mode { + C,T:=GCMEncrypt(key,IV,in,A) + return C,T,nil + }else{ + P,_T:=GCMDecrypt(key,IV,in,A) + return P,_T,nil + } +} + +func GetH(key []byte) (H []byte){ + c,err := NewCipher(key) + if err != nil { + panic(err) + } + + zores:=make([]byte, BlockSize) + H =make([]byte, BlockSize) + c.Encrypt(H,zores) + return H +} + +//ut = a + b +func addition(a ,b []byte) (out []byte){ + Len:=len(a) + if Len != len(b) { + return nil + } + out = make([]byte, Len) + for i := 0; i < Len; i++ { + out[i] = a[i] ^ b[i] + } + return out +} + +func Rightshift(V []byte){ + n:=len(V) + for i:=n-1;i>=0;i-- { + V[i]=V[i]>>1 + if i!=0{ + V[i]=((V[i-1]&0x01)<<7)|V[i] + } + } +} + +func findYi( Y []byte,index int) int{ + var temp byte + temp=Y[index/8] + temp=temp>>(7-index%8) + if temp & 0x01 == 1{ + return 1 + }else{ + return 0 + } +} + + +func multiplication(X,Y []byte) (Z []byte){ + + R:=make([]byte,BlockSize) + R[0]=0xe1 + Z=make([]byte,BlockSize) + V:=make([]byte,BlockSize) + copy(V,X) + for i:=0;i<=127;i++{ + if findYi(Y,i)==1{ + Z=addition(Z,V) + } + if V[BlockSize-1]&0x01==0{ + Rightshift(V) + }else{ + Rightshift(V) + V=addition(V,R) + } + } + return Z +} + +func GHASH(H []byte,A []byte,C []byte) (X[]byte){ + + calculm_v:=func(m ,v int) (int,int) { + if(m==0 && v!=0){ + m=1 + v=v*8 + }else if(m!=0 && v==0) { + v=BlockSize*8 + }else if(m!=0 && v!=0){ + m=m+1 + v=v*8 + }else { //m==0 && v==0 + m=1 + v=0 + } + return m,v + } + m:=len(A)/BlockSize + v:=len(A)%BlockSize + m,v=calculm_v(m,v) + + n:=len(C)/BlockSize + u:=(len(C)%BlockSize) + n,u=calculm_v(n,u) + + //i=0 + X=make([]byte,BlockSize*(m+n+2)) //X0 = 0 + for i:=0;im-1 对于数组来说是 0-->m-2 + } + + //i=m + zeros:=make([]byte,(128-v)/8) + Am:=make([]byte,v/8) + copy(Am[:],A[(m-1)*BlockSize:]) + Am=append(Am,zeros...) + copy(X[m*BlockSize:m*BlockSize+BlockSize],multiplication( addition(X[(m-1)*BlockSize:(m-1)*BlockSize+BlockSize],Am),H)) + + //i=m+1...m+n-1 + for i:=m+1;i<=(m+n-1);i++{ + copy(X[i*BlockSize:i*BlockSize+BlockSize],multiplication( addition(X[(i-1)*BlockSize:(i-1)*BlockSize+BlockSize],C[(i-m-1)*BlockSize:(i-m-1)*BlockSize+BlockSize]),H)) + } + + //i=m+n + zeros =make([]byte,(128-u)/8) + Cn:=make([]byte,u/8) + copy(Cn[:],C[(n-1)*BlockSize:]) + Cn=append(Cn,zeros...) + copy(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize],multiplication( addition(X[(m+n-1)*BlockSize:(m+n-1)*BlockSize+BlockSize],Cn),H)) + + //i=m+n+1 + var lenAB []byte + calculateLenToBytes :=func(len int) []byte{ + data:=make([]byte,8) + data[0]=byte((len>>56)&0xff) + data[1]=byte((len>>48)&0xff) + data[2]=byte((len>>40)&0xff) + data[3]=byte((len>>32)&0xff) + data[4]=byte((len>>24)&0xff) + data[5]=byte((len>>16)&0xff) + data[6]=byte((len>>8)&0xff) + data[7]=byte((len>>0)&0xff) + return data + } + lenAB=append(lenAB,calculateLenToBytes(len(A))...) + lenAB=append(lenAB,calculateLenToBytes(len(C))...) + copy(X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize],multiplication(addition(X[(m+n)*BlockSize:(m+n)*BlockSize+BlockSize],lenAB),H)) + return X[(m+n+1)*BlockSize:(m+n+1)*BlockSize+BlockSize] +} + + +func GetY0(H,IV []byte) []byte{ + if len(IV)*8 == 96 { + zero31one1:=[]byte{0x00,0x00,0x00,0x01} + IV=append(IV,zero31one1...) + return IV + }else{ + return GHASH(H,[]byte{},IV) + + } + +} + +func incr(n int ,Y_i []byte) (Y_ii []byte) { + + Y_ii=make([]byte,BlockSize*n) + copy(Y_ii,Y_i) + + addYone:=func(yi,yii []byte){ + copy(yii[:],yi[:]) + + Len:=len(yi) + var rc byte=0x00 + for i:=Len-1;i>=0;i--{ + if(i==Len-1){ + if(yii[i]<0xff){ + yii[i]=yii[i]+0x01 + rc=0x00 + }else{ + yii[i]=0x00 + rc=0x01 + } + }else{ + if yii[i]+rc<0xff { + yii[i]=yii[i]+rc + rc=0x00 + }else{ + yii[i]=0x00 + rc=0x01 + } + } + } + } + for i:=1;i> 32) } +// Seed sets the r state to n. +func (r *RNG) Seed(n uint32) { + r.x = n +} + func getRandomUint32() uint32 { x := time.Now().UnixNano() return uint32((x >> 32) ^ x) diff --git a/vendor/github.com/valyala/histogram/go.mod b/vendor/github.com/valyala/histogram/go.mod index 984efbe6..cc65b006 100644 --- a/vendor/github.com/valyala/histogram/go.mod +++ b/vendor/github.com/valyala/histogram/go.mod @@ -2,4 +2,4 @@ module github.com/valyala/histogram go 1.12 -require github.com/valyala/fastrand v1.0.0 +require github.com/valyala/fastrand v1.1.0 diff --git a/vendor/github.com/valyala/histogram/go.sum b/vendor/github.com/valyala/histogram/go.sum index 2b3e848a..c5ca5880 100644 --- a/vendor/github.com/valyala/histogram/go.sum +++ b/vendor/github.com/valyala/histogram/go.sum @@ -1,2 +1,2 @@ -github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI= -github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= +github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= +github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= diff --git a/vendor/github.com/valyala/histogram/histogram.go b/vendor/github.com/valyala/histogram/histogram.go index e90dd703..71be2afc 100644 --- a/vendor/github.com/valyala/histogram/histogram.go +++ b/vendor/github.com/valyala/histogram/histogram.go @@ -49,6 +49,10 @@ func (f *Fast) Reset() { f.a = nil f.tmp = nil } + // Reset rng state in order to get repeatable results + // for the same sequence of values passed to Fast.Update. + // See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1612 + f.rng.Seed(1) } // Update updates the f with v. diff --git a/vendor/go.etcd.io/bbolt/.gitignore b/vendor/go.etcd.io/bbolt/.gitignore index 3bcd8cba..18312f00 100644 --- a/vendor/go.etcd.io/bbolt/.gitignore +++ b/vendor/go.etcd.io/bbolt/.gitignore @@ -3,3 +3,5 @@ *.swp /bin/ cover.out +/.idea +*.iml diff --git a/vendor/go.etcd.io/bbolt/.travis.yml b/vendor/go.etcd.io/bbolt/.travis.yml index 257dfdfe..452601e4 100644 --- a/vendor/go.etcd.io/bbolt/.travis.yml +++ b/vendor/go.etcd.io/bbolt/.travis.yml @@ -4,9 +4,10 @@ go_import_path: go.etcd.io/bbolt sudo: false go: -- 1.12 +- 1.15 before_install: +- go get -v golang.org/x/sys/unix - go get -v honnef.co/go/tools/... - go get -v github.com/kisielk/errcheck diff --git a/vendor/go.etcd.io/bbolt/Makefile b/vendor/go.etcd.io/bbolt/Makefile index 2968aaa6..21ecf48f 100644 --- a/vendor/go.etcd.io/bbolt/Makefile +++ b/vendor/go.etcd.io/bbolt/Makefile @@ -2,8 +2,6 @@ BRANCH=`git rev-parse --abbrev-ref HEAD` COMMIT=`git rev-parse --short HEAD` GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" -default: build - race: @TEST_FREELIST_TYPE=hashmap go test -v -race -test.run="TestSimulate_(100op|1000op)" @echo "array freelist test" diff --git a/vendor/go.etcd.io/bbolt/README.md b/vendor/go.etcd.io/bbolt/README.md index c9e64b1a..f1b4a7b2 100644 --- a/vendor/go.etcd.io/bbolt/README.md +++ b/vendor/go.etcd.io/bbolt/README.md @@ -908,12 +908,14 @@ Below is a list of public, open source projects that use Bolt: * [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt. * [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. * [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. +* [BoltDB Viewer](https://github.com/zc310/rich_boltdb) - A BoltDB Viewer Can run on Windows、Linux、Android system. * [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. * [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. * [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining simple tx and key scans. * [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. * [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations. +* [🌰 Chestnut](https://github.com/jrapoport/chestnut) - Chestnut is encrypted storage for Go. * [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. * [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. * [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. @@ -938,9 +940,8 @@ Below is a list of public, open source projects that use Bolt: * [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite. * [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. * [NATS](https://github.com/nats-io/nats-streaming-server) - NATS Streaming uses bbolt for message and metadata storage. -* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. -* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site. * [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system. +* [Rain](https://github.com/cenkalti/rain) - BitTorrent client and library. * [reef-pi](https://github.com/reef-pi/reef-pi) - reef-pi is an award winning, modular, DIY reef tank controller using easy to learn electronics based on a Raspberry Pi. * [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service * [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. diff --git a/vendor/go.etcd.io/bbolt/bolt_unix.go b/vendor/go.etcd.io/bbolt/bolt_unix.go index 2938fed5..4e5f65cc 100644 --- a/vendor/go.etcd.io/bbolt/bolt_unix.go +++ b/vendor/go.etcd.io/bbolt/bolt_unix.go @@ -7,6 +7,8 @@ import ( "syscall" "time" "unsafe" + + "golang.org/x/sys/unix" ) // flock acquires an advisory lock on a file descriptor. @@ -49,13 +51,13 @@ func funlock(db *DB) error { // mmap memory maps a DB's data file. func mmap(db *DB, sz int) error { // Map the data file to memory. - b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) + b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) if err != nil { return err } // Advise the kernel that the mmap is accessed randomly. - err = madvise(b, syscall.MADV_RANDOM) + err = unix.Madvise(b, syscall.MADV_RANDOM) if err != nil && err != syscall.ENOSYS { // Ignore not implemented error in kernel because it still works. return fmt.Errorf("madvise: %s", err) @@ -76,18 +78,9 @@ func munmap(db *DB) error { } // Unmap using the original byte slice. - err := syscall.Munmap(db.dataref) + err := unix.Munmap(db.dataref) db.dataref = nil db.data = nil db.datasz = 0 return err } - -// NOTE: This function is copied from stdlib because it is not available on darwin. -func madvise(b []byte, advice int) (err error) { - _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) - if e1 != 0 { - err = e1 - } - return -} diff --git a/vendor/go.etcd.io/bbolt/compact.go b/vendor/go.etcd.io/bbolt/compact.go new file mode 100644 index 00000000..e4fe91b0 --- /dev/null +++ b/vendor/go.etcd.io/bbolt/compact.go @@ -0,0 +1,114 @@ +package bbolt + +// Compact will create a copy of the source DB and in the destination DB. This may +// reclaim space that the source database no longer has use for. txMaxSize can be +// used to limit the transactions size of this process and may trigger intermittent +// commits. A value of zero will ignore transaction sizes. +// TODO: merge with: https://github.com/etcd-io/etcd/blob/b7f0f52a16dbf83f18ca1d803f7892d750366a94/mvcc/backend/backend.go#L349 +func Compact(dst, src *DB, txMaxSize int64) error { + // commit regularly, or we'll run out of memory for large datasets if using one transaction. + var size int64 + tx, err := dst.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + if err := walk(src, func(keys [][]byte, k, v []byte, seq uint64) error { + // On each key/value, check if we have exceeded tx size. + sz := int64(len(k) + len(v)) + if size+sz > txMaxSize && txMaxSize != 0 { + // Commit previous transaction. + if err := tx.Commit(); err != nil { + return err + } + + // Start new transaction. + tx, err = dst.Begin(true) + if err != nil { + return err + } + size = 0 + } + size += sz + + // Create bucket on the root transaction if this is the first level. + nk := len(keys) + if nk == 0 { + bkt, err := tx.CreateBucket(k) + if err != nil { + return err + } + if err := bkt.SetSequence(seq); err != nil { + return err + } + return nil + } + + // Create buckets on subsequent levels, if necessary. + b := tx.Bucket(keys[0]) + if nk > 1 { + for _, k := range keys[1:] { + b = b.Bucket(k) + } + } + + // Fill the entire page for best compaction. + b.FillPercent = 1.0 + + // If there is no value then this is a bucket call. + if v == nil { + bkt, err := b.CreateBucket(k) + if err != nil { + return err + } + if err := bkt.SetSequence(seq); err != nil { + return err + } + return nil + } + + // Otherwise treat it as a key/value pair. + return b.Put(k, v) + }); err != nil { + return err + } + + return tx.Commit() +} + +// walkFunc is the type of the function called for keys (buckets and "normal" +// values) discovered by Walk. keys is the list of keys to descend to the bucket +// owning the discovered key/value pair k/v. +type walkFunc func(keys [][]byte, k, v []byte, seq uint64) error + +// walk walks recursively the bolt database db, calling walkFn for each key it finds. +func walk(db *DB, walkFn walkFunc) error { + return db.View(func(tx *Tx) error { + return tx.ForEach(func(name []byte, b *Bucket) error { + return walkBucket(b, nil, name, nil, b.Sequence(), walkFn) + }) + }) +} + +func walkBucket(b *Bucket, keypath [][]byte, k, v []byte, seq uint64, fn walkFunc) error { + // Execute callback. + if err := fn(keypath, k, v, seq); err != nil { + return err + } + + // If this is not a bucket then stop. + if v != nil { + return nil + } + + // Iterate over each child key/value. + keypath = append(keypath, k) + return b.ForEach(func(k, v []byte) error { + if v == nil { + bkt := b.Bucket(k) + return walkBucket(bkt, keypath, k, nil, bkt.Sequence(), fn) + } + return walkBucket(b, keypath, k, v, b.Sequence(), fn) + }) +} diff --git a/vendor/go.etcd.io/bbolt/db.go b/vendor/go.etcd.io/bbolt/db.go index 80b0095c..a798c390 100644 --- a/vendor/go.etcd.io/bbolt/db.go +++ b/vendor/go.etcd.io/bbolt/db.go @@ -120,6 +120,12 @@ type DB struct { // of truncate() and fsync() when growing the data file. AllocSize int + // Mlock locks database file in memory when set to true. + // It prevents major page faults, however used memory can't be reclaimed. + // + // Supported only on Unix via mlock/munlock syscalls. + Mlock bool + path string openFile func(string, int, os.FileMode) (*os.File, error) file *os.File @@ -188,6 +194,7 @@ func Open(path string, mode os.FileMode, options *Options) (*DB, error) { db.MmapFlags = options.MmapFlags db.NoFreelistSync = options.NoFreelistSync db.FreelistType = options.FreelistType + db.Mlock = options.Mlock // Set default values for later DB operations. db.MaxBatchSize = DefaultMaxBatchSize @@ -337,7 +344,8 @@ func (db *DB) mmap(minsz int) error { } // Ensure the size is at least the minimum size. - var size = int(info.Size()) + fileSize := int(info.Size()) + var size = fileSize if size < minsz { size = minsz } @@ -346,6 +354,13 @@ func (db *DB) mmap(minsz int) error { return err } + if db.Mlock { + // Unlock db memory + if err := db.munlock(fileSize); err != nil { + return err + } + } + // Dereference all mmap references before unmapping. if db.rwtx != nil { db.rwtx.root.dereference() @@ -361,6 +376,13 @@ func (db *DB) mmap(minsz int) error { return err } + if db.Mlock { + // Don't allow swapping of data file + if err := db.mlock(fileSize); err != nil { + return err + } + } + // Save references to the meta pages. db.meta0 = db.page(0).meta() db.meta1 = db.page(1).meta() @@ -422,12 +444,36 @@ func (db *DB) mmapSize(size int) (int, error) { return int(sz), nil } +func (db *DB) munlock(fileSize int) error { + if err := munlock(db, fileSize); err != nil { + return fmt.Errorf("munlock error: " + err.Error()) + } + return nil +} + +func (db *DB) mlock(fileSize int) error { + if err := mlock(db, fileSize); err != nil { + return fmt.Errorf("mlock error: " + err.Error()) + } + return nil +} + +func (db *DB) mrelock(fileSizeFrom, fileSizeTo int) error { + if err := db.munlock(fileSizeFrom); err != nil { + return err + } + if err := db.mlock(fileSizeTo); err != nil { + return err + } + return nil +} + // init creates a new database file and initializes its meta pages. func (db *DB) init() error { // Create two meta pages on a buffer. buf := make([]byte, db.pageSize*4) for i := 0; i < 2; i++ { - p := db.pageInBuffer(buf[:], pgid(i)) + p := db.pageInBuffer(buf, pgid(i)) p.id = pgid(i) p.flags = metaPageFlag @@ -444,13 +490,13 @@ func (db *DB) init() error { } // Write an empty freelist at page 3. - p := db.pageInBuffer(buf[:], pgid(2)) + p := db.pageInBuffer(buf, pgid(2)) p.id = pgid(2) p.flags = freelistPageFlag p.count = 0 // Write an empty leaf page at page 4. - p = db.pageInBuffer(buf[:], pgid(3)) + p = db.pageInBuffer(buf, pgid(3)) p.id = pgid(3) p.flags = leafPageFlag p.count = 0 @@ -462,6 +508,7 @@ func (db *DB) init() error { if err := fdatasync(db); err != nil { return err } + db.filesz = len(buf) return nil } @@ -973,6 +1020,12 @@ func (db *DB) grow(sz int) error { if err := db.file.Sync(); err != nil { return fmt.Errorf("file sync error: %s", err) } + if db.Mlock { + // unlock old file and lock new one + if err := db.mrelock(db.filesz, sz); err != nil { + return fmt.Errorf("mlock/munlock error: %s", err) + } + } } db.filesz = sz @@ -1064,6 +1117,11 @@ type Options struct { // OpenFile is used to open files. It defaults to os.OpenFile. This option // is useful for writing hermetic tests. OpenFile func(string, int, os.FileMode) (*os.File, error) + + // Mlock locks database file in memory when set to true. + // It prevents potential page faults, however + // used memory can't be reclaimed. (UNIX only) + Mlock bool } // DefaultOptions represent the options used if nil options are passed into Open(). diff --git a/vendor/go.etcd.io/bbolt/freelist_hmap.go b/vendor/go.etcd.io/bbolt/freelist_hmap.go index 02ef2be0..dbd67a1e 100644 --- a/vendor/go.etcd.io/bbolt/freelist_hmap.go +++ b/vendor/go.etcd.io/bbolt/freelist_hmap.go @@ -4,7 +4,7 @@ import "sort" // hashmapFreeCount returns count of free pages(hashmap version) func (f *freelist) hashmapFreeCount() int { - // use the forwardmap to get the total count + // use the forwardMap to get the total count count := 0 for _, size := range f.forwardMap { count += int(size) @@ -41,7 +41,7 @@ func (f *freelist) hashmapAllocate(txid txid, n int) pgid { for pid := range bm { // remove the initial - f.delSpan(pid, uint64(size)) + f.delSpan(pid, size) f.allocs[pid] = txid @@ -51,7 +51,7 @@ func (f *freelist) hashmapAllocate(txid txid, n int) pgid { f.addSpan(pid+pgid(n), remain) for i := pgid(0); i < pgid(n); i++ { - delete(f.cache, pid+pgid(i)) + delete(f.cache, pid+i) } return pid } diff --git a/vendor/go.etcd.io/bbolt/go.mod b/vendor/go.etcd.io/bbolt/go.mod index c2366dae..96355a69 100644 --- a/vendor/go.etcd.io/bbolt/go.mod +++ b/vendor/go.etcd.io/bbolt/go.mod @@ -2,4 +2,4 @@ module go.etcd.io/bbolt go 1.12 -require golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 +require golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d diff --git a/vendor/go.etcd.io/bbolt/go.sum b/vendor/go.etcd.io/bbolt/go.sum index 4ad15a48..c13f8f47 100644 --- a/vendor/go.etcd.io/bbolt/go.sum +++ b/vendor/go.etcd.io/bbolt/go.sum @@ -1,2 +1,2 @@ -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/go.etcd.io/bbolt/mlock_unix.go b/vendor/go.etcd.io/bbolt/mlock_unix.go new file mode 100644 index 00000000..6a6c7b35 --- /dev/null +++ b/vendor/go.etcd.io/bbolt/mlock_unix.go @@ -0,0 +1,36 @@ +// +build !windows + +package bbolt + +import "golang.org/x/sys/unix" + +// mlock locks memory of db file +func mlock(db *DB, fileSize int) error { + sizeToLock := fileSize + if sizeToLock > db.datasz { + // Can't lock more than mmaped slice + sizeToLock = db.datasz + } + if err := unix.Mlock(db.dataref[:sizeToLock]); err != nil { + return err + } + return nil +} + +//munlock unlocks memory of db file +func munlock(db *DB, fileSize int) error { + if db.dataref == nil { + return nil + } + + sizeToUnlock := fileSize + if sizeToUnlock > db.datasz { + // Can't unlock more than mmaped slice + sizeToUnlock = db.datasz + } + + if err := unix.Munlock(db.dataref[:sizeToUnlock]); err != nil { + return err + } + return nil +} diff --git a/vendor/go.etcd.io/bbolt/mlock_windows.go b/vendor/go.etcd.io/bbolt/mlock_windows.go new file mode 100644 index 00000000..b4a36a49 --- /dev/null +++ b/vendor/go.etcd.io/bbolt/mlock_windows.go @@ -0,0 +1,11 @@ +package bbolt + +// mlock locks memory of db file +func mlock(_ *DB, _ int) error { + panic("mlock is supported only on UNIX systems") +} + +//munlock unlocks memory of db file +func munlock(_ *DB, _ int) error { + panic("munlock is supported only on UNIX systems") +} diff --git a/vendor/go.etcd.io/bbolt/tx.go b/vendor/go.etcd.io/bbolt/tx.go index 4b1a64a8..869d4120 100644 --- a/vendor/go.etcd.io/bbolt/tx.go +++ b/vendor/go.etcd.io/bbolt/tx.go @@ -188,7 +188,6 @@ func (tx *Tx) Commit() error { } // If strict mode is enabled then perform a consistency check. - // Only the first consistency error is reported in the panic. if tx.db.StrictMode { ch := tx.Check() var errs []string @@ -393,7 +392,7 @@ func (tx *Tx) CopyFile(path string, mode os.FileMode) error { return err } - err = tx.Copy(f) + _, err = tx.WriteTo(f) if err != nil { _ = f.Close() return err diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go index 0d7bac3f..93da7322 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -26,6 +26,10 @@ const ( // NonceSizeX is the size of the nonce used with the XChaCha20-Poly1305 // variant of this AEAD, in bytes. NonceSizeX = 24 + + // Overhead is the size of the Poly1305 authentication tag, and the + // difference between a ciphertext length and its plaintext. + Overhead = 16 ) type chacha20poly1305 struct { @@ -47,7 +51,7 @@ func (c *chacha20poly1305) NonceSize() int { } func (c *chacha20poly1305) Overhead() int { - return 16 + return Overhead } func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go index fe191d39..96b2fd89 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go @@ -8,8 +8,8 @@ import ( "encoding/binary" "golang.org/x/crypto/chacha20" + "golang.org/x/crypto/internal/poly1305" "golang.org/x/crypto/internal/subtle" - "golang.org/x/crypto/poly1305" ) func writeWithPadding(p *poly1305.MAC, b []byte) { diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go index d9d46b96..1cebfe94 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go @@ -35,7 +35,7 @@ func (*xchacha20poly1305) NonceSize() int { } func (*xchacha20poly1305) Overhead() int { - return 16 + return Overhead } func (x *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { diff --git a/vendor/golang.org/x/crypto/poly1305/bits_compat.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/bits_compat.go rename to vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go diff --git a/vendor/golang.org/x/crypto/poly1305/bits_go1.13.go b/vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/bits_go1.13.go rename to vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go diff --git a/vendor/golang.org/x/crypto/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/mac_noasm.go rename to vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go similarity index 98% rename from vendor/golang.org/x/crypto/poly1305/poly1305.go rename to vendor/golang.org/x/crypto/internal/poly1305/poly1305.go index 9d7a6af0..4aaea810 100644 --- a/vendor/golang.org/x/crypto/poly1305/poly1305.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/poly1305.go @@ -15,7 +15,7 @@ // used with a fixed key in order to generate one-time keys from an nonce. // However, in this package AES isn't used and the one-time key is specified // directly. -package poly1305 // import "golang.org/x/crypto/poly1305" +package poly1305 import "crypto/subtle" diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/sum_amd64.go rename to vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/sum_amd64.s rename to vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s diff --git a/vendor/golang.org/x/crypto/poly1305/sum_generic.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/sum_generic.go rename to vendor/golang.org/x/crypto/internal/poly1305/sum_generic.go diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go similarity index 100% rename from vendor/golang.org/x/crypto/poly1305/sum_s390x.go rename to vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.go diff --git a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s similarity index 99% rename from vendor/golang.org/x/crypto/poly1305/sum_s390x.s rename to vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s index 69c64f84..aa9e0494 100644 --- a/vendor/golang.org/x/crypto/poly1305/sum_s390x.s +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_s390x.s @@ -18,7 +18,7 @@ // value. These limbs are, for the most part, zero extended and // placed into 64-bit vector register elements. Each vector // register is 128-bits wide and so holds 2 of these elements. -// Using 26-bit limbs allows us plenty of headroom to accomodate +// Using 26-bit limbs allows us plenty of headroom to accommodate // accumulations before and after multiplication without // overflowing either 32-bits (before multiplication) or 64-bits // (after multiplication). diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go index f91466f7..038941d7 100644 --- a/vendor/golang.org/x/net/html/parse.go +++ b/vendor/golang.org/x/net/html/parse.go @@ -663,6 +663,24 @@ func inHeadIM(p *parser) bool { // Ignore the token. return true case a.Template: + // TODO: remove this divergence from the HTML5 spec. + // + // We don't handle all of the corner cases when mixing foreign + // content (i.e. or ) with