WIP: Save agent roles integration work before CHORUS rebrand
- Agent roles and coordination features - Chat API integration testing - New configuration and workspace management 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
27
vendor/github.com/multiformats/go-base32/LICENSE
generated
vendored
Normal file
27
vendor/github.com/multiformats/go-base32/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 The Go Authors. 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.
|
||||
509
vendor/github.com/multiformats/go-base32/base32.go
generated
vendored
Normal file
509
vendor/github.com/multiformats/go-base32/base32.go
generated
vendored
Normal file
@@ -0,0 +1,509 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package base32 implements base32 encoding as specified by RFC 4648.
|
||||
package base32
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
/*
|
||||
* Encodings
|
||||
*/
|
||||
|
||||
// An Encoding is a radix 32 encoding/decoding scheme, defined by a
|
||||
// 32-character alphabet. The most common is the "base32" encoding
|
||||
// introduced for SASL GSSAPI and standardized in RFC 4648.
|
||||
// The alternate "base32hex" encoding is used in DNSSEC.
|
||||
type Encoding struct {
|
||||
encode string
|
||||
decodeMap [256]byte
|
||||
padChar rune
|
||||
}
|
||||
|
||||
// Alphabet returns the Base32 alphabet used
|
||||
func (enc *Encoding) Alphabet() string {
|
||||
return enc.encode
|
||||
}
|
||||
|
||||
const (
|
||||
StdPadding rune = '='
|
||||
NoPadding rune = -1
|
||||
)
|
||||
|
||||
const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
||||
const encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
|
||||
|
||||
// NewEncoding returns a new Encoding defined by the given alphabet,
|
||||
// which must be a 32-byte string.
|
||||
func NewEncoding(encoder string) *Encoding {
|
||||
e := new(Encoding)
|
||||
e.padChar = StdPadding
|
||||
e.encode = encoder
|
||||
for i := 0; i < len(e.decodeMap); i++ {
|
||||
e.decodeMap[i] = 0xFF
|
||||
}
|
||||
for i := 0; i < len(encoder); i++ {
|
||||
e.decodeMap[encoder[i]] = byte(i)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// NewEncoding returns a new case insensitive Encoding defined by the
|
||||
// given alphabet, which must be a 32-byte string.
|
||||
func NewEncodingCI(encoder string) *Encoding {
|
||||
e := new(Encoding)
|
||||
e.padChar = StdPadding
|
||||
e.encode = encoder
|
||||
for i := 0; i < len(e.decodeMap); i++ {
|
||||
e.decodeMap[i] = 0xFF
|
||||
}
|
||||
for i := 0; i < len(encoder); i++ {
|
||||
e.decodeMap[asciiToLower(encoder[i])] = byte(i)
|
||||
e.decodeMap[asciiToUpper(encoder[i])] = byte(i)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func asciiToLower(c byte) byte {
|
||||
if c >= 'A' && c <= 'Z' {
|
||||
return c + 32
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func asciiToUpper(c byte) byte {
|
||||
if c >= 'a' && c <= 'z' {
|
||||
return c - 32
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// WithPadding creates a new encoding identical to enc except
|
||||
// with a specified padding character, or NoPadding to disable padding.
|
||||
func (enc Encoding) WithPadding(padding rune) *Encoding {
|
||||
enc.padChar = padding
|
||||
return &enc
|
||||
}
|
||||
|
||||
// StdEncoding is the standard base32 encoding, as defined in
|
||||
// RFC 4648.
|
||||
var StdEncoding = NewEncodingCI(encodeStd)
|
||||
|
||||
// HexEncoding is the “Extended Hex Alphabet” defined in RFC 4648.
|
||||
// It is typically used in DNS.
|
||||
var HexEncoding = NewEncodingCI(encodeHex)
|
||||
|
||||
var RawStdEncoding = NewEncodingCI(encodeStd).WithPadding(NoPadding)
|
||||
var RawHexEncoding = NewEncodingCI(encodeHex).WithPadding(NoPadding)
|
||||
|
||||
/*
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
// Encode encodes src using the encoding enc, writing
|
||||
// EncodedLen(len(src)) bytes to dst.
|
||||
//
|
||||
// The encoding pads the output to a multiple of 8 bytes,
|
||||
// so Encode is not appropriate for use on individual blocks
|
||||
// of a large data stream. Use NewEncoder() instead.
|
||||
func (enc *Encoding) Encode(dst, src []byte) {
|
||||
if len(src) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Unpack 8x 5-bit source blocks into a 5 byte
|
||||
// destination quantum
|
||||
for len(src) > 4 {
|
||||
dst[7] = enc.encode[src[4]&0x1F]
|
||||
dst[6] = enc.encode[(src[4]>>5)|(src[3]<<3)&0x1F]
|
||||
dst[5] = enc.encode[(src[3]>>2)&0x1F]
|
||||
dst[4] = enc.encode[(src[3]>>7)|(src[2]<<1)&0x1F]
|
||||
dst[3] = enc.encode[((src[2]>>4)|(src[1]<<4))&0x1F]
|
||||
dst[2] = enc.encode[(src[1]>>1)&0x1F]
|
||||
dst[1] = enc.encode[((src[1]>>6)|(src[0]<<2))&0x1F]
|
||||
dst[0] = enc.encode[src[0]>>3]
|
||||
src = src[5:]
|
||||
dst = dst[8:]
|
||||
}
|
||||
|
||||
var carry byte
|
||||
|
||||
switch len(src) {
|
||||
case 4:
|
||||
dst[6] = enc.encode[(src[3]<<3)&0x1F]
|
||||
dst[5] = enc.encode[(src[3]>>2)&0x1F]
|
||||
carry = src[3] >> 7
|
||||
fallthrough
|
||||
case 3:
|
||||
dst[4] = enc.encode[carry|(src[2]<<1)&0x1F]
|
||||
carry = (src[2] >> 4) & 0x1F
|
||||
fallthrough
|
||||
case 2:
|
||||
dst[3] = enc.encode[carry|(src[1]<<4)&0x1F]
|
||||
dst[2] = enc.encode[(src[1]>>1)&0x1F]
|
||||
carry = (src[1] >> 6) & 0x1F
|
||||
fallthrough
|
||||
case 1:
|
||||
dst[1] = enc.encode[carry|(src[0]<<2)&0x1F]
|
||||
dst[0] = enc.encode[src[0]>>3]
|
||||
case 0:
|
||||
return
|
||||
}
|
||||
|
||||
if enc.padChar != NoPadding {
|
||||
dst[7] = byte(enc.padChar)
|
||||
if len(src) < 4 {
|
||||
dst[6] = byte(enc.padChar)
|
||||
dst[5] = byte(enc.padChar)
|
||||
if len(src) < 3 {
|
||||
dst[4] = byte(enc.padChar)
|
||||
if len(src) < 2 {
|
||||
dst[3] = byte(enc.padChar)
|
||||
dst[2] = byte(enc.padChar)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeToString returns the base32 encoding of src.
|
||||
func (enc *Encoding) EncodeToString(src []byte) string {
|
||||
buf := make([]byte, enc.EncodedLen(len(src)))
|
||||
enc.Encode(buf, src)
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
type encoder struct {
|
||||
err error
|
||||
enc *Encoding
|
||||
w io.Writer
|
||||
buf [5]byte // buffered data waiting to be encoded
|
||||
nbuf int // number of bytes in buf
|
||||
out [1024]byte // output buffer
|
||||
}
|
||||
|
||||
func (e *encoder) Write(p []byte) (n int, err error) {
|
||||
if e.err != nil {
|
||||
return 0, e.err
|
||||
}
|
||||
|
||||
// Leading fringe.
|
||||
if e.nbuf > 0 {
|
||||
var i int
|
||||
for i = 0; i < len(p) && e.nbuf < 5; i++ {
|
||||
e.buf[e.nbuf] = p[i]
|
||||
e.nbuf++
|
||||
}
|
||||
n += i
|
||||
p = p[i:]
|
||||
if e.nbuf < 5 {
|
||||
return
|
||||
}
|
||||
e.enc.Encode(e.out[0:], e.buf[0:])
|
||||
if _, e.err = e.w.Write(e.out[0:8]); e.err != nil {
|
||||
return n, e.err
|
||||
}
|
||||
e.nbuf = 0
|
||||
}
|
||||
|
||||
// Large interior chunks.
|
||||
for len(p) >= 5 {
|
||||
nn := len(e.out) / 8 * 5
|
||||
if nn > len(p) {
|
||||
nn = len(p)
|
||||
nn -= nn % 5
|
||||
}
|
||||
e.enc.Encode(e.out[0:], p[0:nn])
|
||||
if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil {
|
||||
return n, e.err
|
||||
}
|
||||
n += nn
|
||||
p = p[nn:]
|
||||
}
|
||||
|
||||
// Trailing fringe.
|
||||
//lint:ignore S1001 fixed-length 5-byte slice
|
||||
for i := 0; i < len(p); i++ {
|
||||
e.buf[i] = p[i]
|
||||
}
|
||||
e.nbuf = len(p)
|
||||
n += len(p)
|
||||
return
|
||||
}
|
||||
|
||||
// Close flushes any pending output from the encoder.
|
||||
// It is an error to call Write after calling Close.
|
||||
func (e *encoder) Close() error {
|
||||
// If there's anything left in the buffer, flush it out
|
||||
if e.err == nil && e.nbuf > 0 {
|
||||
e.enc.Encode(e.out[0:], e.buf[0:e.nbuf])
|
||||
e.nbuf = 0
|
||||
_, e.err = e.w.Write(e.out[0:8])
|
||||
}
|
||||
return e.err
|
||||
}
|
||||
|
||||
// NewEncoder returns a new base32 stream encoder. Data written to
|
||||
// the returned writer will be encoded using enc and then written to w.
|
||||
// Base32 encodings operate in 5-byte blocks; when finished
|
||||
// writing, the caller must Close the returned encoder to flush any
|
||||
// partially written blocks.
|
||||
func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
|
||||
return &encoder{enc: enc, w: w}
|
||||
}
|
||||
|
||||
// EncodedLen returns the length in bytes of the base32 encoding
|
||||
// of an input buffer of length n.
|
||||
func (enc *Encoding) EncodedLen(n int) int {
|
||||
if enc.padChar == NoPadding {
|
||||
return (n*8 + 4) / 5 // minimum # chars at 5 bits per char
|
||||
}
|
||||
return (n + 4) / 5 * 8
|
||||
}
|
||||
|
||||
/*
|
||||
* Decoder
|
||||
*/
|
||||
|
||||
type CorruptInputError int64
|
||||
|
||||
func (e CorruptInputError) Error() string {
|
||||
return "illegal base32 data at input byte " + strconv.FormatInt(int64(e), 10)
|
||||
}
|
||||
|
||||
// decode is like Decode but returns an additional 'end' value, which
|
||||
// indicates if end-of-message padding was encountered and thus any
|
||||
// additional data is an error. This method assumes that src has been
|
||||
// stripped of all supported whitespace ('\r' and '\n').
|
||||
func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
olen := len(src)
|
||||
for len(src) > 0 && !end {
|
||||
// Decode quantum using the base32 alphabet
|
||||
var dbuf [8]byte
|
||||
dlen := 8
|
||||
|
||||
for j := 0; j < 8; {
|
||||
if len(src) == 0 {
|
||||
if enc.padChar != NoPadding {
|
||||
return n, false, CorruptInputError(olen - len(src) - j)
|
||||
}
|
||||
dlen = j
|
||||
break
|
||||
}
|
||||
in := src[0]
|
||||
src = src[1:]
|
||||
if in == byte(enc.padChar) && j >= 2 && len(src) < 8 {
|
||||
if enc.padChar == NoPadding {
|
||||
return n, false, CorruptInputError(olen)
|
||||
}
|
||||
|
||||
// We've reached the end and there's padding
|
||||
if len(src)+j < 8-1 {
|
||||
// not enough padding
|
||||
return n, false, CorruptInputError(olen)
|
||||
}
|
||||
for k := 0; k < 8-1-j; k++ {
|
||||
if len(src) > k && src[k] != byte(enc.padChar) {
|
||||
// incorrect padding
|
||||
return n, false, CorruptInputError(olen - len(src) + k - 1)
|
||||
}
|
||||
}
|
||||
dlen, end = j, true
|
||||
// 7, 5 and 2 are not valid padding lengths, and so 1, 3 and 6 are not
|
||||
// valid dlen values. See RFC 4648 Section 6 "Base 32 Encoding" listing
|
||||
// the five valid padding lengths, and Section 9 "Illustrations and
|
||||
// Examples" for an illustration for how the 1st, 3rd and 6th base32
|
||||
// src bytes do not yield enough information to decode a dst byte.
|
||||
if dlen == 1 || dlen == 3 || dlen == 6 {
|
||||
return n, false, CorruptInputError(olen - len(src) - 1)
|
||||
}
|
||||
break
|
||||
}
|
||||
dbuf[j] = enc.decodeMap[in]
|
||||
if dbuf[j] == 0xFF {
|
||||
return n, false, CorruptInputError(olen - len(src) - 1)
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
// Pack 8x 5-bit source blocks into 5 byte destination
|
||||
// quantum
|
||||
switch dlen {
|
||||
case 8:
|
||||
dst[4] = dbuf[6]<<5 | dbuf[7]
|
||||
fallthrough
|
||||
case 7:
|
||||
dst[3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
|
||||
fallthrough
|
||||
case 5:
|
||||
dst[2] = dbuf[3]<<4 | dbuf[4]>>1
|
||||
fallthrough
|
||||
case 4:
|
||||
dst[1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
|
||||
fallthrough
|
||||
case 2:
|
||||
dst[0] = dbuf[0]<<3 | dbuf[1]>>2
|
||||
}
|
||||
|
||||
if len(dst) > 5 {
|
||||
dst = dst[5:]
|
||||
}
|
||||
|
||||
switch dlen {
|
||||
case 2:
|
||||
n += 1
|
||||
case 4:
|
||||
n += 2
|
||||
case 5:
|
||||
n += 3
|
||||
case 7:
|
||||
n += 4
|
||||
case 8:
|
||||
n += 5
|
||||
}
|
||||
}
|
||||
return n, end, nil
|
||||
}
|
||||
|
||||
// Decode decodes src using the encoding enc. It writes at most
|
||||
// DecodedLen(len(src)) bytes to dst and returns the number of bytes
|
||||
// written. If src contains invalid base32 data, it will return the
|
||||
// number of bytes successfully written and CorruptInputError.
|
||||
// New line characters (\r and \n) are ignored.
|
||||
func (enc *Encoding) Decode(dst, s []byte) (n int, err error) {
|
||||
// FIXME: if dst is the same as s use decodeInPlace
|
||||
stripped := make([]byte, 0, len(s))
|
||||
for _, c := range s {
|
||||
if c != '\r' && c != '\n' {
|
||||
stripped = append(stripped, c)
|
||||
}
|
||||
}
|
||||
n, _, err = enc.decode(dst, stripped)
|
||||
return
|
||||
}
|
||||
|
||||
func (enc *Encoding) decodeInPlace(strb []byte) (n int, err error) {
|
||||
off := 0
|
||||
for _, b := range strb {
|
||||
if b == '\n' || b == '\r' {
|
||||
continue
|
||||
}
|
||||
strb[off] = b
|
||||
off++
|
||||
}
|
||||
n, _, err = enc.decode(strb, strb[:off])
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeString returns the bytes represented by the base32 string s.
|
||||
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
|
||||
strb := []byte(s)
|
||||
n, err := enc.decodeInPlace(strb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return strb[:n], nil
|
||||
}
|
||||
|
||||
type decoder struct {
|
||||
err error
|
||||
enc *Encoding
|
||||
r io.Reader
|
||||
end bool // saw end of message
|
||||
buf [1024]byte // leftover input
|
||||
nbuf int
|
||||
out []byte // leftover decoded output
|
||||
outbuf [1024 / 8 * 5]byte
|
||||
}
|
||||
|
||||
func (d *decoder) Read(p []byte) (n int, err error) {
|
||||
if d.err != nil {
|
||||
return 0, d.err
|
||||
}
|
||||
|
||||
// Use leftover decoded output from last read.
|
||||
if len(d.out) > 0 {
|
||||
n = copy(p, d.out)
|
||||
d.out = d.out[n:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Read a chunk.
|
||||
nn := len(p) / 5 * 8
|
||||
if nn < 8 {
|
||||
nn = 8
|
||||
}
|
||||
if nn > len(d.buf) {
|
||||
nn = len(d.buf)
|
||||
}
|
||||
nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 8-d.nbuf)
|
||||
d.nbuf += nn
|
||||
if d.nbuf < 8 {
|
||||
return 0, d.err
|
||||
}
|
||||
|
||||
// Decode chunk into p, or d.out and then p if p is too small.
|
||||
nr := d.nbuf / 8 * 8
|
||||
nw := d.nbuf / 8 * 5
|
||||
if nw > len(p) {
|
||||
nw, d.end, d.err = d.enc.decode(d.outbuf[0:], d.buf[0:nr])
|
||||
d.out = d.outbuf[0:nw]
|
||||
n = copy(p, d.out)
|
||||
d.out = d.out[n:]
|
||||
} else {
|
||||
n, d.end, d.err = d.enc.decode(p, d.buf[0:nr])
|
||||
}
|
||||
d.nbuf -= nr
|
||||
for i := 0; i < d.nbuf; i++ {
|
||||
d.buf[i] = d.buf[i+nr]
|
||||
}
|
||||
|
||||
if d.err == nil {
|
||||
d.err = err
|
||||
}
|
||||
return n, d.err
|
||||
}
|
||||
|
||||
type newlineFilteringReader struct {
|
||||
wrapped io.Reader
|
||||
}
|
||||
|
||||
func (r *newlineFilteringReader) Read(p []byte) (int, error) {
|
||||
n, err := r.wrapped.Read(p)
|
||||
for n > 0 {
|
||||
offset := 0
|
||||
for i, b := range p[0:n] {
|
||||
if b != '\r' && b != '\n' {
|
||||
if i != offset {
|
||||
p[offset] = b
|
||||
}
|
||||
offset++
|
||||
}
|
||||
}
|
||||
if offset > 0 {
|
||||
return offset, err
|
||||
}
|
||||
// Previous buffer entirely whitespace, read again
|
||||
n, err = r.wrapped.Read(p)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// NewDecoder constructs a new base32 stream decoder.
|
||||
func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
|
||||
return &decoder{enc: enc, r: &newlineFilteringReader{r}}
|
||||
}
|
||||
|
||||
// DecodedLen returns the maximum length in bytes of the decoded data
|
||||
// corresponding to n bytes of base32-encoded data.
|
||||
func (enc *Encoding) DecodedLen(n int) int {
|
||||
if enc.padChar == NoPadding {
|
||||
return (n*5 + 7) / 8
|
||||
}
|
||||
|
||||
return n / 8 * 5
|
||||
}
|
||||
15
vendor/github.com/multiformats/go-base32/package.json
generated
vendored
Normal file
15
vendor/github.com/multiformats/go-base32/package.json
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"author": "Golang",
|
||||
"bugs": {
|
||||
"url": "https://github.com/multiformats/go-base32"
|
||||
},
|
||||
"gx": {
|
||||
"dvcsimport": "github.com/multiformats/go-base32"
|
||||
},
|
||||
"gxVersion": "0.7.0",
|
||||
"language": "go",
|
||||
"license": "BSD-3",
|
||||
"name": "base32",
|
||||
"version": "0.0.3"
|
||||
}
|
||||
|
||||
3
vendor/github.com/multiformats/go-base32/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-base32/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.1.0"
|
||||
}
|
||||
22
vendor/github.com/multiformats/go-base36/LICENSE.md
generated
vendored
Normal file
22
vendor/github.com/multiformats/go-base36/LICENSE.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The software contents of this repository are Copyright (c) Protocol Labs,
|
||||
Licensed under the `Permissive License Stack`, meaning either of:
|
||||
|
||||
- Apache-2.0 Software License: https://www.apache.org/licenses/LICENSE-2.0
|
||||
([...4tr2kfsq](https://gateway.ipfs.io/ipfs/bafkreiankqxazcae4onkp436wag2lj3ccso4nawxqkkfckd6cg4tr2kfsq))
|
||||
|
||||
- MIT Software License: https://opensource.org/licenses/MIT
|
||||
([...vljevcba](https://gateway.ipfs.io/ipfs/bafkreiepofszg4gfe2gzuhojmksgemsub2h4uy2gewdnr35kswvljevcba))
|
||||
|
||||
You may not use the contents of this repository except in compliance
|
||||
with one of the listed Licenses. For an extended clarification of the
|
||||
intent behind the choice of Licensing please refer to
|
||||
https://protocol.ai/blog/announcing-the-permissive-license-stack/
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the terms listed in this notice is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
either express or implied. See each License for the specific language
|
||||
governing permissions and limitations under that License.
|
||||
|
||||
<!--- SPDX-License-Identifier: Apache-2.0 OR MIT -->
|
||||
`SPDX-License-Identifier: Apache-2.0 OR MIT`
|
||||
22
vendor/github.com/multiformats/go-base36/README.md
generated
vendored
Normal file
22
vendor/github.com/multiformats/go-base36/README.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
multiformats/go-base36
|
||||
=======================
|
||||
|
||||
> Simple base36 codec
|
||||
|
||||
This is an optimized codec for []byte <=> base36 string conversion
|
||||
|
||||
## Documentation
|
||||
|
||||
https://pkg.go.dev/github.com/multiformats/go-base36
|
||||
|
||||
## Lead Maintainer
|
||||
|
||||
[Steven Allen](https://github.com/stebalien)
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! This repository is related to the IPFS project and therefore governed by our [contributing guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
[SPDX-License-Identifier: Apache-2.0 OR MIT](LICENSE.md)
|
||||
143
vendor/github.com/multiformats/go-base36/base36.go
generated
vendored
Normal file
143
vendor/github.com/multiformats/go-base36/base36.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Package base36 provides a reasonably fast implementation of a binary base36 codec.
|
||||
*/
|
||||
package base36
|
||||
|
||||
// Simplified code based on https://godoc.org/github.com/mr-tron/base58
|
||||
// which in turn is based on https://github.com/trezor/trezor-crypto/commit/89a7d7797b806fac
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const UcAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
const LcAlphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
const maxDigitOrdinal = 'z'
|
||||
const maxDigitValueB36 = 35
|
||||
|
||||
var revAlphabet [maxDigitOrdinal + 1]byte
|
||||
|
||||
func init() {
|
||||
for i := range revAlphabet {
|
||||
revAlphabet[i] = maxDigitValueB36 + 1
|
||||
}
|
||||
for i, c := range UcAlphabet {
|
||||
revAlphabet[byte(c)] = byte(i)
|
||||
if c > '9' {
|
||||
revAlphabet[byte(c)+32] = byte(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeToStringUc encodes the given byte-buffer as base36 using [0-9A-Z] as
|
||||
// the digit-alphabet
|
||||
func EncodeToStringUc(b []byte) string { return encode(b, UcAlphabet) }
|
||||
|
||||
// EncodeToStringLc encodes the given byte-buffer as base36 using [0-9a-z] as
|
||||
// the digit-alphabet
|
||||
func EncodeToStringLc(b []byte) string { return encode(b, LcAlphabet) }
|
||||
|
||||
func encode(inBuf []byte, al string) string {
|
||||
|
||||
bufsz := len(inBuf)
|
||||
zcnt := 0
|
||||
for zcnt < bufsz && inBuf[zcnt] == 0 {
|
||||
zcnt++
|
||||
}
|
||||
|
||||
// It is crucial to make this as short as possible, especially for
|
||||
// the usual case of CIDs.
|
||||
bufsz = zcnt +
|
||||
// This is an integer simplification of
|
||||
// ceil(log(256)/log(36))
|
||||
(bufsz-zcnt)*277/179 + 1
|
||||
|
||||
// Note: pools *DO NOT* help, the overhead of zeroing
|
||||
// kills any performance gain to be had
|
||||
out := make([]byte, bufsz)
|
||||
|
||||
var idx, stopIdx int
|
||||
var carry uint32
|
||||
|
||||
stopIdx = bufsz - 1
|
||||
for _, b := range inBuf[zcnt:] {
|
||||
idx = bufsz - 1
|
||||
for carry = uint32(b); idx > stopIdx || carry != 0; idx-- {
|
||||
carry += uint32((out[idx])) * 256
|
||||
out[idx] = byte(carry % 36)
|
||||
carry /= 36
|
||||
}
|
||||
stopIdx = idx
|
||||
}
|
||||
|
||||
// Determine the additional "zero-gap" in the buffer (aside from zcnt)
|
||||
for stopIdx = zcnt; stopIdx < bufsz && out[stopIdx] == 0; stopIdx++ {
|
||||
}
|
||||
|
||||
// Now encode the values with actual alphabet in-place
|
||||
vBuf := out[stopIdx-zcnt:]
|
||||
bufsz = len(vBuf)
|
||||
for idx = 0; idx < bufsz; idx++ {
|
||||
out[idx] = al[vBuf[idx]]
|
||||
}
|
||||
|
||||
return string(out[:bufsz])
|
||||
}
|
||||
|
||||
// DecodeString takes a base36 encoded string and returns a slice of the decoded
|
||||
// bytes.
|
||||
func DecodeString(s string) ([]byte, error) {
|
||||
|
||||
if len(s) == 0 {
|
||||
return nil, fmt.Errorf("can not decode zero-length string")
|
||||
}
|
||||
|
||||
zcnt := 0
|
||||
for zcnt < len(s) && s[zcnt] == '0' {
|
||||
zcnt++
|
||||
}
|
||||
|
||||
// the 32bit algo stretches the result up to 2 times
|
||||
binu := make([]byte, 2*(((len(s))*179/277)+1)) // no more than 84 bytes when len(s) <= 64
|
||||
outi := make([]uint32, (len(s)+3)/4) // no more than 16 bytes when len(s) <= 64
|
||||
|
||||
for _, r := range s {
|
||||
if r > maxDigitOrdinal || revAlphabet[r] > maxDigitValueB36 {
|
||||
return nil, fmt.Errorf("invalid base36 character (%q)", r)
|
||||
}
|
||||
|
||||
c := uint64(revAlphabet[r])
|
||||
|
||||
for j := len(outi) - 1; j >= 0; j-- {
|
||||
t := uint64(outi[j])*36 + c
|
||||
c = (t >> 32)
|
||||
outi[j] = uint32(t & 0xFFFFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
mask := (uint(len(s)%4) * 8)
|
||||
if mask == 0 {
|
||||
mask = 32
|
||||
}
|
||||
mask -= 8
|
||||
|
||||
outidx := 0
|
||||
for j := 0; j < len(outi); j++ {
|
||||
for mask < 32 { // loop relies on uint overflow
|
||||
binu[outidx] = byte(outi[j] >> mask)
|
||||
mask -= 8
|
||||
outidx++
|
||||
}
|
||||
mask = 24
|
||||
}
|
||||
|
||||
// find the most significant byte post-decode, if any
|
||||
for msb := zcnt; msb < outidx; msb++ {
|
||||
if binu[msb] > 0 {
|
||||
return binu[msb-zcnt : outidx : outidx], nil
|
||||
}
|
||||
}
|
||||
|
||||
// it's all zeroes
|
||||
return binu[:outidx:outidx], nil
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-base36/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-base36/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.2.0"
|
||||
}
|
||||
1
vendor/github.com/multiformats/go-multiaddr-dns/.gitignore
generated
vendored
Normal file
1
vendor/github.com/multiformats/go-multiaddr-dns/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/madns/madns
|
||||
30
vendor/github.com/multiformats/go-multiaddr-dns/.travis.yml
generated
vendored
Normal file
30
vendor/github.com/multiformats/go-multiaddr-dns/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
os:
|
||||
- linux
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.15.x
|
||||
|
||||
env:
|
||||
global:
|
||||
- GOTFLAGS="-race"
|
||||
matrix:
|
||||
- BUILD_DEPTYPE=gomod
|
||||
|
||||
|
||||
# disable travis install
|
||||
install:
|
||||
- true
|
||||
|
||||
script:
|
||||
- bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh)
|
||||
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/pkg/mod
|
||||
- /home/travis/.cache/go-build
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
21
vendor/github.com/multiformats/go-multiaddr-dns/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multiaddr-dns/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Juan Batiz-Benet
|
||||
|
||||
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.
|
||||
57
vendor/github.com/multiformats/go-multiaddr-dns/README.md
generated
vendored
Normal file
57
vendor/github.com/multiformats/go-multiaddr-dns/README.md
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# go-multiaddr-dns
|
||||
|
||||
> Resolve /dns4, /dns6, and /dnsaddr multiaddrs.
|
||||
|
||||
```sh
|
||||
> madns /dnsaddr/ipfs.io/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||
/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||
/ip6/2604:a880:1:20::1d9:6001/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||
/ip6/fc3d:9a4e:3c96:2fd2:1afa:18fe:8dd2:b602/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||
/dns4/jupiter.i.ipfs.io/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||
/dns6/jupiter.i.ipfs.io/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||
```
|
||||
|
||||
|
||||
In more detail:
|
||||
|
||||
```sh
|
||||
> madns /dns6/example.net
|
||||
/ip6/2001:db8::a3
|
||||
/ip6/2001:db8::a4
|
||||
...
|
||||
|
||||
> madns /dns4/example.net/tcp/443/wss
|
||||
/ip4/192.0.2.1/tcp/443/wss
|
||||
/ip4/192.0.2.2/tcp/443/wss
|
||||
|
||||
# No-op if it's not a dns-ish address.
|
||||
|
||||
> madns /ip4/127.0.0.1/tcp/8080
|
||||
/ip4/127.0.0.1/tcp/8080
|
||||
|
||||
# /dnsaddr resolves by looking up TXT records.
|
||||
|
||||
> dig +short TXT _dnsaddr.example.net
|
||||
"dnsaddr=/ip6/2001:db8::a3/tcp/443/wss/ipfs/Qmfoo"
|
||||
"dnsaddr=/ip6/2001:db8::a4/tcp/443/wss/ipfs/Qmbar"
|
||||
"dnsaddr=/ip4/192.0.2.1/tcp/443/wss/ipfs/Qmfoo"
|
||||
"dnsaddr=/ip4/192.0.2.2/tcp/443/wss/ipfs/Qmbar"
|
||||
...
|
||||
|
||||
# /dnsaddr returns addrs which encapsulate whatever /dnsaddr encapsulates too.
|
||||
|
||||
> madns example.net/ipfs/Qmfoo
|
||||
info: changing query to /dnsaddr/example.net/ipfs/Qmfoo
|
||||
/ip6/2001:db8::a3/tcp/443/wss/ipfs/Qmfoo
|
||||
/ip4/192.0.2.1/tcp/443/wss/ipfs/Qmfoo
|
||||
|
||||
# TODO -p filters by protocol stacks.
|
||||
|
||||
> madns -p /ip6/tcp/wss /dnsaddr/example.net
|
||||
/ip6/2001:db8::a3/tcp/443/wss/ipfs/Qmfoo
|
||||
/ip6/2001:db8::a4/tcp/443/wss/ipfs/Qmbar
|
||||
|
||||
# TODO -c filters by CIDR
|
||||
> madns -c /ip4/104.236.76.0/ipcidr/24 /dnsaddr/example.net
|
||||
/ip4/192.0.2.2/tcp/443/wss/ipfs/Qmbar
|
||||
```
|
||||
29
vendor/github.com/multiformats/go-multiaddr-dns/dns.go
generated
vendored
Normal file
29
vendor/github.com/multiformats/go-multiaddr-dns/dns.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package madns
|
||||
|
||||
import (
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// Extracted from source of truth for multicodec codes: https://github.com/multiformats/multicodec
|
||||
const (
|
||||
// Deprecated: use ma.P_DNS
|
||||
P_DNS = ma.P_DNS
|
||||
// Deprecated: use ma.P_DNS4
|
||||
P_DNS4 = ma.P_DNS4
|
||||
// Deprecated: use ma.P_DNS6
|
||||
P_DNS6 = ma.P_DNS6
|
||||
// Deprecated: use ma.P_DNSADDR
|
||||
P_DNSADDR = ma.P_DNSADDR
|
||||
)
|
||||
|
||||
// Deprecated: use ma.ProtocolWithCode(P_DNS)
|
||||
var DnsProtocol = ma.ProtocolWithCode(P_DNS)
|
||||
|
||||
// Deprecated: use ma.ProtocolWithCode(P_DNS4)
|
||||
var Dns4Protocol = ma.ProtocolWithCode(P_DNS4)
|
||||
|
||||
// Deprecated: use ma.ProtocolWithCode(P_DNS6)
|
||||
var Dns6Protocol = ma.ProtocolWithCode(P_DNS6)
|
||||
|
||||
// Deprecated: use ma.ProtocolWithCode(P_DNSADDR)
|
||||
var DnsaddrProtocol = ma.ProtocolWithCode(P_DNSADDR)
|
||||
31
vendor/github.com/multiformats/go-multiaddr-dns/mock.go
generated
vendored
Normal file
31
vendor/github.com/multiformats/go-multiaddr-dns/mock.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package madns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
)
|
||||
|
||||
type MockResolver struct {
|
||||
IP map[string][]net.IPAddr
|
||||
TXT map[string][]string
|
||||
}
|
||||
|
||||
var _ BasicResolver = (*MockResolver)(nil)
|
||||
|
||||
func (r *MockResolver) LookupIPAddr(ctx context.Context, name string) ([]net.IPAddr, error) {
|
||||
results, ok := r.IP[name]
|
||||
if ok {
|
||||
return results, nil
|
||||
} else {
|
||||
return []net.IPAddr{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MockResolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
|
||||
results, ok := r.TXT[name]
|
||||
if ok {
|
||||
return results, nil
|
||||
} else {
|
||||
return []string{}, nil
|
||||
}
|
||||
}
|
||||
281
vendor/github.com/multiformats/go-multiaddr-dns/resolve.go
generated
vendored
Normal file
281
vendor/github.com/multiformats/go-multiaddr-dns/resolve.go
generated
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
package madns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
var ResolvableProtocols = []ma.Protocol{DnsaddrProtocol, Dns4Protocol, Dns6Protocol, DnsProtocol}
|
||||
var DefaultResolver = &Resolver{def: net.DefaultResolver}
|
||||
|
||||
const dnsaddrTXTPrefix = "dnsaddr="
|
||||
|
||||
// BasicResolver is a low level interface for DNS resolution
|
||||
type BasicResolver interface {
|
||||
LookupIPAddr(context.Context, string) ([]net.IPAddr, error)
|
||||
LookupTXT(context.Context, string) ([]string, error)
|
||||
}
|
||||
|
||||
// Resolver is an object capable of resolving dns multiaddrs by using one or more BasicResolvers;
|
||||
// it supports custom per domain/TLD resolvers.
|
||||
// It also implements the BasicResolver interface so that it can act as a custom per domain/TLD
|
||||
// resolver.
|
||||
type Resolver struct {
|
||||
def BasicResolver
|
||||
custom map[string]BasicResolver
|
||||
}
|
||||
|
||||
var _ BasicResolver = (*Resolver)(nil)
|
||||
|
||||
// NewResolver creates a new Resolver instance with the specified options
|
||||
func NewResolver(opts ...Option) (*Resolver, error) {
|
||||
r := &Resolver{def: net.DefaultResolver}
|
||||
for _, opt := range opts {
|
||||
err := opt(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
type Option func(*Resolver) error
|
||||
|
||||
// WithDefaultResolver is an option that specifies the default basic resolver,
|
||||
// which resolves any TLD that doesn't have a custom resolver.
|
||||
// Defaults to net.DefaultResolver
|
||||
func WithDefaultResolver(def BasicResolver) Option {
|
||||
return func(r *Resolver) error {
|
||||
r.def = def
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithDomainResolver specifies a custom resolver for a domain/TLD.
|
||||
// Custom resolver selection matches domains left to right, with more specific resolvers
|
||||
// superseding generic ones.
|
||||
func WithDomainResolver(domain string, rslv BasicResolver) Option {
|
||||
return func(r *Resolver) error {
|
||||
if r.custom == nil {
|
||||
r.custom = make(map[string]BasicResolver)
|
||||
}
|
||||
fqdn := dns.Fqdn(domain)
|
||||
r.custom[fqdn] = rslv
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Resolver) getResolver(domain string) BasicResolver {
|
||||
fqdn := dns.Fqdn(domain)
|
||||
|
||||
// we match left-to-right, with more specific resolvers superseding generic ones.
|
||||
// So for a domain a.b.c, we will try a.b,c, b.c, c, and fallback to the default if
|
||||
// there is no match
|
||||
rslv, ok := r.custom[fqdn]
|
||||
if ok {
|
||||
return rslv
|
||||
}
|
||||
|
||||
for i := strings.Index(fqdn, "."); i != -1; i = strings.Index(fqdn, ".") {
|
||||
fqdn = fqdn[i+1:]
|
||||
if fqdn == "" {
|
||||
// the . is the default resolver
|
||||
break
|
||||
}
|
||||
|
||||
rslv, ok = r.custom[fqdn]
|
||||
if ok {
|
||||
return rslv
|
||||
}
|
||||
}
|
||||
|
||||
return r.def
|
||||
}
|
||||
|
||||
// Resolve resolves a DNS multiaddr.
|
||||
func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
|
||||
var results []ma.Multiaddr
|
||||
for i := 0; maddr != nil; i++ {
|
||||
var keep ma.Multiaddr
|
||||
|
||||
// Find the next dns component.
|
||||
keep, maddr = ma.SplitFunc(maddr, func(c ma.Component) bool {
|
||||
switch c.Protocol().Code {
|
||||
case DnsProtocol.Code, Dns4Protocol.Code, Dns6Protocol.Code, DnsaddrProtocol.Code:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
// Keep everything before the dns component.
|
||||
if keep != nil {
|
||||
if len(results) == 0 {
|
||||
results = []ma.Multiaddr{keep}
|
||||
} else {
|
||||
for i, r := range results {
|
||||
results[i] = r.Encapsulate(keep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the rest is empty, we've hit the end (there _was_ no dns component).
|
||||
if maddr == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// split off the dns component.
|
||||
var resolve *ma.Component
|
||||
resolve, maddr = ma.SplitFirst(maddr)
|
||||
|
||||
proto := resolve.Protocol()
|
||||
value := resolve.Value()
|
||||
rslv := r.getResolver(value)
|
||||
|
||||
// resolve the dns component
|
||||
var resolved []ma.Multiaddr
|
||||
switch proto.Code {
|
||||
case Dns4Protocol.Code, Dns6Protocol.Code, DnsProtocol.Code:
|
||||
// The dns, dns4, and dns6 resolver simply resolves each
|
||||
// dns* component into an ipv4/ipv6 address.
|
||||
|
||||
v4only := proto.Code == Dns4Protocol.Code
|
||||
v6only := proto.Code == Dns6Protocol.Code
|
||||
|
||||
// XXX: Unfortunately, go does a pretty terrible job of
|
||||
// differentiating between IPv6 and IPv4. A v4-in-v6
|
||||
// AAAA record will _look_ like an A record to us and
|
||||
// there's nothing we can do about that.
|
||||
records, err := rslv.LookupIPAddr(ctx, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert each DNS record into a multiaddr. If the
|
||||
// protocol is dns4, throw away any IPv6 addresses. If
|
||||
// the protocol is dns6, throw away any IPv4 addresses.
|
||||
|
||||
for _, r := range records {
|
||||
var (
|
||||
rmaddr ma.Multiaddr
|
||||
err error
|
||||
)
|
||||
ip4 := r.IP.To4()
|
||||
if ip4 == nil {
|
||||
if v4only {
|
||||
continue
|
||||
}
|
||||
rmaddr, err = ma.NewMultiaddr("/ip6/" + r.IP.String())
|
||||
} else {
|
||||
if v6only {
|
||||
continue
|
||||
}
|
||||
rmaddr, err = ma.NewMultiaddr("/ip4/" + ip4.String())
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resolved = append(resolved, rmaddr)
|
||||
}
|
||||
case DnsaddrProtocol.Code:
|
||||
// The dnsaddr resolver is a bit more complicated. We:
|
||||
//
|
||||
// 1. Lookup the dnsaddr txt record on _dnsaddr.DOMAIN.TLD
|
||||
// 2. Take everything _after_ the `/dnsaddr/DOMAIN.TLD`
|
||||
// part of the multiaddr.
|
||||
// 3. Find the dnsaddr records (if any) with suffixes
|
||||
// matching the result of step 2.
|
||||
|
||||
// First, lookup the TXT record
|
||||
records, err := rslv.LookupTXT(ctx, "_dnsaddr."+value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Then, calculate the length of the suffix we're
|
||||
// looking for.
|
||||
length := 0
|
||||
if maddr != nil {
|
||||
length = addrLen(maddr)
|
||||
}
|
||||
|
||||
for _, r := range records {
|
||||
// Ignore non dnsaddr TXT records.
|
||||
if !strings.HasPrefix(r, dnsaddrTXTPrefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Extract and decode the multiaddr.
|
||||
rmaddr, err := ma.NewMultiaddr(r[len(dnsaddrTXTPrefix):])
|
||||
if err != nil {
|
||||
// discard multiaddrs we don't understand.
|
||||
// XXX: Is this right? It's the best we
|
||||
// can do for now, really.
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have a suffix to match on.
|
||||
if maddr != nil {
|
||||
// Make sure the new address is at least
|
||||
// as long as the suffix we're looking
|
||||
// for.
|
||||
rmlen := addrLen(rmaddr)
|
||||
if rmlen < length {
|
||||
// not long enough.
|
||||
continue
|
||||
}
|
||||
|
||||
// Matches everything after the /dnsaddr/... with the end of the
|
||||
// dnsaddr record:
|
||||
//
|
||||
// v----------rmlen-----------------v
|
||||
// /ip4/1.2.3.4/tcp/1234/p2p/QmFoobar
|
||||
// /p2p/QmFoobar
|
||||
// ^--(rmlen - length)--^---length--^
|
||||
if !maddr.Equal(offset(rmaddr, rmlen-length)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
resolved = append(resolved, rmaddr)
|
||||
}
|
||||
|
||||
// consumes the rest of the multiaddr as part of the "match" process.
|
||||
maddr = nil
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
if len(resolved) == 0 {
|
||||
return nil, nil
|
||||
} else if len(results) == 0 {
|
||||
results = resolved
|
||||
} else {
|
||||
// We take the cross product here as we don't have any
|
||||
// better way to represent "ORs" in multiaddrs. For
|
||||
// example, `/dns/foo.com/p2p-circuit/dns/bar.com` could
|
||||
// resolve to:
|
||||
//
|
||||
// * /ip4/1.1.1.1/p2p-circuit/ip4/2.1.1.1
|
||||
// * /ip4/1.1.1.1/p2p-circuit/ip4/2.1.1.2
|
||||
// * /ip4/1.1.1.2/p2p-circuit/ip4/2.1.1.1
|
||||
// * /ip4/1.1.1.2/p2p-circuit/ip4/2.1.1.2
|
||||
results = cross(results, resolved)
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (r *Resolver) LookupIPAddr(ctx context.Context, domain string) ([]net.IPAddr, error) {
|
||||
return r.getResolver(domain).LookupIPAddr(ctx, domain)
|
||||
}
|
||||
|
||||
func (r *Resolver) LookupTXT(ctx context.Context, txt string) ([]string, error) {
|
||||
return r.getResolver(txt).LookupTXT(ctx, txt)
|
||||
}
|
||||
57
vendor/github.com/multiformats/go-multiaddr-dns/util.go
generated
vendored
Normal file
57
vendor/github.com/multiformats/go-multiaddr-dns/util.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package madns
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
func Matches(maddr ma.Multiaddr) (matches bool) {
|
||||
ma.ForEach(maddr, func(c ma.Component) bool {
|
||||
switch c.Protocol().Code {
|
||||
case DnsProtocol.Code, Dns4Protocol.Code, Dns6Protocol.Code, DnsaddrProtocol.Code:
|
||||
matches = true
|
||||
}
|
||||
return !matches
|
||||
})
|
||||
return matches
|
||||
}
|
||||
|
||||
func Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
|
||||
return DefaultResolver.Resolve(ctx, maddr)
|
||||
}
|
||||
|
||||
// counts the number of components in the multiaddr
|
||||
func addrLen(maddr ma.Multiaddr) int {
|
||||
length := 0
|
||||
ma.ForEach(maddr, func(_ ma.Component) bool {
|
||||
length++
|
||||
return true
|
||||
})
|
||||
return length
|
||||
}
|
||||
|
||||
// trims `offset` components from the beginning of the multiaddr.
|
||||
func offset(maddr ma.Multiaddr, offset int) ma.Multiaddr {
|
||||
_, after := ma.SplitFunc(maddr, func(c ma.Component) bool {
|
||||
if offset == 0 {
|
||||
return true
|
||||
}
|
||||
offset--
|
||||
return false
|
||||
})
|
||||
return after
|
||||
}
|
||||
|
||||
// takes the cross product of two sets of multiaddrs
|
||||
//
|
||||
// assumes `a` is non-empty.
|
||||
func cross(a, b []ma.Multiaddr) []ma.Multiaddr {
|
||||
res := make([]ma.Multiaddr, 0, len(a)*len(b))
|
||||
for _, x := range a {
|
||||
for _, y := range b {
|
||||
res = append(res, x.Encapsulate(y))
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
31
vendor/github.com/multiformats/go-multiaddr-fmt/.travis.yml
generated
vendored
Normal file
31
vendor/github.com/multiformats/go-multiaddr-fmt/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
os:
|
||||
- linux
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12.x
|
||||
|
||||
env:
|
||||
global:
|
||||
- GOTFLAGS="-race"
|
||||
- IPFS_REUSEPORT=false
|
||||
matrix:
|
||||
- BUILD_DEPTYPE=gomod
|
||||
|
||||
|
||||
# disable travis install
|
||||
install:
|
||||
- true
|
||||
|
||||
script:
|
||||
- bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh)
|
||||
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/pkg/mod
|
||||
- /home/travis/.cache/go-build
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
21
vendor/github.com/multiformats/go-multiaddr-fmt/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multiaddr-fmt/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Jeromy Johnson
|
||||
|
||||
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.
|
||||
34
vendor/github.com/multiformats/go-multiaddr-fmt/README.md
generated
vendored
Normal file
34
vendor/github.com/multiformats/go-multiaddr-fmt/README.md
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# multiaddr format
|
||||
A validation checker for multiaddrs. Some basic validators for common address
|
||||
types are provided, but creating your own combinations is easy.
|
||||
|
||||
Usage:
|
||||
```go
|
||||
a, _ := ma.NewMultiaddr("/ip4/5.2.67.3/tcp/1708")
|
||||
TCP.Matches(a) // returns true
|
||||
```
|
||||
|
||||
Making your own validators is easy, for example, the `Reliable` multiaddr is
|
||||
defined as follows:
|
||||
|
||||
```go
|
||||
// Define IP as either ipv4 or ipv6
|
||||
var IP = Or(Base(ma.P_IP4), Base(ma.P_IP6))
|
||||
|
||||
// Define TCP as 'tcp' on top of either ipv4 or ipv6
|
||||
var TCP = And(IP, Base(ma.P_TCP))
|
||||
|
||||
// Define UDP as 'udp' on top of either ipv4 or ipv6
|
||||
var UDP = And(IP, Base(ma.P_UDP))
|
||||
|
||||
// Define UTP as 'utp' on top of udp (on top of ipv4 or ipv6)
|
||||
var UTP = And(UDP, Base(ma.P_UTP))
|
||||
|
||||
// Now define a Reliable transport as either tcp or utp
|
||||
var Reliable = Or(TCP, UTP)
|
||||
|
||||
// From here, we can easily define multiaddrs for protocols that can run on top
|
||||
// of any 'reliable' transport (such as ipfs)
|
||||
```
|
||||
|
||||
NOTE: the above patterns are already implemented in package
|
||||
177
vendor/github.com/multiformats/go-multiaddr-fmt/patterns.go
generated
vendored
Normal file
177
vendor/github.com/multiformats/go-multiaddr-fmt/patterns.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
package mafmt
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// Define a dns4 format multiaddr
|
||||
var DNS4 = Base(ma.P_DNS4)
|
||||
|
||||
// Define a dns6 format multiaddr
|
||||
var DNS6 = Base(ma.P_DNS6)
|
||||
|
||||
// Define a dnsaddr, dns, dns4 or dns6 format multiaddr
|
||||
var DNS = Or(
|
||||
Base(ma.P_DNS),
|
||||
Base(ma.P_DNSADDR),
|
||||
DNS4,
|
||||
DNS6,
|
||||
)
|
||||
|
||||
// Define IP as either ipv4 or ipv6
|
||||
var IP = Or(Base(ma.P_IP4), Base(ma.P_IP6))
|
||||
|
||||
// Define TCP as 'tcp' on top of either ipv4 or ipv6, or dns equivalents.
|
||||
var TCP = Or(
|
||||
And(DNS, Base(ma.P_TCP)),
|
||||
And(IP, Base(ma.P_TCP)),
|
||||
)
|
||||
|
||||
// Define UDP as 'udp' on top of either ipv4 or ipv6, or dns equivalents.
|
||||
var UDP = Or(
|
||||
And(DNS, Base(ma.P_UDP)),
|
||||
And(IP, Base(ma.P_UDP)),
|
||||
)
|
||||
|
||||
// Define UTP as 'utp' on top of udp (on top of ipv4 or ipv6).
|
||||
var UTP = And(UDP, Base(ma.P_UTP))
|
||||
|
||||
// Define QUIC as 'quic' on top of udp (on top of ipv4 or ipv6)
|
||||
var QUIC = And(UDP, Base(ma.P_QUIC))
|
||||
|
||||
// Define unreliable transport as udp
|
||||
var Unreliable = Or(UDP)
|
||||
|
||||
// Now define a Reliable transport as either tcp or utp or quic
|
||||
var Reliable = Or(TCP, UTP, QUIC)
|
||||
|
||||
// P2P can run over any reliable underlying transport protocol
|
||||
var P2P = And(Reliable, Base(ma.P_P2P))
|
||||
|
||||
// IPFS can run over any reliable underlying transport protocol
|
||||
//
|
||||
// Deprecated: use P2P
|
||||
var IPFS = P2P
|
||||
|
||||
// Define http over TCP or DNS or http over DNS format multiaddr
|
||||
var HTTP = Or(
|
||||
And(TCP, Base(ma.P_HTTP)),
|
||||
And(IP, Base(ma.P_HTTP)),
|
||||
And(DNS, Base(ma.P_HTTP)),
|
||||
)
|
||||
|
||||
// Define https over TCP or DNS or https over DNS format multiaddr
|
||||
var HTTPS = Or(
|
||||
And(TCP, Base(ma.P_HTTPS)),
|
||||
And(IP, Base(ma.P_HTTPS)),
|
||||
And(DNS, Base(ma.P_HTTPS)),
|
||||
)
|
||||
|
||||
// Define p2p-webrtc-direct over HTTP or p2p-webrtc-direct over HTTPS format multiaddr
|
||||
var WebRTCDirect = Or(
|
||||
And(HTTP, Base(ma.P_P2P_WEBRTC_DIRECT)),
|
||||
And(HTTPS, Base(ma.P_P2P_WEBRTC_DIRECT)))
|
||||
|
||||
const (
|
||||
or = iota
|
||||
and = iota
|
||||
)
|
||||
|
||||
func And(ps ...Pattern) Pattern {
|
||||
return &pattern{
|
||||
Op: and,
|
||||
Args: ps,
|
||||
}
|
||||
}
|
||||
|
||||
func Or(ps ...Pattern) Pattern {
|
||||
return &pattern{
|
||||
Op: or,
|
||||
Args: ps,
|
||||
}
|
||||
}
|
||||
|
||||
type Pattern interface {
|
||||
Matches(ma.Multiaddr) bool
|
||||
partialMatch([]ma.Protocol) (bool, []ma.Protocol)
|
||||
String() string
|
||||
}
|
||||
|
||||
type pattern struct {
|
||||
Args []Pattern
|
||||
Op int
|
||||
}
|
||||
|
||||
func (ptrn *pattern) Matches(a ma.Multiaddr) bool {
|
||||
ok, rem := ptrn.partialMatch(a.Protocols())
|
||||
return ok && len(rem) == 0
|
||||
}
|
||||
|
||||
func (ptrn *pattern) partialMatch(pcs []ma.Protocol) (bool, []ma.Protocol) {
|
||||
switch ptrn.Op {
|
||||
case or:
|
||||
for _, a := range ptrn.Args {
|
||||
ok, rem := a.partialMatch(pcs)
|
||||
if ok {
|
||||
return true, rem
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
case and:
|
||||
if len(pcs) < len(ptrn.Args) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(ptrn.Args); i++ {
|
||||
ok, rem := ptrn.Args[i].partialMatch(pcs)
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
pcs = rem
|
||||
}
|
||||
|
||||
return true, pcs
|
||||
default:
|
||||
panic("unrecognized pattern operand")
|
||||
}
|
||||
}
|
||||
|
||||
func (ptrn *pattern) String() string {
|
||||
var sub []string
|
||||
for _, a := range ptrn.Args {
|
||||
sub = append(sub, a.String())
|
||||
}
|
||||
|
||||
switch ptrn.Op {
|
||||
case and:
|
||||
return strings.Join(sub, "/")
|
||||
case or:
|
||||
return "{" + strings.Join(sub, "|") + "}"
|
||||
default:
|
||||
panic("unrecognized pattern op!")
|
||||
}
|
||||
}
|
||||
|
||||
type Base int
|
||||
|
||||
func (p Base) Matches(a ma.Multiaddr) bool {
|
||||
pcs := a.Protocols()
|
||||
return pcs[0].Code == int(p) && len(pcs) == 1
|
||||
}
|
||||
|
||||
func (p Base) partialMatch(pcs []ma.Protocol) (bool, []ma.Protocol) {
|
||||
if len(pcs) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
if pcs[0].Code == int(p) {
|
||||
return true, pcs[1:]
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (p Base) String() string {
|
||||
return ma.ProtocolWithCode(int(p)).Name
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-multiaddr/.gitignore
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multiaddr/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.vscode/
|
||||
multiaddr/multiaddr
|
||||
tmp/
|
||||
21
vendor/github.com/multiformats/go-multiaddr/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multiaddr/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Juan Batiz-Benet
|
||||
|
||||
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.
|
||||
117
vendor/github.com/multiformats/go-multiaddr/README.md
generated
vendored
Normal file
117
vendor/github.com/multiformats/go-multiaddr/README.md
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
# go-multiaddr
|
||||
|
||||
[](http://ipn.io)
|
||||
[](https://github.com/multiformats/multiformats)
|
||||
[](https://webchat.freenode.net/?channels=%23ipfs)
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
[](https://godoc.org/github.com/multiformats/go-multiaddr)
|
||||
[](https://travis-ci.org/multiformats/go-multiaddr)
|
||||
[](https://codecov.io/github/multiformats/go-multiaddr?branch=master)
|
||||
|
||||
> [multiaddr](https://github.com/multiformats/multiaddr) implementation in go
|
||||
|
||||
Multiaddr is a standard way to represent addresses that:
|
||||
|
||||
- Support any standard network protocols.
|
||||
- Self-describe (include protocols).
|
||||
- Have a binary packed format.
|
||||
- Have a nice string representation.
|
||||
- Encapsulate well.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Example](#example)
|
||||
- [Simple](#simple)
|
||||
- [Protocols](#protocols)
|
||||
- [En/decapsulate](#endecapsulate)
|
||||
- [Tunneling](#tunneling)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
go get github.com/multiformats/go-multiaddr
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Example
|
||||
|
||||
#### Simple
|
||||
|
||||
```go
|
||||
import ma "github.com/multiformats/go-multiaddr"
|
||||
|
||||
// construct from a string (err signals parse failure)
|
||||
m1, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
||||
|
||||
// construct from bytes (err signals parse failure)
|
||||
m2, err := ma.NewMultiaddrBytes(m1.Bytes())
|
||||
|
||||
// true
|
||||
strings.Equal(m1.String(), "/ip4/127.0.0.1/udp/1234")
|
||||
strings.Equal(m1.String(), m2.String())
|
||||
bytes.Equal(m1.Bytes(), m2.Bytes())
|
||||
m1.Equal(m2)
|
||||
m2.Equal(m1)
|
||||
```
|
||||
|
||||
#### Protocols
|
||||
|
||||
```go
|
||||
// get the multiaddr protocol description objects
|
||||
m1.Protocols()
|
||||
// []Protocol{
|
||||
// Protocol{ Code: 4, Name: 'ip4', Size: 32},
|
||||
// Protocol{ Code: 17, Name: 'udp', Size: 16},
|
||||
// }
|
||||
```
|
||||
|
||||
#### En/decapsulate
|
||||
|
||||
```go
|
||||
import ma "github.com/multiformats/go-multiaddr"
|
||||
|
||||
m, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
||||
// <Multiaddr /ip4/127.0.0.1/udp/1234>
|
||||
|
||||
sctpMA, err := ma.NewMultiaddr("/sctp/5678")
|
||||
|
||||
m.Encapsulate(sctpMA)
|
||||
// <Multiaddr /ip4/127.0.0.1/udp/1234/sctp/5678>
|
||||
|
||||
udpMA, err := ma.NewMultiaddr("/udp/1234")
|
||||
|
||||
m.Decapsulate(udpMA) // up to + inc last occurrence of subaddr
|
||||
// <Multiaddr /ip4/127.0.0.1>
|
||||
```
|
||||
|
||||
#### Tunneling
|
||||
|
||||
Multiaddr allows expressing tunnels very nicely.
|
||||
|
||||
```js
|
||||
printer, _ := ma.NewMultiaddr("/ip4/192.168.0.13/tcp/80")
|
||||
proxy, _ := ma.NewMultiaddr("/ip4/10.20.30.40/tcp/443")
|
||||
printerOverProxy := proxy.Encapsulate(printer)
|
||||
// /ip4/10.20.30.40/tcp/443/ip4/192.168.0.13/tcp/80
|
||||
|
||||
proxyAgain := printerOverProxy.Decapsulate(printer)
|
||||
// /ip4/10.20.30.40/tcp/443
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multiaddr/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © 2014 Juan Batiz-Benet
|
||||
178
vendor/github.com/multiformats/go-multiaddr/codec.go
generated
vendored
Normal file
178
vendor/github.com/multiformats/go-multiaddr/codec.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
func stringToBytes(s string) ([]byte, error) {
|
||||
// consume trailing slashes
|
||||
s = strings.TrimRight(s, "/")
|
||||
|
||||
var b bytes.Buffer
|
||||
sp := strings.Split(s, "/")
|
||||
|
||||
if sp[0] != "" {
|
||||
return nil, fmt.Errorf("failed to parse multiaddr %q: must begin with /", s)
|
||||
}
|
||||
|
||||
// consume first empty elem
|
||||
sp = sp[1:]
|
||||
|
||||
if len(sp) == 0 {
|
||||
return nil, fmt.Errorf("failed to parse multiaddr %q: empty multiaddr", s)
|
||||
}
|
||||
|
||||
for len(sp) > 0 {
|
||||
name := sp[0]
|
||||
p := ProtocolWithName(name)
|
||||
if p.Code == 0 {
|
||||
return nil, fmt.Errorf("failed to parse multiaddr %q: unknown protocol %s", s, sp[0])
|
||||
}
|
||||
_, _ = b.Write(p.VCode)
|
||||
sp = sp[1:]
|
||||
|
||||
if p.Size == 0 { // no length.
|
||||
continue
|
||||
}
|
||||
|
||||
if len(sp) < 1 {
|
||||
return nil, fmt.Errorf("failed to parse multiaddr %q: unexpected end of multiaddr", s)
|
||||
}
|
||||
|
||||
if p.Path {
|
||||
// it's a path protocol (terminal).
|
||||
// consume the rest of the address as the next component.
|
||||
sp = []string{"/" + strings.Join(sp, "/")}
|
||||
}
|
||||
|
||||
a, err := p.Transcoder.StringToBytes(sp[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse multiaddr %q: invalid value %q for protocol %s: %s", s, sp[0], p.Name, err)
|
||||
}
|
||||
if p.Size < 0 { // varint size.
|
||||
_, _ = b.Write(varint.ToUvarint(uint64(len(a))))
|
||||
}
|
||||
b.Write(a)
|
||||
sp = sp[1:]
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
func validateBytes(b []byte) (err error) {
|
||||
if len(b) == 0 {
|
||||
return fmt.Errorf("empty multiaddr")
|
||||
}
|
||||
for len(b) > 0 {
|
||||
code, n, err := ReadVarintCode(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b = b[n:]
|
||||
p := ProtocolWithCode(code)
|
||||
if p.Code == 0 {
|
||||
return fmt.Errorf("no protocol with code %d", code)
|
||||
}
|
||||
|
||||
if p.Size == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
n, size, err := sizeForAddr(p, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b = b[n:]
|
||||
|
||||
if len(b) < size || size < 0 {
|
||||
return fmt.Errorf("invalid value for size %d", len(b))
|
||||
}
|
||||
|
||||
err = p.Transcoder.ValidateBytes(b[:size])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b = b[size:]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readComponent(b []byte) (int, Component, error) {
|
||||
var offset int
|
||||
code, n, err := ReadVarintCode(b)
|
||||
if err != nil {
|
||||
return 0, Component{}, err
|
||||
}
|
||||
offset += n
|
||||
|
||||
p := ProtocolWithCode(code)
|
||||
if p.Code == 0 {
|
||||
return 0, Component{}, fmt.Errorf("no protocol with code %d", code)
|
||||
}
|
||||
|
||||
if p.Size == 0 {
|
||||
return offset, Component{
|
||||
bytes: b[:offset],
|
||||
offset: offset,
|
||||
protocol: p,
|
||||
}, nil
|
||||
}
|
||||
|
||||
n, size, err := sizeForAddr(p, b[offset:])
|
||||
if err != nil {
|
||||
return 0, Component{}, err
|
||||
}
|
||||
|
||||
offset += n
|
||||
|
||||
if len(b[offset:]) < size || size < 0 {
|
||||
return 0, Component{}, fmt.Errorf("invalid value for size %d", len(b[offset:]))
|
||||
}
|
||||
|
||||
return offset + size, Component{
|
||||
bytes: b[:offset+size],
|
||||
protocol: p,
|
||||
offset: offset,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func bytesToString(b []byte) (ret string, err error) {
|
||||
if len(b) == 0 {
|
||||
return "", fmt.Errorf("empty multiaddr")
|
||||
}
|
||||
var buf strings.Builder
|
||||
|
||||
for len(b) > 0 {
|
||||
n, c, err := readComponent(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b = b[n:]
|
||||
c.writeTo(&buf)
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func sizeForAddr(p Protocol, b []byte) (skip, size int, err error) {
|
||||
switch {
|
||||
case p.Size > 0:
|
||||
return 0, (p.Size / 8), nil
|
||||
case p.Size == 0:
|
||||
return 0, 0, nil
|
||||
default:
|
||||
size, n, err := ReadVarintCode(b)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return n, size, nil
|
||||
}
|
||||
}
|
||||
2
vendor/github.com/multiformats/go-multiaddr/codecov.yml
generated
vendored
Normal file
2
vendor/github.com/multiformats/go-multiaddr/codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
ignore:
|
||||
- "multiaddr"
|
||||
183
vendor/github.com/multiformats/go-multiaddr/component.go
generated
vendored
Normal file
183
vendor/github.com/multiformats/go-multiaddr/component.go
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
// Component is a single multiaddr Component.
|
||||
type Component struct {
|
||||
bytes []byte
|
||||
protocol Protocol
|
||||
offset int
|
||||
}
|
||||
|
||||
func (c *Component) Bytes() []byte {
|
||||
return c.bytes
|
||||
}
|
||||
|
||||
func (c *Component) MarshalBinary() ([]byte, error) {
|
||||
return c.Bytes(), nil
|
||||
}
|
||||
|
||||
func (c *Component) UnmarshalBinary(data []byte) error {
|
||||
_, comp, err := readComponent(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*c = comp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Component) MarshalText() ([]byte, error) {
|
||||
return []byte(c.String()), nil
|
||||
}
|
||||
|
||||
func (c *Component) UnmarshalText(data []byte) error {
|
||||
bytes, err := stringToBytes(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, comp, err := readComponent(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*c = comp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Component) MarshalJSON() ([]byte, error) {
|
||||
txt, err := c.MarshalText()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(string(txt))
|
||||
}
|
||||
|
||||
func (m *Component) UnmarshalJSON(data []byte) error {
|
||||
var v string
|
||||
if err := json.Unmarshal(data, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return m.UnmarshalText([]byte(v))
|
||||
}
|
||||
|
||||
func (c *Component) Equal(o Multiaddr) bool {
|
||||
return bytes.Equal(c.bytes, o.Bytes())
|
||||
}
|
||||
|
||||
func (c *Component) Protocols() []Protocol {
|
||||
return []Protocol{c.protocol}
|
||||
}
|
||||
|
||||
func (c *Component) Decapsulate(o Multiaddr) Multiaddr {
|
||||
if c.Equal(o) {
|
||||
return nil
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Component) Encapsulate(o Multiaddr) Multiaddr {
|
||||
m := &multiaddr{bytes: c.bytes}
|
||||
return m.Encapsulate(o)
|
||||
}
|
||||
|
||||
func (c *Component) ValueForProtocol(code int) (string, error) {
|
||||
if c.protocol.Code != code {
|
||||
return "", ErrProtocolNotFound
|
||||
}
|
||||
return c.Value(), nil
|
||||
}
|
||||
|
||||
func (c *Component) Protocol() Protocol {
|
||||
return c.protocol
|
||||
}
|
||||
|
||||
func (c *Component) RawValue() []byte {
|
||||
return c.bytes[c.offset:]
|
||||
}
|
||||
|
||||
func (c *Component) Value() string {
|
||||
if c.protocol.Transcoder == nil {
|
||||
return ""
|
||||
}
|
||||
value, err := c.protocol.Transcoder.BytesToString(c.bytes[c.offset:])
|
||||
if err != nil {
|
||||
// This Component must have been checked.
|
||||
panic(err)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (c *Component) String() string {
|
||||
var b strings.Builder
|
||||
c.writeTo(&b)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// writeTo is an efficient, private function for string-formatting a multiaddr.
|
||||
// Trust me, we tend to allocate a lot when doing this.
|
||||
func (c *Component) writeTo(b *strings.Builder) {
|
||||
b.WriteByte('/')
|
||||
b.WriteString(c.protocol.Name)
|
||||
value := c.Value()
|
||||
if len(value) == 0 {
|
||||
return
|
||||
}
|
||||
if !(c.protocol.Path && value[0] == '/') {
|
||||
b.WriteByte('/')
|
||||
}
|
||||
b.WriteString(value)
|
||||
}
|
||||
|
||||
// NewComponent constructs a new multiaddr component
|
||||
func NewComponent(protocol, value string) (*Component, error) {
|
||||
p := ProtocolWithName(protocol)
|
||||
if p.Code == 0 {
|
||||
return nil, fmt.Errorf("unsupported protocol: %s", protocol)
|
||||
}
|
||||
if p.Transcoder != nil {
|
||||
bts, err := p.Transcoder.StringToBytes(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newComponent(p, bts), nil
|
||||
} else if value != "" {
|
||||
return nil, fmt.Errorf("protocol %s doesn't take a value", p.Name)
|
||||
}
|
||||
return newComponent(p, nil), nil
|
||||
// TODO: handle path /?
|
||||
}
|
||||
|
||||
func newComponent(protocol Protocol, bvalue []byte) *Component {
|
||||
size := len(bvalue)
|
||||
size += len(protocol.VCode)
|
||||
if protocol.Size < 0 {
|
||||
size += varint.UvarintSize(uint64(len(bvalue)))
|
||||
}
|
||||
maddr := make([]byte, size)
|
||||
var offset int
|
||||
offset += copy(maddr[offset:], protocol.VCode)
|
||||
if protocol.Size < 0 {
|
||||
offset += binary.PutUvarint(maddr[offset:], uint64(len(bvalue)))
|
||||
}
|
||||
copy(maddr[offset:], bvalue)
|
||||
|
||||
// For debugging
|
||||
if len(maddr) != offset+len(bvalue) {
|
||||
panic("incorrect length")
|
||||
}
|
||||
|
||||
return &Component{
|
||||
bytes: maddr,
|
||||
protocol: protocol,
|
||||
offset: offset,
|
||||
}
|
||||
}
|
||||
35
vendor/github.com/multiformats/go-multiaddr/doc.go
generated
vendored
Normal file
35
vendor/github.com/multiformats/go-multiaddr/doc.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Package multiaddr provides an implementation of the Multiaddr network
|
||||
address format. Multiaddr emphasizes explicitness, self-description, and
|
||||
portability. It allows applications to treat addresses as opaque tokens,
|
||||
and to avoid making assumptions about the address representation (e.g. length).
|
||||
Learn more at https://github.com/multiformats/multiaddr
|
||||
|
||||
Basic Use:
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// construct from a string (err signals parse failure)
|
||||
m1, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
||||
|
||||
// construct from bytes (err signals parse failure)
|
||||
m2, err := ma.NewMultiaddrBytes(m1.Bytes())
|
||||
|
||||
// true
|
||||
strings.Equal(m1.String(), "/ip4/127.0.0.1/udp/1234")
|
||||
strings.Equal(m1.String(), m2.String())
|
||||
bytes.Equal(m1.Bytes(), m2.Bytes())
|
||||
m1.Equal(m2)
|
||||
m2.Equal(m1)
|
||||
|
||||
// tunneling (en/decap)
|
||||
printer, _ := ma.NewMultiaddr("/ip4/192.168.0.13/tcp/80")
|
||||
proxy, _ := ma.NewMultiaddr("/ip4/10.20.30.40/tcp/443")
|
||||
printerOverProxy := proxy.Encapsulate(printer)
|
||||
proxyAgain := printerOverProxy.Decapsulate(printer)
|
||||
*/
|
||||
package multiaddr
|
||||
145
vendor/github.com/multiformats/go-multiaddr/filter.go
generated
vendored
Normal file
145
vendor/github.com/multiformats/go-multiaddr/filter.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Action is an enum modelling all possible filter actions.
|
||||
type Action int32
|
||||
|
||||
const (
|
||||
ActionNone Action = iota // zero value.
|
||||
ActionAccept
|
||||
ActionDeny
|
||||
)
|
||||
|
||||
type filterEntry struct {
|
||||
f net.IPNet
|
||||
action Action
|
||||
}
|
||||
|
||||
// Filters is a structure representing a collection of accept/deny
|
||||
// net.IPNet filters, together with the DefaultAction flag, which
|
||||
// represents the default filter policy.
|
||||
//
|
||||
// Note that the last policy added to the Filters is authoritative.
|
||||
type Filters struct {
|
||||
DefaultAction Action
|
||||
|
||||
mu sync.RWMutex
|
||||
filters []*filterEntry
|
||||
}
|
||||
|
||||
// NewFilters constructs and returns a new set of net.IPNet filters.
|
||||
// By default, the new filter accepts all addresses.
|
||||
func NewFilters() *Filters {
|
||||
return &Filters{
|
||||
DefaultAction: ActionAccept,
|
||||
filters: make([]*filterEntry, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *Filters) find(ipnet net.IPNet) (int, *filterEntry) {
|
||||
s := ipnet.String()
|
||||
for idx, ft := range fs.filters {
|
||||
if ft.f.String() == s {
|
||||
return idx, ft
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
// AddFilter adds a rule to the Filters set, enforcing the desired action for
|
||||
// the provided IPNet mask.
|
||||
func (fs *Filters) AddFilter(ipnet net.IPNet, action Action) {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
||||
if _, f := fs.find(ipnet); f != nil {
|
||||
f.action = action
|
||||
} else {
|
||||
fs.filters = append(fs.filters, &filterEntry{ipnet, action})
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveLiteral removes the first filter associated with the supplied IPNet,
|
||||
// returning whether something was removed or not. It makes no distinction
|
||||
// between whether the rule is an accept or a deny.
|
||||
func (fs *Filters) RemoveLiteral(ipnet net.IPNet) (removed bool) {
|
||||
fs.mu.Lock()
|
||||
defer fs.mu.Unlock()
|
||||
|
||||
if idx, _ := fs.find(ipnet); idx != -1 {
|
||||
fs.filters = append(fs.filters[:idx], fs.filters[idx+1:]...)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AddrBlocked parses a ma.Multiaddr and, if a valid netip is found, it applies the
|
||||
// Filter set rules, returning true if the given address should be denied, and false if
|
||||
// the given address is accepted.
|
||||
//
|
||||
// If a parsing error occurs, or no filter matches, the Filters'
|
||||
// default is returned.
|
||||
//
|
||||
// TODO: currently, the last filter to match wins always, but it shouldn't be that way.
|
||||
//
|
||||
// Instead, the highest-specific last filter should win; that way more specific filters
|
||||
// override more general ones.
|
||||
func (fs *Filters) AddrBlocked(a Multiaddr) (deny bool) {
|
||||
var (
|
||||
netip net.IP
|
||||
found bool
|
||||
)
|
||||
|
||||
ForEach(a, func(c Component) bool {
|
||||
switch c.Protocol().Code {
|
||||
case P_IP6ZONE:
|
||||
return true
|
||||
case P_IP6, P_IP4:
|
||||
found = true
|
||||
netip = net.IP(c.RawValue())
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
if !found {
|
||||
return fs.DefaultAction == ActionDeny
|
||||
}
|
||||
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
action := fs.DefaultAction
|
||||
for _, ft := range fs.filters {
|
||||
if ft.f.Contains(netip) {
|
||||
action = ft.action
|
||||
}
|
||||
}
|
||||
|
||||
return action == ActionDeny
|
||||
}
|
||||
|
||||
func (fs *Filters) ActionForFilter(ipnet net.IPNet) (action Action, ok bool) {
|
||||
if _, f := fs.find(ipnet); f != nil {
|
||||
return f.action, true
|
||||
}
|
||||
return ActionNone, false
|
||||
}
|
||||
|
||||
// FiltersForAction returns the filters associated with the indicated action.
|
||||
func (fs *Filters) FiltersForAction(action Action) (result []net.IPNet) {
|
||||
fs.mu.RLock()
|
||||
defer fs.mu.RUnlock()
|
||||
|
||||
for _, ff := range fs.filters {
|
||||
if ff.action == action {
|
||||
result = append(result, ff.f)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
63
vendor/github.com/multiformats/go-multiaddr/interface.go
generated
vendored
Normal file
63
vendor/github.com/multiformats/go-multiaddr/interface.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
/*
|
||||
Multiaddr is a cross-protocol, cross-platform format for representing
|
||||
internet addresses. It emphasizes explicitness and self-description.
|
||||
Learn more here: https://github.com/multiformats/multiaddr
|
||||
|
||||
Multiaddrs have both a binary and string representation.
|
||||
|
||||
import ma "github.com/multiformats/go-multiaddr"
|
||||
|
||||
addr, err := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/80")
|
||||
// err non-nil when parsing failed.
|
||||
*/
|
||||
type Multiaddr interface {
|
||||
json.Marshaler
|
||||
json.Unmarshaler
|
||||
encoding.TextMarshaler
|
||||
encoding.TextUnmarshaler
|
||||
encoding.BinaryMarshaler
|
||||
encoding.BinaryUnmarshaler
|
||||
|
||||
// Equal returns whether two Multiaddrs are exactly equal
|
||||
Equal(Multiaddr) bool
|
||||
|
||||
// Bytes returns the []byte representation of this Multiaddr
|
||||
//
|
||||
// This function may expose immutable, internal state. Do not modify.
|
||||
Bytes() []byte
|
||||
|
||||
// String returns the string representation of this Multiaddr
|
||||
// (may panic if internal state is corrupted)
|
||||
String() string
|
||||
|
||||
// Protocols returns the list of Protocols this Multiaddr includes
|
||||
// will panic if protocol code incorrect (and bytes accessed incorrectly)
|
||||
Protocols() []Protocol
|
||||
|
||||
// Encapsulate wraps this Multiaddr around another. For example:
|
||||
//
|
||||
// /ip4/1.2.3.4 encapsulate /tcp/80 = /ip4/1.2.3.4/tcp/80
|
||||
//
|
||||
Encapsulate(Multiaddr) Multiaddr
|
||||
|
||||
// Decapsulate removes a Multiaddr wrapping. For example:
|
||||
//
|
||||
// /ip4/1.2.3.4/tcp/80 decapsulate /tcp/80 = /ip4/1.2.3.4
|
||||
// /ip4/1.2.3.4/tcp/80 decapsulate /udp/80 = /ip4/1.2.3.4/tcp/80
|
||||
// /ip4/1.2.3.4/tcp/80 decapsulate /ip4/1.2.3.4 = nil
|
||||
//
|
||||
Decapsulate(Multiaddr) Multiaddr
|
||||
|
||||
// ValueForProtocol returns the value (if any) following the specified protocol
|
||||
//
|
||||
// Note: protocols can appear multiple times in a single multiaddr.
|
||||
// Consider using `ForEach` to walk over the addr manually.
|
||||
ValueForProtocol(code int) (string, error)
|
||||
}
|
||||
235
vendor/github.com/multiformats/go-multiaddr/multiaddr.go
generated
vendored
Normal file
235
vendor/github.com/multiformats/go-multiaddr/multiaddr.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// multiaddr is the data structure representing a Multiaddr
|
||||
type multiaddr struct {
|
||||
bytes []byte
|
||||
}
|
||||
|
||||
// NewMultiaddr parses and validates an input string, returning a *Multiaddr
|
||||
func NewMultiaddr(s string) (a Multiaddr, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("Panic in NewMultiaddr on input %q: %s", s, e)
|
||||
err = fmt.Errorf("%v", e)
|
||||
}
|
||||
}()
|
||||
b, err := stringToBytes(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &multiaddr{bytes: b}, nil
|
||||
}
|
||||
|
||||
// NewMultiaddrBytes initializes a Multiaddr from a byte representation.
|
||||
// It validates it as an input string.
|
||||
func NewMultiaddrBytes(b []byte) (a Multiaddr, err error) {
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
log.Printf("Panic in NewMultiaddrBytes on input %q: %s", b, e)
|
||||
err = fmt.Errorf("%v", e)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := validateBytes(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &multiaddr{bytes: b}, nil
|
||||
}
|
||||
|
||||
// Equal tests whether two multiaddrs are equal
|
||||
func (m *multiaddr) Equal(m2 Multiaddr) bool {
|
||||
return bytes.Equal(m.bytes, m2.Bytes())
|
||||
}
|
||||
|
||||
// Bytes returns the []byte representation of this Multiaddr
|
||||
//
|
||||
// Do not modify the returned buffer, it may be shared.
|
||||
func (m *multiaddr) Bytes() []byte {
|
||||
return m.bytes
|
||||
}
|
||||
|
||||
// String returns the string representation of a Multiaddr
|
||||
func (m *multiaddr) String() string {
|
||||
s, err := bytesToString(m.bytes)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("multiaddr failed to convert back to string. corrupted? %s", err))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (m *multiaddr) MarshalBinary() ([]byte, error) {
|
||||
return m.Bytes(), nil
|
||||
}
|
||||
|
||||
func (m *multiaddr) UnmarshalBinary(data []byte) error {
|
||||
new, err := NewMultiaddrBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = *(new.(*multiaddr))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *multiaddr) MarshalText() ([]byte, error) {
|
||||
return []byte(m.String()), nil
|
||||
}
|
||||
|
||||
func (m *multiaddr) UnmarshalText(data []byte) error {
|
||||
new, err := NewMultiaddr(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = *(new.(*multiaddr))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *multiaddr) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(m.String())
|
||||
}
|
||||
|
||||
func (m *multiaddr) UnmarshalJSON(data []byte) error {
|
||||
var v string
|
||||
if err := json.Unmarshal(data, &v); err != nil {
|
||||
return err
|
||||
}
|
||||
new, err := NewMultiaddr(v)
|
||||
*m = *(new.(*multiaddr))
|
||||
return err
|
||||
}
|
||||
|
||||
// Protocols returns the list of protocols this Multiaddr has.
|
||||
// will panic in case we access bytes incorrectly.
|
||||
func (m *multiaddr) Protocols() []Protocol {
|
||||
ps := make([]Protocol, 0, 8)
|
||||
b := m.bytes
|
||||
for len(b) > 0 {
|
||||
code, n, err := ReadVarintCode(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
p := ProtocolWithCode(code)
|
||||
if p.Code == 0 {
|
||||
// this is a panic (and not returning err) because this should've been
|
||||
// caught on constructing the Multiaddr
|
||||
panic(fmt.Errorf("no protocol with code %d", b[0]))
|
||||
}
|
||||
ps = append(ps, p)
|
||||
b = b[n:]
|
||||
|
||||
n, size, err := sizeForAddr(p, b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
b = b[n+size:]
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
// Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr
|
||||
func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
|
||||
mb := m.bytes
|
||||
ob := o.Bytes()
|
||||
|
||||
b := make([]byte, len(mb)+len(ob))
|
||||
copy(b, mb)
|
||||
copy(b[len(mb):], ob)
|
||||
return &multiaddr{bytes: b}
|
||||
}
|
||||
|
||||
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
|
||||
func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
||||
s1 := m.String()
|
||||
s2 := o.String()
|
||||
i := strings.LastIndex(s1, s2)
|
||||
if i < 0 {
|
||||
// if multiaddr not contained, returns a copy.
|
||||
cpy := make([]byte, len(m.bytes))
|
||||
copy(cpy, m.bytes)
|
||||
return &multiaddr{bytes: cpy}
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ma, err := NewMultiaddr(s1[:i])
|
||||
if err != nil {
|
||||
panic("Multiaddr.Decapsulate incorrect byte boundaries.")
|
||||
}
|
||||
return ma
|
||||
}
|
||||
|
||||
var ErrProtocolNotFound = fmt.Errorf("protocol not found in multiaddr")
|
||||
|
||||
func (m *multiaddr) ValueForProtocol(code int) (value string, err error) {
|
||||
err = ErrProtocolNotFound
|
||||
ForEach(m, func(c Component) bool {
|
||||
if c.Protocol().Code == code {
|
||||
value = c.Value()
|
||||
err = nil
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// FilterAddrs is a filter that removes certain addresses, according to the given filters.
|
||||
// If all filters return true, the address is kept.
|
||||
func FilterAddrs(a []Multiaddr, filters ...func(Multiaddr) bool) []Multiaddr {
|
||||
b := make([]Multiaddr, 0, len(a))
|
||||
addrloop:
|
||||
for _, addr := range a {
|
||||
for _, filter := range filters {
|
||||
if !filter(addr) {
|
||||
continue addrloop
|
||||
}
|
||||
}
|
||||
b = append(b, addr)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Contains reports whether addr is contained in addrs.
|
||||
func Contains(addrs []Multiaddr, addr Multiaddr) bool {
|
||||
for _, a := range addrs {
|
||||
if addr.Equal(a) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Unique deduplicates addresses in place, leave only unique addresses.
|
||||
// It doesn't allocate.
|
||||
func Unique(addrs []Multiaddr) []Multiaddr {
|
||||
if len(addrs) == 0 {
|
||||
return addrs
|
||||
}
|
||||
// Use the new slices package here, as the sort function doesn't allocate (sort.Slice does).
|
||||
slices.SortFunc(addrs, func(a, b Multiaddr) int { return bytes.Compare(a.Bytes(), b.Bytes()) })
|
||||
idx := 1
|
||||
for i := 1; i < len(addrs); i++ {
|
||||
if !addrs[i-1].Equal(addrs[i]) {
|
||||
addrs[idx] = addrs[i]
|
||||
idx++
|
||||
}
|
||||
}
|
||||
for i := idx; i < len(addrs); i++ {
|
||||
addrs[i] = nil
|
||||
}
|
||||
return addrs[:idx]
|
||||
}
|
||||
358
vendor/github.com/multiformats/go-multiaddr/net/convert.go
generated
vendored
Normal file
358
vendor/github.com/multiformats/go-multiaddr/net/convert.go
generated
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
package manet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
var errIncorrectNetAddr = fmt.Errorf("incorrect network addr conversion")
|
||||
var errNotIP = fmt.Errorf("multiaddr does not start with an IP address")
|
||||
|
||||
// FromNetAddr converts a net.Addr type to a Multiaddr.
|
||||
func FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
return defaultCodecs.FromNetAddr(a)
|
||||
}
|
||||
|
||||
// FromNetAddr converts a net.Addr to Multiaddress.
|
||||
func (cm *CodecMap) FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
if a == nil {
|
||||
return nil, fmt.Errorf("nil multiaddr")
|
||||
}
|
||||
p, err := cm.getAddrParser(a.Network())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p(a)
|
||||
}
|
||||
|
||||
// ToNetAddr converts a Multiaddr to a net.Addr
|
||||
// Must be ThinWaist. acceptable protocol stacks are:
|
||||
// /ip{4,6}/{tcp, udp}
|
||||
func ToNetAddr(maddr ma.Multiaddr) (net.Addr, error) {
|
||||
return defaultCodecs.ToNetAddr(maddr)
|
||||
}
|
||||
|
||||
// ToNetAddr converts a Multiaddress to a standard net.Addr.
|
||||
func (cm *CodecMap) ToNetAddr(maddr ma.Multiaddr) (net.Addr, error) {
|
||||
protos := maddr.Protocols()
|
||||
final := protos[len(protos)-1]
|
||||
|
||||
p, err := cm.getMaddrParser(final.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p(maddr)
|
||||
}
|
||||
|
||||
// MultiaddrToIPNet converts a multiaddr to an IPNet. Useful for seeing if another IP address is contained within this multiaddr network+mask
|
||||
func MultiaddrToIPNet(m ma.Multiaddr) (*net.IPNet, error) {
|
||||
var ipString string
|
||||
var mask string
|
||||
|
||||
ma.ForEach(m, func(c ma.Component) bool {
|
||||
if c.Protocol().Code == ma.P_IP4 || c.Protocol().Code == ma.P_IP6 {
|
||||
ipString = c.Value()
|
||||
}
|
||||
if c.Protocol().Code == ma.P_IPCIDR {
|
||||
mask = c.Value()
|
||||
}
|
||||
return ipString == "" || mask == ""
|
||||
})
|
||||
|
||||
if ipString == "" {
|
||||
return nil, errors.New("no ip protocol found")
|
||||
}
|
||||
|
||||
if mask == "" {
|
||||
return nil, errors.New("no mask found")
|
||||
}
|
||||
|
||||
_, ipnet, err := net.ParseCIDR(ipString + "/" + string(mask))
|
||||
return ipnet, err
|
||||
}
|
||||
|
||||
func parseBasicNetMaddr(maddr ma.Multiaddr) (net.Addr, error) {
|
||||
network, host, err := DialArgs(maddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch network {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
return net.ResolveTCPAddr(network, host)
|
||||
case "udp", "udp4", "udp6":
|
||||
return net.ResolveUDPAddr(network, host)
|
||||
case "ip", "ip4", "ip6":
|
||||
return net.ResolveIPAddr(network, host)
|
||||
case "unix":
|
||||
return net.ResolveUnixAddr(network, host)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("network not supported: %s", network)
|
||||
}
|
||||
|
||||
func FromIPAndZone(ip net.IP, zone string) (ma.Multiaddr, error) {
|
||||
switch {
|
||||
case ip.To4() != nil:
|
||||
return ma.NewComponent("ip4", ip.String())
|
||||
case ip.To16() != nil:
|
||||
ip6, err := ma.NewComponent("ip6", ip.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if zone == "" {
|
||||
return ip6, nil
|
||||
} else {
|
||||
zone, err := ma.NewComponent("ip6zone", zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return zone.Encapsulate(ip6), nil
|
||||
}
|
||||
default:
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
}
|
||||
|
||||
// FromIP converts a net.IP type to a Multiaddr.
|
||||
func FromIP(ip net.IP) (ma.Multiaddr, error) {
|
||||
return FromIPAndZone(ip, "")
|
||||
}
|
||||
|
||||
// ToIP converts a Multiaddr to a net.IP when possible
|
||||
func ToIP(addr ma.Multiaddr) (net.IP, error) {
|
||||
var ip net.IP
|
||||
ma.ForEach(addr, func(c ma.Component) bool {
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_IP6ZONE:
|
||||
// we can't return these anyways.
|
||||
return true
|
||||
case ma.P_IP6, ma.P_IP4:
|
||||
ip = net.IP(c.RawValue())
|
||||
return false
|
||||
}
|
||||
return false
|
||||
})
|
||||
if ip == nil {
|
||||
return nil, errNotIP
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// DialArgs is a convenience function that returns network and address as
|
||||
// expected by net.Dial. See https://godoc.org/net#Dial for an overview of
|
||||
// possible return values (we do not support the unixpacket ones yet). Unix
|
||||
// addresses do not, at present, compose.
|
||||
func DialArgs(m ma.Multiaddr) (string, string, error) {
|
||||
zone, network, ip, port, hostname, err := dialArgComponents(m)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// If we have a hostname (dns*), we don't want any fancy ipv6 formatting
|
||||
// logic (zone, brackets, etc.).
|
||||
if hostname {
|
||||
switch network {
|
||||
case "ip", "ip4", "ip6":
|
||||
return network, ip, nil
|
||||
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
|
||||
return network, ip + ":" + port, nil
|
||||
}
|
||||
// Hostname is only true when network is one of the above.
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
switch network {
|
||||
case "ip6":
|
||||
if zone != "" {
|
||||
ip += "%" + zone
|
||||
}
|
||||
fallthrough
|
||||
case "ip4":
|
||||
return network, ip, nil
|
||||
case "tcp4", "udp4":
|
||||
return network, ip + ":" + port, nil
|
||||
case "tcp6", "udp6":
|
||||
if zone != "" {
|
||||
ip += "%" + zone
|
||||
}
|
||||
return network, "[" + ip + "]" + ":" + port, nil
|
||||
case "unix":
|
||||
if runtime.GOOS == "windows" {
|
||||
// convert /c:/... to c:\...
|
||||
ip = filepath.FromSlash(strings.TrimLeft(ip, "/"))
|
||||
}
|
||||
return network, ip, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("%s is not a 'thin waist' address", m)
|
||||
}
|
||||
}
|
||||
|
||||
// dialArgComponents extracts the raw pieces used in dialing a Multiaddr
|
||||
func dialArgComponents(m ma.Multiaddr) (zone, network, ip, port string, hostname bool, err error) {
|
||||
ma.ForEach(m, func(c ma.Component) bool {
|
||||
switch network {
|
||||
case "":
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_IP6ZONE:
|
||||
if zone != "" {
|
||||
err = fmt.Errorf("%s has multiple zones", m)
|
||||
return false
|
||||
}
|
||||
zone = c.Value()
|
||||
return true
|
||||
case ma.P_IP6:
|
||||
network = "ip6"
|
||||
ip = c.Value()
|
||||
return true
|
||||
case ma.P_IP4:
|
||||
if zone != "" {
|
||||
err = fmt.Errorf("%s has ip4 with zone", m)
|
||||
return false
|
||||
}
|
||||
network = "ip4"
|
||||
ip = c.Value()
|
||||
return true
|
||||
case ma.P_DNS:
|
||||
network = "ip"
|
||||
hostname = true
|
||||
ip = c.Value()
|
||||
return true
|
||||
case ma.P_DNS4:
|
||||
network = "ip4"
|
||||
hostname = true
|
||||
ip = c.Value()
|
||||
return true
|
||||
case ma.P_DNS6:
|
||||
network = "ip6"
|
||||
hostname = true
|
||||
ip = c.Value()
|
||||
return true
|
||||
case ma.P_UNIX:
|
||||
network = "unix"
|
||||
ip = c.Value()
|
||||
return false
|
||||
}
|
||||
case "ip":
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_UDP:
|
||||
network = "udp"
|
||||
case ma.P_TCP:
|
||||
network = "tcp"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
port = c.Value()
|
||||
case "ip4":
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_UDP:
|
||||
network = "udp4"
|
||||
case ma.P_TCP:
|
||||
network = "tcp4"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
port = c.Value()
|
||||
case "ip6":
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_UDP:
|
||||
network = "udp6"
|
||||
case ma.P_TCP:
|
||||
network = "tcp6"
|
||||
default:
|
||||
return false
|
||||
}
|
||||
port = c.Value()
|
||||
}
|
||||
// Done.
|
||||
return false
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func parseTCPNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
ac, ok := a.(*net.TCPAddr)
|
||||
if !ok {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
// Get IP Addr
|
||||
ipm, err := FromIPAndZone(ac.IP, ac.Zone)
|
||||
if err != nil {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
// Get TCP Addr
|
||||
tcpm, err := ma.NewMultiaddr(fmt.Sprintf("/tcp/%d", ac.Port))
|
||||
if err != nil {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
// Encapsulate
|
||||
return ipm.Encapsulate(tcpm), nil
|
||||
}
|
||||
|
||||
func parseUDPNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
ac, ok := a.(*net.UDPAddr)
|
||||
if !ok {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
// Get IP Addr
|
||||
ipm, err := FromIPAndZone(ac.IP, ac.Zone)
|
||||
if err != nil {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
// Get UDP Addr
|
||||
udpm, err := ma.NewMultiaddr(fmt.Sprintf("/udp/%d", ac.Port))
|
||||
if err != nil {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
// Encapsulate
|
||||
return ipm.Encapsulate(udpm), nil
|
||||
}
|
||||
|
||||
func parseIPNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
ac, ok := a.(*net.IPAddr)
|
||||
if !ok {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
return FromIPAndZone(ac.IP, ac.Zone)
|
||||
}
|
||||
|
||||
func parseIPPlusNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
ac, ok := a.(*net.IPNet)
|
||||
if !ok {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
return FromIP(ac.IP)
|
||||
}
|
||||
|
||||
func parseUnixNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||
ac, ok := a.(*net.UnixAddr)
|
||||
if !ok {
|
||||
return nil, errIncorrectNetAddr
|
||||
}
|
||||
|
||||
path := ac.Name
|
||||
if runtime.GOOS == "windows" {
|
||||
// Convert c:\foobar\... to c:/foobar/...
|
||||
path = filepath.ToSlash(path)
|
||||
}
|
||||
if len(path) == 0 || path[0] != '/' {
|
||||
// convert "" and "c:/..." to "/..."
|
||||
path = "/" + path
|
||||
}
|
||||
|
||||
return ma.NewComponent("unix", path)
|
||||
}
|
||||
5
vendor/github.com/multiformats/go-multiaddr/net/doc.go
generated
vendored
Normal file
5
vendor/github.com/multiformats/go-multiaddr/net/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Package manet provides Multiaddr specific versions of common
|
||||
// functions in stdlib's net package. This means wrappers of
|
||||
// standard net symbols like net.Dial and net.Listen, as well
|
||||
// as conversion to/from net.Addr.
|
||||
package manet
|
||||
136
vendor/github.com/multiformats/go-multiaddr/net/ip.go
generated
vendored
Normal file
136
vendor/github.com/multiformats/go-multiaddr/net/ip.go
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
package manet
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// Loopback Addresses
|
||||
var (
|
||||
// IP4Loopback is the ip4 loopback multiaddr
|
||||
IP4Loopback = ma.StringCast("/ip4/127.0.0.1")
|
||||
|
||||
// IP6Loopback is the ip6 loopback multiaddr
|
||||
IP6Loopback = ma.StringCast("/ip6/::1")
|
||||
|
||||
// IP4MappedIP6Loopback is the IPv4 Mapped IPv6 loopback address.
|
||||
IP4MappedIP6Loopback = ma.StringCast("/ip6/::ffff:127.0.0.1")
|
||||
)
|
||||
|
||||
// Unspecified Addresses (used for )
|
||||
var (
|
||||
IP4Unspecified = ma.StringCast("/ip4/0.0.0.0")
|
||||
IP6Unspecified = ma.StringCast("/ip6/::")
|
||||
)
|
||||
|
||||
// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
|
||||
// This means: /{IP4, IP6}[/{TCP, UDP}]
|
||||
func IsThinWaist(m ma.Multiaddr) bool {
|
||||
m = zoneless(m)
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
p := m.Protocols()
|
||||
|
||||
// nothing? not even a waist.
|
||||
if len(p) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
|
||||
return false
|
||||
}
|
||||
|
||||
// only IP? still counts.
|
||||
if len(p) == 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
switch p[1].Code {
|
||||
case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsIPLoopback returns whether a Multiaddr starts with a "Loopback" IP address
|
||||
// This means either /ip4/127.*.*.*/*, /ip6/::1/*, or /ip6/::ffff:127.*.*.*.*/*,
|
||||
// or /ip6zone/<any value>/ip6/<one of the preceding ip6 values>/*
|
||||
func IsIPLoopback(m ma.Multiaddr) bool {
|
||||
m = zoneless(m)
|
||||
c, _ := ma.SplitFirst(m)
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_IP4, ma.P_IP6:
|
||||
return net.IP(c.RawValue()).IsLoopback()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsIP6LinkLocal returns whether a Multiaddr starts with an IPv6 link-local
|
||||
// multiaddress (with zero or one leading zone). These addresses are non
|
||||
// routable.
|
||||
func IsIP6LinkLocal(m ma.Multiaddr) bool {
|
||||
m = zoneless(m)
|
||||
c, _ := ma.SplitFirst(m)
|
||||
if c == nil || c.Protocol().Code != ma.P_IP6 {
|
||||
return false
|
||||
}
|
||||
ip := net.IP(c.RawValue())
|
||||
return ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast()
|
||||
}
|
||||
|
||||
// IsIPUnspecified returns whether a Multiaddr starts with an Unspecified IP address
|
||||
// This means either /ip4/0.0.0.0/* or /ip6/::/*
|
||||
func IsIPUnspecified(m ma.Multiaddr) bool {
|
||||
m = zoneless(m)
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
c, _ := ma.SplitFirst(m)
|
||||
return net.IP(c.RawValue()).IsUnspecified()
|
||||
}
|
||||
|
||||
// If m matches [zone,ip6,...], return [ip6,...]
|
||||
// else if m matches [], [zone], or [zone,...], return nil
|
||||
// else return m
|
||||
func zoneless(m ma.Multiaddr) ma.Multiaddr {
|
||||
head, tail := ma.SplitFirst(m)
|
||||
if head == nil {
|
||||
return nil
|
||||
}
|
||||
if head.Protocol().Code == ma.P_IP6ZONE {
|
||||
if tail == nil {
|
||||
return nil
|
||||
}
|
||||
tailhead, _ := ma.SplitFirst(tail)
|
||||
if tailhead.Protocol().Code != ma.P_IP6 {
|
||||
return nil
|
||||
}
|
||||
return tail
|
||||
} else {
|
||||
return m
|
||||
}
|
||||
}
|
||||
|
||||
var nat64WellKnownPrefix net.IPNet
|
||||
|
||||
func init() {
|
||||
_, np, err := net.ParseCIDR("64:ff9b::/96")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nat64WellKnownPrefix = *np
|
||||
}
|
||||
|
||||
// IsNAT64IPv4ConvertedIPv6Addr returns whether addr is a well-known prefix "64:ff9b::/96" addr
|
||||
// used for NAT64 Translation. See RFC 6052
|
||||
func IsNAT64IPv4ConvertedIPv6Addr(addr ma.Multiaddr) bool {
|
||||
c, _ := ma.SplitFirst(addr)
|
||||
return c != nil && c.Protocol().Code == ma.P_IP6 &&
|
||||
nat64WellKnownPrefix.Contains(net.IP(c.RawValue()))
|
||||
}
|
||||
430
vendor/github.com/multiformats/go-multiaddr/net/net.go
generated
vendored
Normal file
430
vendor/github.com/multiformats/go-multiaddr/net/net.go
generated
vendored
Normal file
@@ -0,0 +1,430 @@
|
||||
// Package manet provides Multiaddr
|
||||
// (https://github.com/multiformats/go-multiaddr) specific versions of common
|
||||
// functions in Go's standard `net` package. This means wrappers of standard
|
||||
// net symbols like `net.Dial` and `net.Listen`, as well as conversion to
|
||||
// and from `net.Addr`.
|
||||
package manet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// Conn is the equivalent of a net.Conn object. It is the
|
||||
// result of calling the Dial or Listen functions in this
|
||||
// package, with associated local and remote Multiaddrs.
|
||||
type Conn interface {
|
||||
net.Conn
|
||||
|
||||
// LocalMultiaddr returns the local Multiaddr associated
|
||||
// with this connection
|
||||
LocalMultiaddr() ma.Multiaddr
|
||||
|
||||
// RemoteMultiaddr returns the remote Multiaddr associated
|
||||
// with this connection
|
||||
RemoteMultiaddr() ma.Multiaddr
|
||||
}
|
||||
|
||||
type halfOpen interface {
|
||||
net.Conn
|
||||
CloseRead() error
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
func wrap(nconn net.Conn, laddr, raddr ma.Multiaddr) Conn {
|
||||
endpts := maEndpoints{
|
||||
laddr: laddr,
|
||||
raddr: raddr,
|
||||
}
|
||||
// This sucks. However, it's the only way to reliably expose the
|
||||
// underlying methods. This way, users that need access to, e.g.,
|
||||
// CloseRead and CloseWrite, can do so via type assertions.
|
||||
switch nconn := nconn.(type) {
|
||||
case *net.TCPConn:
|
||||
return &struct {
|
||||
*net.TCPConn
|
||||
maEndpoints
|
||||
}{nconn, endpts}
|
||||
case *net.UDPConn:
|
||||
return &struct {
|
||||
*net.UDPConn
|
||||
maEndpoints
|
||||
}{nconn, endpts}
|
||||
case *net.IPConn:
|
||||
return &struct {
|
||||
*net.IPConn
|
||||
maEndpoints
|
||||
}{nconn, endpts}
|
||||
case *net.UnixConn:
|
||||
return &struct {
|
||||
*net.UnixConn
|
||||
maEndpoints
|
||||
}{nconn, endpts}
|
||||
case halfOpen:
|
||||
return &struct {
|
||||
halfOpen
|
||||
maEndpoints
|
||||
}{nconn, endpts}
|
||||
default:
|
||||
return &struct {
|
||||
net.Conn
|
||||
maEndpoints
|
||||
}{nconn, endpts}
|
||||
}
|
||||
}
|
||||
|
||||
// WrapNetConn wraps a net.Conn object with a Multiaddr friendly Conn.
|
||||
//
|
||||
// This function does it's best to avoid "hiding" methods exposed by the wrapped
|
||||
// type. Guarantees:
|
||||
//
|
||||
// - If the wrapped connection exposes the "half-open" closer methods
|
||||
// (CloseWrite, CloseRead), these will be available on the wrapped connection
|
||||
// via type assertions.
|
||||
// - If the wrapped connection is a UnixConn, IPConn, TCPConn, or UDPConn, all
|
||||
// methods on these wrapped connections will be available via type assertions.
|
||||
func WrapNetConn(nconn net.Conn) (Conn, error) {
|
||||
if nconn == nil {
|
||||
return nil, fmt.Errorf("failed to convert nconn.LocalAddr: nil")
|
||||
}
|
||||
|
||||
laddr, err := FromNetAddr(nconn.LocalAddr())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert nconn.LocalAddr: %s", err)
|
||||
}
|
||||
|
||||
raddr, err := FromNetAddr(nconn.RemoteAddr())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert nconn.RemoteAddr: %s", err)
|
||||
}
|
||||
|
||||
return wrap(nconn, laddr, raddr), nil
|
||||
}
|
||||
|
||||
type maEndpoints struct {
|
||||
laddr ma.Multiaddr
|
||||
raddr ma.Multiaddr
|
||||
}
|
||||
|
||||
// LocalMultiaddr returns the local address associated with
|
||||
// this connection
|
||||
func (c *maEndpoints) LocalMultiaddr() ma.Multiaddr {
|
||||
return c.laddr
|
||||
}
|
||||
|
||||
// RemoteMultiaddr returns the remote address associated with
|
||||
// this connection
|
||||
func (c *maEndpoints) RemoteMultiaddr() ma.Multiaddr {
|
||||
return c.raddr
|
||||
}
|
||||
|
||||
// Dialer contains options for connecting to an address. It
|
||||
// is effectively the same as net.Dialer, but its LocalAddr
|
||||
// and RemoteAddr options are Multiaddrs, instead of net.Addrs.
|
||||
type Dialer struct {
|
||||
|
||||
// Dialer is just an embedded net.Dialer, with all its options.
|
||||
net.Dialer
|
||||
|
||||
// LocalAddr is the local address to use when dialing an
|
||||
// address. The address must be of a compatible type for the
|
||||
// network being dialed.
|
||||
// If nil, a local address is automatically chosen.
|
||||
LocalAddr ma.Multiaddr
|
||||
}
|
||||
|
||||
// Dial connects to a remote address, using the options of the
|
||||
// Dialer. Dialer uses an underlying net.Dialer to Dial a
|
||||
// net.Conn, then wraps that in a Conn object (with local and
|
||||
// remote Multiaddrs).
|
||||
func (d *Dialer) Dial(remote ma.Multiaddr) (Conn, error) {
|
||||
return d.DialContext(context.Background(), remote)
|
||||
}
|
||||
|
||||
// DialContext allows to provide a custom context to Dial().
|
||||
func (d *Dialer) DialContext(ctx context.Context, remote ma.Multiaddr) (Conn, error) {
|
||||
// if a LocalAddr is specified, use it on the embedded dialer.
|
||||
if d.LocalAddr != nil {
|
||||
// convert our multiaddr to net.Addr friendly
|
||||
naddr, err := ToNetAddr(d.LocalAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// set the dialer's LocalAddr as naddr
|
||||
d.Dialer.LocalAddr = naddr
|
||||
}
|
||||
|
||||
// get the net.Dial friendly arguments from the remote addr
|
||||
rnet, rnaddr, err := DialArgs(remote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ok, Dial!
|
||||
var nconn net.Conn
|
||||
switch rnet {
|
||||
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "unix":
|
||||
nconn, err = d.Dialer.DialContext(ctx, rnet, rnaddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized network: %s", rnet)
|
||||
}
|
||||
|
||||
// get local address (pre-specified or assigned within net.Conn)
|
||||
local := d.LocalAddr
|
||||
// This block helps us avoid parsing addresses in transports (such as unix
|
||||
// sockets) that don't have local addresses when dialing out.
|
||||
if local == nil && nconn.LocalAddr().String() != "" {
|
||||
local, err = FromNetAddr(nconn.LocalAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return wrap(nconn, local, remote), nil
|
||||
}
|
||||
|
||||
// Dial connects to a remote address. It uses an underlying net.Conn,
|
||||
// then wraps it in a Conn object (with local and remote Multiaddrs).
|
||||
func Dial(remote ma.Multiaddr) (Conn, error) {
|
||||
return (&Dialer{}).Dial(remote)
|
||||
}
|
||||
|
||||
// A Listener is a generic network listener for stream-oriented protocols.
|
||||
// it uses an embedded net.Listener, overriding net.Listener.Accept to
|
||||
// return a Conn and providing Multiaddr.
|
||||
type Listener interface {
|
||||
// Accept waits for and returns the next connection to the listener.
|
||||
// Returns a Multiaddr friendly Conn
|
||||
Accept() (Conn, error)
|
||||
|
||||
// Close closes the listener.
|
||||
// Any blocked Accept operations will be unblocked and return errors.
|
||||
Close() error
|
||||
|
||||
// Multiaddr returns the listener's (local) Multiaddr.
|
||||
Multiaddr() ma.Multiaddr
|
||||
|
||||
// Addr returns the net.Listener's network address.
|
||||
Addr() net.Addr
|
||||
}
|
||||
|
||||
type netListenerAdapter struct {
|
||||
Listener
|
||||
}
|
||||
|
||||
func (nla *netListenerAdapter) Accept() (net.Conn, error) {
|
||||
return nla.Listener.Accept()
|
||||
}
|
||||
|
||||
// NetListener turns this Listener into a net.Listener.
|
||||
//
|
||||
// - Connections returned from Accept implement multiaddr/net Conn.
|
||||
// - Calling WrapNetListener on the net.Listener returned by this function will
|
||||
// return the original (underlying) multiaddr/net Listener.
|
||||
func NetListener(l Listener) net.Listener {
|
||||
return &netListenerAdapter{l}
|
||||
}
|
||||
|
||||
// maListener implements Listener
|
||||
type maListener struct {
|
||||
net.Listener
|
||||
laddr ma.Multiaddr
|
||||
}
|
||||
|
||||
// Accept waits for and returns the next connection to the listener.
|
||||
// Returns a Multiaddr friendly Conn
|
||||
func (l *maListener) Accept() (Conn, error) {
|
||||
nconn, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var raddr ma.Multiaddr
|
||||
// This block protects us in transports (i.e. unix sockets) that don't have
|
||||
// remote addresses for inbound connections.
|
||||
if addr := nconn.RemoteAddr(); addr != nil && addr.String() != "" {
|
||||
raddr, err = FromNetAddr(addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert conn.RemoteAddr: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
var laddr ma.Multiaddr
|
||||
if addr := nconn.LocalAddr(); addr != nil && addr.String() != "" {
|
||||
laddr, err = FromNetAddr(addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert conn.LocalAddr: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return wrap(nconn, laddr, raddr), nil
|
||||
}
|
||||
|
||||
// Multiaddr returns the listener's (local) Multiaddr.
|
||||
func (l *maListener) Multiaddr() ma.Multiaddr {
|
||||
return l.laddr
|
||||
}
|
||||
|
||||
// Addr returns the listener's network address.
|
||||
func (l *maListener) Addr() net.Addr {
|
||||
return l.Listener.Addr()
|
||||
}
|
||||
|
||||
// Listen announces on the local network address laddr.
|
||||
// The Multiaddr must be a "ThinWaist" stream-oriented network:
|
||||
// ip4/tcp, ip6/tcp, (TODO: unix, unixpacket)
|
||||
// See Dial for the syntax of laddr.
|
||||
func Listen(laddr ma.Multiaddr) (Listener, error) {
|
||||
|
||||
// get the net.Listen friendly arguments from the remote addr
|
||||
lnet, lnaddr, err := DialArgs(laddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nl, err := net.Listen(lnet, lnaddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// we want to fetch the new multiaddr from the listener, as it may
|
||||
// have resolved to some other value. WrapNetListener does it for us.
|
||||
return WrapNetListener(nl)
|
||||
}
|
||||
|
||||
// WrapNetListener wraps a net.Listener with a manet.Listener.
|
||||
func WrapNetListener(nl net.Listener) (Listener, error) {
|
||||
if nla, ok := nl.(*netListenerAdapter); ok {
|
||||
return nla.Listener, nil
|
||||
}
|
||||
|
||||
laddr, err := FromNetAddr(nl.Addr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &maListener{
|
||||
Listener: nl,
|
||||
laddr: laddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// A PacketConn is a generic packet oriented network connection which uses an
|
||||
// underlying net.PacketConn, wrapped with the locally bound Multiaddr.
|
||||
type PacketConn interface {
|
||||
net.PacketConn
|
||||
|
||||
LocalMultiaddr() ma.Multiaddr
|
||||
|
||||
ReadFromMultiaddr(b []byte) (int, ma.Multiaddr, error)
|
||||
WriteToMultiaddr(b []byte, maddr ma.Multiaddr) (int, error)
|
||||
}
|
||||
|
||||
// maPacketConn implements PacketConn
|
||||
type maPacketConn struct {
|
||||
net.PacketConn
|
||||
laddr ma.Multiaddr
|
||||
}
|
||||
|
||||
var _ PacketConn = (*maPacketConn)(nil)
|
||||
|
||||
// LocalMultiaddr returns the bound local Multiaddr.
|
||||
func (l *maPacketConn) LocalMultiaddr() ma.Multiaddr {
|
||||
return l.laddr
|
||||
}
|
||||
|
||||
func (l *maPacketConn) ReadFromMultiaddr(b []byte) (int, ma.Multiaddr, error) {
|
||||
n, addr, err := l.ReadFrom(b)
|
||||
maddr, _ := FromNetAddr(addr)
|
||||
return n, maddr, err
|
||||
}
|
||||
|
||||
func (l *maPacketConn) WriteToMultiaddr(b []byte, maddr ma.Multiaddr) (int, error) {
|
||||
addr, err := ToNetAddr(maddr)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return l.WriteTo(b, addr)
|
||||
}
|
||||
|
||||
// ListenPacket announces on the local network address laddr.
|
||||
// The Multiaddr must be a packet driven network, like udp4 or udp6.
|
||||
// See Dial for the syntax of laddr.
|
||||
func ListenPacket(laddr ma.Multiaddr) (PacketConn, error) {
|
||||
lnet, lnaddr, err := DialArgs(laddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pc, err := net.ListenPacket(lnet, lnaddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We want to fetch the new multiaddr from the listener, as it may
|
||||
// have resolved to some other value. WrapPacketConn does this.
|
||||
return WrapPacketConn(pc)
|
||||
}
|
||||
|
||||
// WrapPacketConn wraps a net.PacketConn with a manet.PacketConn.
|
||||
func WrapPacketConn(pc net.PacketConn) (PacketConn, error) {
|
||||
laddr, err := FromNetAddr(pc.LocalAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &maPacketConn{
|
||||
PacketConn: pc,
|
||||
laddr: laddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InterfaceMultiaddrs will return the addresses matching net.InterfaceAddrs
|
||||
func InterfaceMultiaddrs() ([]ma.Multiaddr, error) {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maddrs := make([]ma.Multiaddr, len(addrs))
|
||||
for i, a := range addrs {
|
||||
maddrs[i], err = FromNetAddr(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return maddrs, nil
|
||||
}
|
||||
|
||||
// AddrMatch returns the Multiaddrs that match the protocol stack on addr
|
||||
func AddrMatch(match ma.Multiaddr, addrs []ma.Multiaddr) []ma.Multiaddr {
|
||||
|
||||
// we should match transports entirely.
|
||||
p1s := match.Protocols()
|
||||
|
||||
out := make([]ma.Multiaddr, 0, len(addrs))
|
||||
for _, a := range addrs {
|
||||
p2s := a.Protocols()
|
||||
if len(p1s) != len(p2s) {
|
||||
continue
|
||||
}
|
||||
|
||||
match := true
|
||||
for i, p2 := range p2s {
|
||||
if p1s[i].Code != p2.Code {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if match {
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
177
vendor/github.com/multiformats/go-multiaddr/net/private.go
generated
vendored
Normal file
177
vendor/github.com/multiformats/go-multiaddr/net/private.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
package manet
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// Private4 and Private6 are well-known private networks
|
||||
var Private4, Private6 []*net.IPNet
|
||||
var privateCIDR4 = []string{
|
||||
// localhost
|
||||
"127.0.0.0/8",
|
||||
// private networks
|
||||
"10.0.0.0/8",
|
||||
"100.64.0.0/10",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16",
|
||||
// link local
|
||||
"169.254.0.0/16",
|
||||
}
|
||||
var privateCIDR6 = []string{
|
||||
// localhost
|
||||
"::1/128",
|
||||
// ULA reserved
|
||||
"fc00::/7",
|
||||
// link local
|
||||
"fe80::/10",
|
||||
}
|
||||
|
||||
// Unroutable4 and Unroutable6 are well known unroutable address ranges
|
||||
var Unroutable4, Unroutable6 []*net.IPNet
|
||||
var unroutableCIDR4 = []string{
|
||||
"0.0.0.0/8",
|
||||
"192.0.0.0/26",
|
||||
"192.0.2.0/24",
|
||||
"192.88.99.0/24",
|
||||
"198.18.0.0/15",
|
||||
"198.51.100.0/24",
|
||||
"203.0.113.0/24",
|
||||
"224.0.0.0/4",
|
||||
"240.0.0.0/4",
|
||||
"255.255.255.255/32",
|
||||
}
|
||||
var unroutableCIDR6 = []string{
|
||||
"ff00::/8",
|
||||
}
|
||||
|
||||
// unResolvableDomains do not resolve to an IP address.
|
||||
// Ref: https://en.wikipedia.org/wiki/Special-use_domain_name#Reserved_domain_names
|
||||
var unResolvableDomains = []string{
|
||||
// Reverse DNS Lookup
|
||||
".in-addr.arpa",
|
||||
".ip6.arpa",
|
||||
|
||||
// RFC 6761: Users MAY assume that queries for "invalid" names will always return NXDOMAIN
|
||||
// responses
|
||||
".invalid",
|
||||
}
|
||||
|
||||
// privateUseDomains are reserved for private use and have no central authority for consistent
|
||||
// address resolution
|
||||
// Ref: https://en.wikipedia.org/wiki/Special-use_domain_name#Reserved_domain_names
|
||||
var privateUseDomains = []string{
|
||||
// RFC 8375: Reserved for home networks
|
||||
".home.arpa",
|
||||
|
||||
// MDNS
|
||||
".local",
|
||||
|
||||
// RFC 6761: No central authority for .test names
|
||||
".test",
|
||||
}
|
||||
|
||||
// RFC 6761: Users may assume that IPv4 and IPv6 address queries for localhost names will
|
||||
// always resolve to the respective IP loopback address
|
||||
const localHostDomain = ".localhost"
|
||||
|
||||
func init() {
|
||||
Private4 = parseCIDR(privateCIDR4)
|
||||
Private6 = parseCIDR(privateCIDR6)
|
||||
Unroutable4 = parseCIDR(unroutableCIDR4)
|
||||
Unroutable6 = parseCIDR(unroutableCIDR6)
|
||||
}
|
||||
|
||||
func parseCIDR(cidrs []string) []*net.IPNet {
|
||||
ipnets := make([]*net.IPNet, len(cidrs))
|
||||
for i, cidr := range cidrs {
|
||||
_, ipnet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ipnets[i] = ipnet
|
||||
}
|
||||
return ipnets
|
||||
}
|
||||
|
||||
// IsPublicAddr returns true if the IP part of the multiaddr is a publicly routable address
|
||||
// or if it's a dns address without a special use domain e.g. .local.
|
||||
func IsPublicAddr(a ma.Multiaddr) bool {
|
||||
isPublic := false
|
||||
ma.ForEach(a, func(c ma.Component) bool {
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_IP6ZONE:
|
||||
return true
|
||||
case ma.P_IP4:
|
||||
ip := net.IP(c.RawValue())
|
||||
isPublic = !inAddrRange(ip, Private4) && !inAddrRange(ip, Unroutable4)
|
||||
case ma.P_IP6:
|
||||
ip := net.IP(c.RawValue())
|
||||
isPublic = !inAddrRange(ip, Private6) && !inAddrRange(ip, Unroutable6)
|
||||
case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR:
|
||||
dnsAddr := c.Value()
|
||||
isPublic = true
|
||||
if isSubdomain(dnsAddr, localHostDomain) {
|
||||
isPublic = false
|
||||
return false
|
||||
}
|
||||
for _, ud := range unResolvableDomains {
|
||||
if isSubdomain(dnsAddr, ud) {
|
||||
isPublic = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, pd := range privateUseDomains {
|
||||
if isSubdomain(dnsAddr, pd) {
|
||||
isPublic = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
return isPublic
|
||||
}
|
||||
|
||||
// isSubdomain checks if child is sub domain of parent. It also returns true if child and parent are
|
||||
// the same domain.
|
||||
// Parent must have a "." prefix.
|
||||
func isSubdomain(child, parent string) bool {
|
||||
return strings.HasSuffix(child, parent) || child == parent[1:]
|
||||
}
|
||||
|
||||
// IsPrivateAddr returns true if the IP part of the mutiaddr is in a private network
|
||||
func IsPrivateAddr(a ma.Multiaddr) bool {
|
||||
isPrivate := false
|
||||
ma.ForEach(a, func(c ma.Component) bool {
|
||||
switch c.Protocol().Code {
|
||||
case ma.P_IP6ZONE:
|
||||
return true
|
||||
case ma.P_IP4:
|
||||
isPrivate = inAddrRange(net.IP(c.RawValue()), Private4)
|
||||
case ma.P_IP6:
|
||||
isPrivate = inAddrRange(net.IP(c.RawValue()), Private6)
|
||||
case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR:
|
||||
dnsAddr := c.Value()
|
||||
if isSubdomain(dnsAddr, localHostDomain) {
|
||||
isPrivate = true
|
||||
}
|
||||
// We don't check for privateUseDomains because private use domains can
|
||||
// resolve to public IP addresses
|
||||
}
|
||||
return false
|
||||
})
|
||||
return isPrivate
|
||||
}
|
||||
|
||||
func inAddrRange(ip net.IP, ipnets []*net.IPNet) bool {
|
||||
for _, ipnet := range ipnets {
|
||||
if ipnet.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
97
vendor/github.com/multiformats/go-multiaddr/net/registry.go
generated
vendored
Normal file
97
vendor/github.com/multiformats/go-multiaddr/net/registry.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package manet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// FromNetAddrFunc is a generic function which converts a net.Addr to Multiaddress
|
||||
type FromNetAddrFunc func(a net.Addr) (ma.Multiaddr, error)
|
||||
|
||||
// ToNetAddrFunc is a generic function which converts a Multiaddress to net.Addr
|
||||
type ToNetAddrFunc func(ma ma.Multiaddr) (net.Addr, error)
|
||||
|
||||
var defaultCodecs = NewCodecMap()
|
||||
|
||||
func init() {
|
||||
RegisterFromNetAddr(parseTCPNetAddr, "tcp", "tcp4", "tcp6")
|
||||
RegisterFromNetAddr(parseUDPNetAddr, "udp", "udp4", "udp6")
|
||||
RegisterFromNetAddr(parseIPNetAddr, "ip", "ip4", "ip6")
|
||||
RegisterFromNetAddr(parseIPPlusNetAddr, "ip+net")
|
||||
RegisterFromNetAddr(parseUnixNetAddr, "unix")
|
||||
|
||||
RegisterToNetAddr(parseBasicNetMaddr, "tcp", "udp", "ip6", "ip4", "unix")
|
||||
}
|
||||
|
||||
// CodecMap holds a map of NetCodecs indexed by their Protocol ID
|
||||
// along with parsers for the addresses they use.
|
||||
// It is used to keep a list of supported network address codecs (protocols
|
||||
// which addresses can be converted to and from multiaddresses).
|
||||
type CodecMap struct {
|
||||
addrParsers map[string]FromNetAddrFunc
|
||||
maddrParsers map[string]ToNetAddrFunc
|
||||
lk sync.Mutex
|
||||
}
|
||||
|
||||
// NewCodecMap initializes and returns a CodecMap object.
|
||||
func NewCodecMap() *CodecMap {
|
||||
return &CodecMap{
|
||||
addrParsers: make(map[string]FromNetAddrFunc),
|
||||
maddrParsers: make(map[string]ToNetAddrFunc),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterFromNetAddr registers a conversion from net.Addr instances to multiaddrs.
|
||||
func RegisterFromNetAddr(from FromNetAddrFunc, networks ...string) {
|
||||
defaultCodecs.RegisterFromNetAddr(from, networks...)
|
||||
}
|
||||
|
||||
// RegisterToNetAddr registers a conversion from multiaddrs to net.Addr instances.
|
||||
func RegisterToNetAddr(to ToNetAddrFunc, protocols ...string) {
|
||||
defaultCodecs.RegisterToNetAddr(to, protocols...)
|
||||
}
|
||||
|
||||
// RegisterFromNetAddr registers a conversion from net.Addr instances to multiaddrs
|
||||
func (cm *CodecMap) RegisterFromNetAddr(from FromNetAddrFunc, networks ...string) {
|
||||
cm.lk.Lock()
|
||||
defer cm.lk.Unlock()
|
||||
|
||||
for _, n := range networks {
|
||||
cm.addrParsers[n] = from
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterToNetAddr registers a conversion from multiaddrs to net.Addr instances
|
||||
func (cm *CodecMap) RegisterToNetAddr(to ToNetAddrFunc, protocols ...string) {
|
||||
cm.lk.Lock()
|
||||
defer cm.lk.Unlock()
|
||||
|
||||
for _, p := range protocols {
|
||||
cm.maddrParsers[p] = to
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *CodecMap) getAddrParser(net string) (FromNetAddrFunc, error) {
|
||||
cm.lk.Lock()
|
||||
defer cm.lk.Unlock()
|
||||
|
||||
parser, ok := cm.addrParsers[net]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown network %v", net)
|
||||
}
|
||||
return parser, nil
|
||||
}
|
||||
|
||||
func (cm *CodecMap) getMaddrParser(name string) (ToNetAddrFunc, error) {
|
||||
cm.lk.Lock()
|
||||
defer cm.lk.Unlock()
|
||||
p, ok := cm.maddrParsers[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("network not supported: %s", name)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
83
vendor/github.com/multiformats/go-multiaddr/net/resolve.go
generated
vendored
Normal file
83
vendor/github.com/multiformats/go-multiaddr/net/resolve.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package manet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
||||
// ResolveUnspecifiedAddress expands an unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to
|
||||
// use the known local interfaces. If ifaceAddr is nil, we request interface addresses
|
||||
// from the network stack. (this is so you can provide a cached value if resolving many addrs)
|
||||
func ResolveUnspecifiedAddress(resolve ma.Multiaddr, ifaceAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
|
||||
// split address into its components
|
||||
split := ma.Split(resolve)
|
||||
|
||||
// if first component (ip) is not unspecified, use it as is.
|
||||
if !IsIPUnspecified(split[0]) {
|
||||
return []ma.Multiaddr{resolve}, nil
|
||||
}
|
||||
|
||||
out := make([]ma.Multiaddr, 0, len(ifaceAddrs))
|
||||
for _, ia := range ifaceAddrs {
|
||||
// must match the first protocol to be resolve.
|
||||
if ia.Protocols()[0].Code != resolve.Protocols()[0].Code {
|
||||
continue
|
||||
}
|
||||
|
||||
split[0] = ia
|
||||
joined := ma.Join(split...)
|
||||
out = append(out, joined)
|
||||
}
|
||||
if len(out) < 1 {
|
||||
return nil, fmt.Errorf("failed to resolve: %s", resolve)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ResolveUnspecifiedAddresses expands unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to
|
||||
// use the known local interfaces.
|
||||
func ResolveUnspecifiedAddresses(unspecAddrs, ifaceAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
|
||||
// todo optimize: only fetch these if we have a "any" addr.
|
||||
if len(ifaceAddrs) < 1 {
|
||||
var err error
|
||||
ifaceAddrs, err = interfaceAddresses()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var outputAddrs []ma.Multiaddr
|
||||
for _, a := range unspecAddrs {
|
||||
// unspecified?
|
||||
resolved, err := ResolveUnspecifiedAddress(a, ifaceAddrs)
|
||||
if err != nil {
|
||||
continue // optimistic. if we can't resolve anything, we'll know at the bottom.
|
||||
}
|
||||
outputAddrs = append(outputAddrs, resolved...)
|
||||
}
|
||||
|
||||
if len(outputAddrs) < 1 {
|
||||
return nil, fmt.Errorf("failed to specify addrs: %s", unspecAddrs)
|
||||
}
|
||||
return outputAddrs, nil
|
||||
}
|
||||
|
||||
// interfaceAddresses returns a list of addresses associated with local machine
|
||||
// Note: we do not return link local addresses. IP loopback is ok, because we
|
||||
// may be connecting to other nodes in the same machine.
|
||||
func interfaceAddresses() ([]ma.Multiaddr, error) {
|
||||
maddrs, err := InterfaceMultiaddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []ma.Multiaddr
|
||||
for _, a := range maddrs {
|
||||
if IsIP6LinkLocal(a) {
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
23
vendor/github.com/multiformats/go-multiaddr/package.json
generated
vendored
Normal file
23
vendor/github.com/multiformats/go-multiaddr/package.json
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"author": "multiformats",
|
||||
"bugs": {
|
||||
"url": "https://github.com/multiformats/go-multiaddr/issues"
|
||||
},
|
||||
"gx": {
|
||||
"dvcsimport": "github.com/multiformats/go-multiaddr"
|
||||
},
|
||||
"gxDependencies": [
|
||||
{
|
||||
"hash": "QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW",
|
||||
"name": "go-multihash",
|
||||
"version": "1.0.9"
|
||||
}
|
||||
],
|
||||
"gxVersion": "0.9.0",
|
||||
"language": "go",
|
||||
"license": "MIT",
|
||||
"name": "go-multiaddr",
|
||||
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
|
||||
"version": "1.4.1"
|
||||
}
|
||||
|
||||
102
vendor/github.com/multiformats/go-multiaddr/protocol.go
generated
vendored
Normal file
102
vendor/github.com/multiformats/go-multiaddr/protocol.go
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// These are special sizes
|
||||
const (
|
||||
LengthPrefixedVarSize = -1
|
||||
)
|
||||
|
||||
// Protocol is a Multiaddr protocol description structure.
|
||||
type Protocol struct {
|
||||
// Name is the string representation of the protocol code. E.g., ip4,
|
||||
// ip6, tcp, udp, etc.
|
||||
Name string
|
||||
|
||||
// Code is the protocol's multicodec (a normal, non-varint number).
|
||||
Code int
|
||||
|
||||
// VCode is a precomputed varint encoded version of Code.
|
||||
VCode []byte
|
||||
|
||||
// Size is the size of the argument to this protocol.
|
||||
//
|
||||
// * Size == 0 means this protocol takes no argument.
|
||||
// * Size > 0 means this protocol takes a constant sized argument.
|
||||
// * Size < 0 means this protocol takes a variable length, varint
|
||||
// prefixed argument.
|
||||
Size int // a size of -1 indicates a length-prefixed variable size
|
||||
|
||||
// Path indicates a path protocol (e.g., unix). When parsing multiaddr
|
||||
// strings, path protocols consume the remainder of the address instead
|
||||
// of stopping at the next forward slash.
|
||||
//
|
||||
// Size must be LengthPrefixedVarSize.
|
||||
Path bool
|
||||
|
||||
// Transcoder converts between the byte representation and the string
|
||||
// representation of this protocol's argument (if any).
|
||||
//
|
||||
// This should only be non-nil if Size != 0
|
||||
Transcoder Transcoder
|
||||
}
|
||||
|
||||
var protocolsByName = map[string]Protocol{}
|
||||
var protocolsByCode = map[int]Protocol{}
|
||||
|
||||
// Protocols is the list of multiaddr protocols supported by this module.
|
||||
var Protocols = []Protocol{}
|
||||
|
||||
func AddProtocol(p Protocol) error {
|
||||
if _, ok := protocolsByName[p.Name]; ok {
|
||||
return fmt.Errorf("protocol by the name %q already exists", p.Name)
|
||||
}
|
||||
|
||||
if _, ok := protocolsByCode[p.Code]; ok {
|
||||
return fmt.Errorf("protocol code %d already taken by %q", p.Code, p.Code)
|
||||
}
|
||||
|
||||
if p.Size != 0 && p.Transcoder == nil {
|
||||
return fmt.Errorf("protocols with arguments must define transcoders")
|
||||
}
|
||||
if p.Path && p.Size >= 0 {
|
||||
return fmt.Errorf("path protocols must have variable-length sizes")
|
||||
}
|
||||
|
||||
Protocols = append(Protocols, p)
|
||||
protocolsByName[p.Name] = p
|
||||
protocolsByCode[p.Code] = p
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProtocolWithName returns the Protocol description with given string name.
|
||||
func ProtocolWithName(s string) Protocol {
|
||||
return protocolsByName[s]
|
||||
}
|
||||
|
||||
// ProtocolWithCode returns the Protocol description with given protocol code.
|
||||
func ProtocolWithCode(c int) Protocol {
|
||||
return protocolsByCode[c]
|
||||
}
|
||||
|
||||
// ProtocolsWithString returns a slice of protocols matching given string.
|
||||
func ProtocolsWithString(s string) ([]Protocol, error) {
|
||||
s = strings.Trim(s, "/")
|
||||
sp := strings.Split(s, "/")
|
||||
if len(sp) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
t := make([]Protocol, len(sp))
|
||||
for i, name := range sp {
|
||||
p := ProtocolWithName(name)
|
||||
if p.Code == 0 {
|
||||
return nil, fmt.Errorf("no protocol with name: %s", name)
|
||||
}
|
||||
t[i] = p
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
325
vendor/github.com/multiformats/go-multiaddr/protocols.go
generated
vendored
Normal file
325
vendor/github.com/multiformats/go-multiaddr/protocols.go
generated
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
package multiaddr
|
||||
|
||||
// You **MUST** register your multicodecs with
|
||||
// https://github.com/multiformats/multicodec before adding them here.
|
||||
const (
|
||||
P_IP4 = 4
|
||||
P_TCP = 6
|
||||
P_DNS = 53 // 4 or 6
|
||||
P_DNS4 = 54
|
||||
P_DNS6 = 55
|
||||
P_DNSADDR = 56
|
||||
P_UDP = 273
|
||||
P_DCCP = 33
|
||||
P_IP6 = 41
|
||||
P_IP6ZONE = 42
|
||||
P_IPCIDR = 43
|
||||
P_QUIC = 460
|
||||
P_QUIC_V1 = 461
|
||||
P_WEBTRANSPORT = 465
|
||||
P_CERTHASH = 466
|
||||
P_SCTP = 132
|
||||
P_CIRCUIT = 290
|
||||
P_UDT = 301
|
||||
P_UTP = 302
|
||||
P_UNIX = 400
|
||||
P_P2P = 421
|
||||
P_IPFS = P_P2P // alias for backwards compatibility
|
||||
P_HTTP = 480
|
||||
P_HTTPS = 443 // deprecated alias for /tls/http
|
||||
P_ONION = 444 // also for backwards compatibility
|
||||
P_ONION3 = 445
|
||||
P_GARLIC64 = 446
|
||||
P_GARLIC32 = 447
|
||||
P_P2P_WEBRTC_DIRECT = 276 // Deprecated. use webrtc-direct instead
|
||||
P_TLS = 448
|
||||
P_SNI = 449
|
||||
P_NOISE = 454
|
||||
P_WS = 477
|
||||
P_WSS = 478 // deprecated alias for /tls/ws
|
||||
P_PLAINTEXTV2 = 7367777
|
||||
P_WEBRTC_DIRECT = 280
|
||||
P_WEBRTC = 281
|
||||
)
|
||||
|
||||
var (
|
||||
protoIP4 = Protocol{
|
||||
Name: "ip4",
|
||||
Code: P_IP4,
|
||||
VCode: CodeToVarint(P_IP4),
|
||||
Size: 32,
|
||||
Path: false,
|
||||
Transcoder: TranscoderIP4,
|
||||
}
|
||||
protoTCP = Protocol{
|
||||
Name: "tcp",
|
||||
Code: P_TCP,
|
||||
VCode: CodeToVarint(P_TCP),
|
||||
Size: 16,
|
||||
Path: false,
|
||||
Transcoder: TranscoderPort,
|
||||
}
|
||||
protoDNS = Protocol{
|
||||
Code: P_DNS,
|
||||
Size: LengthPrefixedVarSize,
|
||||
Name: "dns",
|
||||
VCode: CodeToVarint(P_DNS),
|
||||
Transcoder: TranscoderDns,
|
||||
}
|
||||
protoDNS4 = Protocol{
|
||||
Code: P_DNS4,
|
||||
Size: LengthPrefixedVarSize,
|
||||
Name: "dns4",
|
||||
VCode: CodeToVarint(P_DNS4),
|
||||
Transcoder: TranscoderDns,
|
||||
}
|
||||
protoDNS6 = Protocol{
|
||||
Code: P_DNS6,
|
||||
Size: LengthPrefixedVarSize,
|
||||
Name: "dns6",
|
||||
VCode: CodeToVarint(P_DNS6),
|
||||
Transcoder: TranscoderDns,
|
||||
}
|
||||
protoDNSADDR = Protocol{
|
||||
Code: P_DNSADDR,
|
||||
Size: LengthPrefixedVarSize,
|
||||
Name: "dnsaddr",
|
||||
VCode: CodeToVarint(P_DNSADDR),
|
||||
Transcoder: TranscoderDns,
|
||||
}
|
||||
protoUDP = Protocol{
|
||||
Name: "udp",
|
||||
Code: P_UDP,
|
||||
VCode: CodeToVarint(P_UDP),
|
||||
Size: 16,
|
||||
Path: false,
|
||||
Transcoder: TranscoderPort,
|
||||
}
|
||||
protoDCCP = Protocol{
|
||||
Name: "dccp",
|
||||
Code: P_DCCP,
|
||||
VCode: CodeToVarint(P_DCCP),
|
||||
Size: 16,
|
||||
Path: false,
|
||||
Transcoder: TranscoderPort,
|
||||
}
|
||||
protoIP6 = Protocol{
|
||||
Name: "ip6",
|
||||
Code: P_IP6,
|
||||
VCode: CodeToVarint(P_IP6),
|
||||
Size: 128,
|
||||
Transcoder: TranscoderIP6,
|
||||
}
|
||||
protoIPCIDR = Protocol{
|
||||
Name: "ipcidr",
|
||||
Code: P_IPCIDR,
|
||||
VCode: CodeToVarint(P_IPCIDR),
|
||||
Size: 8,
|
||||
Transcoder: TranscoderIPCIDR,
|
||||
}
|
||||
// these require varint
|
||||
protoIP6ZONE = Protocol{
|
||||
Name: "ip6zone",
|
||||
Code: P_IP6ZONE,
|
||||
VCode: CodeToVarint(P_IP6ZONE),
|
||||
Size: LengthPrefixedVarSize,
|
||||
Path: false,
|
||||
Transcoder: TranscoderIP6Zone,
|
||||
}
|
||||
protoSCTP = Protocol{
|
||||
Name: "sctp",
|
||||
Code: P_SCTP,
|
||||
VCode: CodeToVarint(P_SCTP),
|
||||
Size: 16,
|
||||
Transcoder: TranscoderPort,
|
||||
}
|
||||
|
||||
protoCIRCUIT = Protocol{
|
||||
Code: P_CIRCUIT,
|
||||
Size: 0,
|
||||
Name: "p2p-circuit",
|
||||
VCode: CodeToVarint(P_CIRCUIT),
|
||||
}
|
||||
|
||||
protoONION2 = Protocol{
|
||||
Name: "onion",
|
||||
Code: P_ONION,
|
||||
VCode: CodeToVarint(P_ONION),
|
||||
Size: 96,
|
||||
Transcoder: TranscoderOnion,
|
||||
}
|
||||
protoONION3 = Protocol{
|
||||
Name: "onion3",
|
||||
Code: P_ONION3,
|
||||
VCode: CodeToVarint(P_ONION3),
|
||||
Size: 296,
|
||||
Transcoder: TranscoderOnion3,
|
||||
}
|
||||
protoGARLIC64 = Protocol{
|
||||
Name: "garlic64",
|
||||
Code: P_GARLIC64,
|
||||
VCode: CodeToVarint(P_GARLIC64),
|
||||
Size: LengthPrefixedVarSize,
|
||||
Transcoder: TranscoderGarlic64,
|
||||
}
|
||||
protoGARLIC32 = Protocol{
|
||||
Name: "garlic32",
|
||||
Code: P_GARLIC32,
|
||||
VCode: CodeToVarint(P_GARLIC32),
|
||||
Size: LengthPrefixedVarSize,
|
||||
Transcoder: TranscoderGarlic32,
|
||||
}
|
||||
protoUTP = Protocol{
|
||||
Name: "utp",
|
||||
Code: P_UTP,
|
||||
VCode: CodeToVarint(P_UTP),
|
||||
}
|
||||
protoUDT = Protocol{
|
||||
Name: "udt",
|
||||
Code: P_UDT,
|
||||
VCode: CodeToVarint(P_UDT),
|
||||
}
|
||||
protoQUIC = Protocol{
|
||||
Name: "quic",
|
||||
Code: P_QUIC,
|
||||
VCode: CodeToVarint(P_QUIC),
|
||||
}
|
||||
protoQUICV1 = Protocol{
|
||||
Name: "quic-v1",
|
||||
Code: P_QUIC_V1,
|
||||
VCode: CodeToVarint(P_QUIC_V1),
|
||||
}
|
||||
protoWEBTRANSPORT = Protocol{
|
||||
Name: "webtransport",
|
||||
Code: P_WEBTRANSPORT,
|
||||
VCode: CodeToVarint(P_WEBTRANSPORT),
|
||||
}
|
||||
protoCERTHASH = Protocol{
|
||||
Name: "certhash",
|
||||
Code: P_CERTHASH,
|
||||
VCode: CodeToVarint(P_CERTHASH),
|
||||
Size: LengthPrefixedVarSize,
|
||||
Transcoder: TranscoderCertHash,
|
||||
}
|
||||
protoHTTP = Protocol{
|
||||
Name: "http",
|
||||
Code: P_HTTP,
|
||||
VCode: CodeToVarint(P_HTTP),
|
||||
}
|
||||
protoHTTPS = Protocol{
|
||||
Name: "https",
|
||||
Code: P_HTTPS,
|
||||
VCode: CodeToVarint(P_HTTPS),
|
||||
}
|
||||
protoP2P = Protocol{
|
||||
Name: "p2p",
|
||||
Code: P_P2P,
|
||||
VCode: CodeToVarint(P_P2P),
|
||||
Size: LengthPrefixedVarSize,
|
||||
Transcoder: TranscoderP2P,
|
||||
}
|
||||
protoUNIX = Protocol{
|
||||
Name: "unix",
|
||||
Code: P_UNIX,
|
||||
VCode: CodeToVarint(P_UNIX),
|
||||
Size: LengthPrefixedVarSize,
|
||||
Path: true,
|
||||
Transcoder: TranscoderUnix,
|
||||
}
|
||||
protoP2P_WEBRTC_DIRECT = Protocol{
|
||||
Name: "p2p-webrtc-direct",
|
||||
Code: P_P2P_WEBRTC_DIRECT,
|
||||
VCode: CodeToVarint(P_P2P_WEBRTC_DIRECT),
|
||||
}
|
||||
protoTLS = Protocol{
|
||||
Name: "tls",
|
||||
Code: P_TLS,
|
||||
VCode: CodeToVarint(P_TLS),
|
||||
}
|
||||
protoSNI = Protocol{
|
||||
Name: "sni",
|
||||
Size: LengthPrefixedVarSize,
|
||||
Code: P_SNI,
|
||||
VCode: CodeToVarint(P_SNI),
|
||||
Transcoder: TranscoderDns,
|
||||
}
|
||||
protoNOISE = Protocol{
|
||||
Name: "noise",
|
||||
Code: P_NOISE,
|
||||
VCode: CodeToVarint(P_NOISE),
|
||||
}
|
||||
protoPlaintextV2 = Protocol{
|
||||
Name: "plaintextv2",
|
||||
Code: P_PLAINTEXTV2,
|
||||
VCode: CodeToVarint(P_PLAINTEXTV2),
|
||||
}
|
||||
protoWS = Protocol{
|
||||
Name: "ws",
|
||||
Code: P_WS,
|
||||
VCode: CodeToVarint(P_WS),
|
||||
}
|
||||
protoWSS = Protocol{
|
||||
Name: "wss",
|
||||
Code: P_WSS,
|
||||
VCode: CodeToVarint(P_WSS),
|
||||
}
|
||||
protoWebRTCDirect = Protocol{
|
||||
Name: "webrtc-direct",
|
||||
Code: P_WEBRTC_DIRECT,
|
||||
VCode: CodeToVarint(P_WEBRTC_DIRECT),
|
||||
}
|
||||
protoWebRTC = Protocol{
|
||||
Name: "webrtc",
|
||||
Code: P_WEBRTC,
|
||||
VCode: CodeToVarint(P_WEBRTC),
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
for _, p := range []Protocol{
|
||||
protoIP4,
|
||||
protoTCP,
|
||||
protoDNS,
|
||||
protoDNS4,
|
||||
protoDNS6,
|
||||
protoDNSADDR,
|
||||
protoUDP,
|
||||
protoDCCP,
|
||||
protoIP6,
|
||||
protoIP6ZONE,
|
||||
protoIPCIDR,
|
||||
protoSCTP,
|
||||
protoCIRCUIT,
|
||||
protoONION2,
|
||||
protoONION3,
|
||||
protoGARLIC64,
|
||||
protoGARLIC32,
|
||||
protoUTP,
|
||||
protoUDT,
|
||||
protoQUIC,
|
||||
protoQUICV1,
|
||||
protoWEBTRANSPORT,
|
||||
protoCERTHASH,
|
||||
protoHTTP,
|
||||
protoHTTPS,
|
||||
protoP2P,
|
||||
protoUNIX,
|
||||
protoP2P_WEBRTC_DIRECT,
|
||||
protoTLS,
|
||||
protoSNI,
|
||||
protoNOISE,
|
||||
protoWS,
|
||||
protoWSS,
|
||||
protoPlaintextV2,
|
||||
protoWebRTCDirect,
|
||||
protoWebRTC,
|
||||
} {
|
||||
if err := AddProtocol(p); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// explicitly set both of these
|
||||
protocolsByName["p2p"] = protoP2P
|
||||
protocolsByName["ipfs"] = protoP2P
|
||||
}
|
||||
393
vendor/github.com/multiformats/go-multiaddr/transcoders.go
generated
vendored
Normal file
393
vendor/github.com/multiformats/go-multiaddr/transcoders.go
generated
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multibase"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
type Transcoder interface {
|
||||
// Validates and encodes to bytes a multiaddr that's in the string representation.
|
||||
StringToBytes(string) ([]byte, error)
|
||||
// Validates and decodes to a string a multiaddr that's in the bytes representation.
|
||||
BytesToString([]byte) (string, error)
|
||||
// Validates bytes when parsing a multiaddr that's already in the bytes representation.
|
||||
ValidateBytes([]byte) error
|
||||
}
|
||||
|
||||
func NewTranscoderFromFunctions(
|
||||
s2b func(string) ([]byte, error),
|
||||
b2s func([]byte) (string, error),
|
||||
val func([]byte) error,
|
||||
) Transcoder {
|
||||
return twrp{s2b, b2s, val}
|
||||
}
|
||||
|
||||
type twrp struct {
|
||||
strtobyte func(string) ([]byte, error)
|
||||
bytetostr func([]byte) (string, error)
|
||||
validbyte func([]byte) error
|
||||
}
|
||||
|
||||
func (t twrp) StringToBytes(s string) ([]byte, error) {
|
||||
return t.strtobyte(s)
|
||||
}
|
||||
func (t twrp) BytesToString(b []byte) (string, error) {
|
||||
return t.bytetostr(b)
|
||||
}
|
||||
|
||||
func (t twrp) ValidateBytes(b []byte) error {
|
||||
if t.validbyte == nil {
|
||||
return nil
|
||||
}
|
||||
return t.validbyte(b)
|
||||
}
|
||||
|
||||
var TranscoderIP4 = NewTranscoderFromFunctions(ip4StB, ip4BtS, nil)
|
||||
var TranscoderIP6 = NewTranscoderFromFunctions(ip6StB, ip6BtS, nil)
|
||||
var TranscoderIP6Zone = NewTranscoderFromFunctions(ip6zoneStB, ip6zoneBtS, ip6zoneVal)
|
||||
var TranscoderIPCIDR = NewTranscoderFromFunctions(ipcidrStB, ipcidrBtS, nil)
|
||||
|
||||
func ipcidrBtS(b []byte) (string, error) {
|
||||
if len(b) != 1 {
|
||||
return "", fmt.Errorf("invalid length (should be == 1)")
|
||||
}
|
||||
return strconv.Itoa(int(b[0])), nil
|
||||
}
|
||||
|
||||
func ipcidrStB(s string) ([]byte, error) {
|
||||
ipMask, err := strconv.ParseUint(s, 10, 8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte{byte(uint8(ipMask))}, nil
|
||||
}
|
||||
|
||||
func ip4StB(s string) ([]byte, error) {
|
||||
i := net.ParseIP(s).To4()
|
||||
if i == nil {
|
||||
return nil, fmt.Errorf("failed to parse ip4 addr: %s", s)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func ip6zoneStB(s string) ([]byte, error) {
|
||||
if len(s) == 0 {
|
||||
return nil, fmt.Errorf("empty ip6zone")
|
||||
}
|
||||
if strings.Contains(s, "/") {
|
||||
return nil, fmt.Errorf("IPv6 zone ID contains '/': %s", s)
|
||||
}
|
||||
return []byte(s), nil
|
||||
}
|
||||
|
||||
func ip6zoneBtS(b []byte) (string, error) {
|
||||
if len(b) == 0 {
|
||||
return "", fmt.Errorf("invalid length (should be > 0)")
|
||||
}
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
func ip6zoneVal(b []byte) error {
|
||||
if len(b) == 0 {
|
||||
return fmt.Errorf("invalid length (should be > 0)")
|
||||
}
|
||||
// Not supported as this would break multiaddrs.
|
||||
if bytes.IndexByte(b, '/') >= 0 {
|
||||
return fmt.Errorf("IPv6 zone ID contains '/': %s", string(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ip6StB(s string) ([]byte, error) {
|
||||
i := net.ParseIP(s).To16()
|
||||
if i == nil {
|
||||
return nil, fmt.Errorf("failed to parse ip6 addr: %s", s)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func ip6BtS(b []byte) (string, error) {
|
||||
ip := net.IP(b)
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
// Go fails to prepend the `::ffff:` part.
|
||||
return "::ffff:" + ip4.String(), nil
|
||||
}
|
||||
return ip.String(), nil
|
||||
}
|
||||
|
||||
func ip4BtS(b []byte) (string, error) {
|
||||
return net.IP(b).String(), nil
|
||||
}
|
||||
|
||||
var TranscoderPort = NewTranscoderFromFunctions(portStB, portBtS, nil)
|
||||
|
||||
func portStB(s string) ([]byte, error) {
|
||||
i, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse port addr: %s", err)
|
||||
}
|
||||
if i >= 65536 {
|
||||
return nil, fmt.Errorf("failed to parse port addr: %s", "greater than 65536")
|
||||
}
|
||||
b := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(b, uint16(i))
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func portBtS(b []byte) (string, error) {
|
||||
i := binary.BigEndian.Uint16(b)
|
||||
return strconv.Itoa(int(i)), nil
|
||||
}
|
||||
|
||||
var TranscoderOnion = NewTranscoderFromFunctions(onionStB, onionBtS, nil)
|
||||
|
||||
func onionStB(s string) ([]byte, error) {
|
||||
addr := strings.Split(s, ":")
|
||||
if len(addr) != 2 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s does not contain a port number", s)
|
||||
}
|
||||
|
||||
// onion address without the ".onion" substring
|
||||
if len(addr[0]) != 16 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s not a Tor onion address", s)
|
||||
}
|
||||
onionHostBytes, err := base32.StdEncoding.DecodeString(strings.ToUpper(addr[0]))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode base32 onion addr: %s %s", s, err)
|
||||
}
|
||||
|
||||
// onion port number
|
||||
i, err := strconv.Atoi(addr[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s", err)
|
||||
}
|
||||
if i >= 65536 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s", "port greater than 65536")
|
||||
}
|
||||
if i < 1 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s", "port less than 1")
|
||||
}
|
||||
|
||||
onionPortBytes := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(onionPortBytes, uint16(i))
|
||||
bytes := []byte{}
|
||||
bytes = append(bytes, onionHostBytes...)
|
||||
bytes = append(bytes, onionPortBytes...)
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
func onionBtS(b []byte) (string, error) {
|
||||
addr := strings.ToLower(base32.StdEncoding.EncodeToString(b[0:10]))
|
||||
port := binary.BigEndian.Uint16(b[10:12])
|
||||
return addr + ":" + strconv.Itoa(int(port)), nil
|
||||
}
|
||||
|
||||
var TranscoderOnion3 = NewTranscoderFromFunctions(onion3StB, onion3BtS, nil)
|
||||
|
||||
func onion3StB(s string) ([]byte, error) {
|
||||
addr := strings.Split(s, ":")
|
||||
if len(addr) != 2 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s does not contain a port number", s)
|
||||
}
|
||||
|
||||
// onion address without the ".onion" substring
|
||||
if len(addr[0]) != 56 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s not a Tor onionv3 address. len == %d", s, len(addr[0]))
|
||||
}
|
||||
onionHostBytes, err := base32.StdEncoding.DecodeString(strings.ToUpper(addr[0]))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode base32 onion addr: %s %s", s, err)
|
||||
}
|
||||
|
||||
// onion port number
|
||||
i, err := strconv.Atoi(addr[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s", err)
|
||||
}
|
||||
if i >= 65536 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s", "port greater than 65536")
|
||||
}
|
||||
if i < 1 {
|
||||
return nil, fmt.Errorf("failed to parse onion addr: %s", "port less than 1")
|
||||
}
|
||||
|
||||
onionPortBytes := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(onionPortBytes, uint16(i))
|
||||
bytes := []byte{}
|
||||
bytes = append(bytes, onionHostBytes[0:35]...)
|
||||
bytes = append(bytes, onionPortBytes...)
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
func onion3BtS(b []byte) (string, error) {
|
||||
addr := strings.ToLower(base32.StdEncoding.EncodeToString(b[0:35]))
|
||||
port := binary.BigEndian.Uint16(b[35:37])
|
||||
str := addr + ":" + strconv.Itoa(int(port))
|
||||
return str, nil
|
||||
}
|
||||
|
||||
var TranscoderGarlic64 = NewTranscoderFromFunctions(garlic64StB, garlic64BtS, garlic64Validate)
|
||||
|
||||
// i2p uses an alternate character set for base64 addresses. This returns an appropriate encoder.
|
||||
var garlicBase64Encoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~")
|
||||
|
||||
func garlic64StB(s string) ([]byte, error) {
|
||||
// i2p base64 address will be between 516 and 616 characters long, depending on
|
||||
// certificate type
|
||||
if len(s) < 516 || len(s) > 616 {
|
||||
return nil, fmt.Errorf("failed to parse garlic addr: %s not an i2p base64 address. len: %d", s, len(s))
|
||||
}
|
||||
garlicHostBytes, err := garlicBase64Encoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode base64 i2p addr: %s %s", s, err)
|
||||
}
|
||||
|
||||
return garlicHostBytes, nil
|
||||
}
|
||||
|
||||
func garlic64BtS(b []byte) (string, error) {
|
||||
if err := garlic64Validate(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
addr := garlicBase64Encoding.EncodeToString(b)
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func garlic64Validate(b []byte) error {
|
||||
// A garlic64 address will always be greater than 386 bytes long when encoded.
|
||||
if len(b) < 386 {
|
||||
return fmt.Errorf("failed to validate garlic addr: %s not an i2p base64 address. len: %d", b, len(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var TranscoderGarlic32 = NewTranscoderFromFunctions(garlic32StB, garlic32BtS, garlic32Validate)
|
||||
|
||||
var garlicBase32Encoding = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
|
||||
|
||||
func garlic32StB(s string) ([]byte, error) {
|
||||
// an i2p base32 address with a length of greater than 55 characters is
|
||||
// using an Encrypted Leaseset v2. all other base32 addresses will always be
|
||||
// exactly 52 characters
|
||||
if len(s) < 55 && len(s) != 52 {
|
||||
return nil, fmt.Errorf("failed to parse garlic addr: %s not a i2p base32 address. len: %d", s, len(s))
|
||||
}
|
||||
for len(s)%8 != 0 {
|
||||
s += "="
|
||||
}
|
||||
garlicHostBytes, err := garlicBase32Encoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode base32 garlic addr: %s, err: %v len: %v", s, err, len(s))
|
||||
}
|
||||
return garlicHostBytes, nil
|
||||
}
|
||||
|
||||
func garlic32BtS(b []byte) (string, error) {
|
||||
if err := garlic32Validate(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimRight(garlicBase32Encoding.EncodeToString(b), "="), nil
|
||||
}
|
||||
|
||||
func garlic32Validate(b []byte) error {
|
||||
// an i2p base64 for an Encrypted Leaseset v2 will be at least 35 bytes
|
||||
// long other than that, they will be exactly 32 bytes
|
||||
if len(b) < 35 && len(b) != 32 {
|
||||
return fmt.Errorf("failed to validate garlic addr: %s not an i2p base32 address. len: %d", b, len(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var TranscoderP2P = NewTranscoderFromFunctions(p2pStB, p2pBtS, p2pVal)
|
||||
|
||||
// The encoded peer ID can either be a CID of a key or a raw multihash (identity
|
||||
// or sha256-256).
|
||||
func p2pStB(s string) ([]byte, error) {
|
||||
// check if the address is a base58 encoded sha256 or identity multihash
|
||||
if strings.HasPrefix(s, "Qm") || strings.HasPrefix(s, "1") {
|
||||
m, err := mh.FromB58String(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse p2p addr: %s %s", s, err)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// check if the address is a CID
|
||||
c, err := cid.Decode(s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse p2p addr: %s %s", s, err)
|
||||
}
|
||||
|
||||
if ty := c.Type(); ty == cid.Libp2pKey {
|
||||
return c.Hash(), nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to parse p2p addr: %s has the invalid codec %d", s, ty)
|
||||
}
|
||||
}
|
||||
|
||||
func p2pVal(b []byte) error {
|
||||
_, err := mh.Cast(b)
|
||||
return err
|
||||
}
|
||||
|
||||
func p2pBtS(b []byte) (string, error) {
|
||||
m, err := mh.Cast(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return m.B58String(), nil
|
||||
}
|
||||
|
||||
var TranscoderUnix = NewTranscoderFromFunctions(unixStB, unixBtS, nil)
|
||||
|
||||
func unixStB(s string) ([]byte, error) {
|
||||
return []byte(s), nil
|
||||
}
|
||||
|
||||
func unixBtS(b []byte) (string, error) {
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
var TranscoderDns = NewTranscoderFromFunctions(dnsStB, dnsBtS, dnsVal)
|
||||
|
||||
func dnsVal(b []byte) error {
|
||||
if bytes.IndexByte(b, '/') >= 0 {
|
||||
return fmt.Errorf("domain name %q contains a slash", string(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func dnsStB(s string) ([]byte, error) {
|
||||
return []byte(s), nil
|
||||
}
|
||||
|
||||
func dnsBtS(b []byte) (string, error) {
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
var TranscoderCertHash = NewTranscoderFromFunctions(certHashStB, certHashBtS, nil)
|
||||
|
||||
func certHashStB(s string) ([]byte, error) {
|
||||
_, data, err := multibase.Decode(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := mh.Decode(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func certHashBtS(b []byte) (string, error) {
|
||||
return multibase.Encode(multibase.Base64url, b)
|
||||
}
|
||||
180
vendor/github.com/multiformats/go-multiaddr/util.go
generated
vendored
Normal file
180
vendor/github.com/multiformats/go-multiaddr/util.go
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
package multiaddr
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Split returns the sub-address portions of a multiaddr.
|
||||
func Split(m Multiaddr) []Multiaddr {
|
||||
if _, ok := m.(*Component); ok {
|
||||
return []Multiaddr{m}
|
||||
}
|
||||
var addrs []Multiaddr
|
||||
ForEach(m, func(c Component) bool {
|
||||
addrs = append(addrs, &c)
|
||||
return true
|
||||
})
|
||||
return addrs
|
||||
}
|
||||
|
||||
// Join returns a combination of addresses.
|
||||
func Join(ms ...Multiaddr) Multiaddr {
|
||||
switch len(ms) {
|
||||
case 0:
|
||||
// empty multiaddr, unfortunately, we have callers that rely on
|
||||
// this contract.
|
||||
return &multiaddr{}
|
||||
case 1:
|
||||
return ms[0]
|
||||
}
|
||||
|
||||
length := 0
|
||||
bs := make([][]byte, len(ms))
|
||||
for i, m := range ms {
|
||||
bs[i] = m.Bytes()
|
||||
length += len(bs[i])
|
||||
}
|
||||
|
||||
bidx := 0
|
||||
b := make([]byte, length)
|
||||
for _, mb := range bs {
|
||||
bidx += copy(b[bidx:], mb)
|
||||
}
|
||||
return &multiaddr{bytes: b}
|
||||
}
|
||||
|
||||
// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
|
||||
func Cast(b []byte) Multiaddr {
|
||||
m, err := NewMultiaddrBytes(b)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("multiaddr failed to parse: %s", err))
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// StringCast like Cast, but parses a string. Will also panic if it fails to parse.
|
||||
func StringCast(s string) Multiaddr {
|
||||
m, err := NewMultiaddr(s)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("multiaddr failed to parse: %s", err))
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// SplitFirst returns the first component and the rest of the multiaddr.
|
||||
func SplitFirst(m Multiaddr) (*Component, Multiaddr) {
|
||||
// Shortcut if we already have a component
|
||||
if c, ok := m.(*Component); ok {
|
||||
return c, nil
|
||||
}
|
||||
|
||||
b := m.Bytes()
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
n, c, err := readComponent(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(b) == n {
|
||||
return &c, nil
|
||||
}
|
||||
return &c, &multiaddr{b[n:]}
|
||||
}
|
||||
|
||||
// SplitLast returns the rest of the multiaddr and the last component.
|
||||
func SplitLast(m Multiaddr) (Multiaddr, *Component) {
|
||||
// Shortcut if we already have a component
|
||||
if c, ok := m.(*Component); ok {
|
||||
return nil, c
|
||||
}
|
||||
|
||||
b := m.Bytes()
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var (
|
||||
c Component
|
||||
err error
|
||||
offset int
|
||||
)
|
||||
for {
|
||||
var n int
|
||||
n, c, err = readComponent(b[offset:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(b) == n+offset {
|
||||
// Reached end
|
||||
if offset == 0 {
|
||||
// Only one component
|
||||
return nil, &c
|
||||
}
|
||||
return &multiaddr{b[:offset]}, &c
|
||||
}
|
||||
offset += n
|
||||
}
|
||||
}
|
||||
|
||||
// SplitFunc splits the multiaddr when the callback first returns true. The
|
||||
// component on which the callback first returns will be included in the
|
||||
// *second* multiaddr.
|
||||
func SplitFunc(m Multiaddr, cb func(Component) bool) (Multiaddr, Multiaddr) {
|
||||
// Shortcut if we already have a component
|
||||
if c, ok := m.(*Component); ok {
|
||||
if cb(*c) {
|
||||
return nil, m
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
b := m.Bytes()
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var (
|
||||
c Component
|
||||
err error
|
||||
offset int
|
||||
)
|
||||
for offset < len(b) {
|
||||
var n int
|
||||
n, c, err = readComponent(b[offset:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if cb(c) {
|
||||
break
|
||||
}
|
||||
offset += n
|
||||
}
|
||||
switch offset {
|
||||
case 0:
|
||||
return nil, m
|
||||
case len(b):
|
||||
return m, nil
|
||||
default:
|
||||
return &multiaddr{b[:offset]}, &multiaddr{b[offset:]}
|
||||
}
|
||||
}
|
||||
|
||||
// ForEach walks over the multiaddr, component by component.
|
||||
//
|
||||
// This function iterates over components *by value* to avoid allocating.
|
||||
func ForEach(m Multiaddr, cb func(c Component) bool) {
|
||||
// Shortcut if we already have a component
|
||||
if c, ok := m.(*Component); ok {
|
||||
cb(*c)
|
||||
return
|
||||
}
|
||||
|
||||
b := m.Bytes()
|
||||
for len(b) > 0 {
|
||||
n, c, err := readComponent(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !cb(c) {
|
||||
return
|
||||
}
|
||||
b = b[n:]
|
||||
}
|
||||
}
|
||||
27
vendor/github.com/multiformats/go-multiaddr/varint.go
generated
vendored
Normal file
27
vendor/github.com/multiformats/go-multiaddr/varint.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
// CodeToVarint converts an integer to a varint-encoded []byte
|
||||
func CodeToVarint(num int) []byte {
|
||||
if num < 0 || num > math.MaxInt32 {
|
||||
panic("invalid code")
|
||||
}
|
||||
return varint.ToUvarint(uint64(num))
|
||||
}
|
||||
|
||||
func ReadVarintCode(b []byte) (int, int, error) {
|
||||
code, n, err := varint.FromUvarint(b)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if code > math.MaxInt32 {
|
||||
// we only allow 32bit codes.
|
||||
return 0, 0, varint.ErrOverflow
|
||||
}
|
||||
return int(code), n, err
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-multiaddr/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multiaddr/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.12.0"
|
||||
}
|
||||
1
vendor/github.com/multiformats/go-multibase/.codecov.yml
generated
vendored
Normal file
1
vendor/github.com/multiformats/go-multibase/.codecov.yml
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
comment: off
|
||||
3
vendor/github.com/multiformats/go-multibase/.gitignore
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multibase/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.swp
|
||||
|
||||
multibase-conv/multibase-conv
|
||||
3
vendor/github.com/multiformats/go-multibase/.gitmodules
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multibase/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "spec"]
|
||||
path = spec
|
||||
url = https://github.com/multiformats/multibase.git
|
||||
21
vendor/github.com/multiformats/go-multibase/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multibase/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Protocol Labs Inc.
|
||||
|
||||
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.
|
||||
7
vendor/github.com/multiformats/go-multibase/Makefile
generated
vendored
Normal file
7
vendor/github.com/multiformats/go-multibase/Makefile
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
test: deps
|
||||
go test -count=1 -race -v ./...
|
||||
|
||||
export IPFS_API ?= v04x.ipfs.io
|
||||
|
||||
deps:
|
||||
go get -t ./...
|
||||
31
vendor/github.com/multiformats/go-multibase/README.md
generated
vendored
Normal file
31
vendor/github.com/multiformats/go-multibase/README.md
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# go-multibase
|
||||
|
||||
[](http://ipn.io)
|
||||
[](https://github.com/multiformats/multiformats)
|
||||
[](https://webchat.freenode.net/?channels=%23ipfs)
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
[](https://travis-ci.org/multiformats/go-multibase)
|
||||
[](https://codecov.io/github/multiformats/go-multibase?branch=master)
|
||||
|
||||
> Implementation of [multibase](https://github.com/multiformats/multibase) -self identifying base encodings- in Go.
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
`go-multibase` is a standard Go module which can be installed with:
|
||||
|
||||
```sh
|
||||
go get github.com/multiformats/go-multibase
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multibase/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © 2016 Protocol Labs Inc.
|
||||
21
vendor/github.com/multiformats/go-multibase/base16.go
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multibase/base16.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package multibase
|
||||
|
||||
func hexEncodeToStringUpper(src []byte) string {
|
||||
dst := make([]byte, len(src)*2)
|
||||
hexEncodeUpper(dst, src)
|
||||
return string(dst)
|
||||
}
|
||||
|
||||
var hexTableUppers = [16]byte{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F',
|
||||
}
|
||||
|
||||
func hexEncodeUpper(dst, src []byte) int {
|
||||
for i, v := range src {
|
||||
dst[i*2] = hexTableUppers[v>>4]
|
||||
dst[i*2+1] = hexTableUppers[v&0x0f]
|
||||
}
|
||||
|
||||
return len(src) * 2
|
||||
}
|
||||
52
vendor/github.com/multiformats/go-multibase/base2.go
generated
vendored
Normal file
52
vendor/github.com/multiformats/go-multibase/base2.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package multibase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// binaryEncodeToString takes an array of bytes and returns
|
||||
// multibase binary representation
|
||||
func binaryEncodeToString(src []byte) string {
|
||||
dst := make([]byte, len(src)*8)
|
||||
encodeBinary(dst, src)
|
||||
return string(dst)
|
||||
}
|
||||
|
||||
// encodeBinary takes the src and dst bytes and converts each
|
||||
// byte to their binary rep using power reduction method
|
||||
func encodeBinary(dst []byte, src []byte) {
|
||||
for i, b := range src {
|
||||
for j := 0; j < 8; j++ {
|
||||
if b&(1<<uint(7-j)) == 0 {
|
||||
dst[i*8+j] = '0'
|
||||
} else {
|
||||
dst[i*8+j] = '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// decodeBinaryString takes multibase binary representation
|
||||
// and returns a byte array
|
||||
func decodeBinaryString(s string) ([]byte, error) {
|
||||
if len(s)&7 != 0 {
|
||||
// prepend the padding
|
||||
s = strings.Repeat("0", 8-len(s)&7) + s
|
||||
}
|
||||
|
||||
data := make([]byte, len(s)>>3)
|
||||
|
||||
for i, dstIndex := 0, 0; i < len(s); i = i + 8 {
|
||||
value, err := strconv.ParseInt(s[i:i+8], 2, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while conversion: %s", err)
|
||||
}
|
||||
|
||||
data[dstIndex] = byte(value)
|
||||
dstIndex++
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
95
vendor/github.com/multiformats/go-multibase/base256emoji.go
generated
vendored
Normal file
95
vendor/github.com/multiformats/go-multibase/base256emoji.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
package multibase
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var base256emojiTable = [256]rune{
|
||||
// Curated list, this is just a list of things that *somwhat* are related to our comunity
|
||||
'🚀', '🪐', '☄', '🛰', '🌌', // Space
|
||||
'🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘', // Moon
|
||||
'🌍', '🌏', '🌎', // Our Home, for now (earth)
|
||||
'🐉', // Dragon!!!
|
||||
'☀', // Our Garden, for now (sol)
|
||||
'💻', '🖥', '💾', '💿', // Computer
|
||||
// The rest is completed from https://home.unicode.org/emoji/emoji-frequency/ at the time of creation (december 2021) (the data is from 2019), most used first until we reach 256.
|
||||
// We exclude modifier based emojies (such as flags) as they are bigger than one single codepoint.
|
||||
// Some other emojies were removed adhoc for various reasons.
|
||||
'😂', '❤', '😍', '🤣', '😊', '🙏', '💕', '😭', '😘', '👍',
|
||||
'😅', '👏', '😁', '🔥', '🥰', '💔', '💖', '💙', '😢', '🤔',
|
||||
'😆', '🙄', '💪', '😉', '☺', '👌', '🤗', '💜', '😔', '😎',
|
||||
'😇', '🌹', '🤦', '🎉', '💞', '✌', '✨', '🤷', '😱', '😌',
|
||||
'🌸', '🙌', '😋', '💗', '💚', '😏', '💛', '🙂', '💓', '🤩',
|
||||
'😄', '😀', '🖤', '😃', '💯', '🙈', '👇', '🎶', '😒', '🤭',
|
||||
'❣', '😜', '💋', '👀', '😪', '😑', '💥', '🙋', '😞', '😩',
|
||||
'😡', '🤪', '👊', '🥳', '😥', '🤤', '👉', '💃', '😳', '✋',
|
||||
'😚', '😝', '😴', '🌟', '😬', '🙃', '🍀', '🌷', '😻', '😓',
|
||||
'⭐', '✅', '🥺', '🌈', '😈', '🤘', '💦', '✔', '😣', '🏃',
|
||||
'💐', '☹', '🎊', '💘', '😠', '☝', '😕', '🌺', '🎂', '🌻',
|
||||
'😐', '🖕', '💝', '🙊', '😹', '🗣', '💫', '💀', '👑', '🎵',
|
||||
'🤞', '😛', '🔴', '😤', '🌼', '😫', '⚽', '🤙', '☕', '🏆',
|
||||
'🤫', '👈', '😮', '🙆', '🍻', '🍃', '🐶', '💁', '😲', '🌿',
|
||||
'🧡', '🎁', '⚡', '🌞', '🎈', '❌', '✊', '👋', '😰', '🤨',
|
||||
'😶', '🤝', '🚶', '💰', '🍓', '💢', '🤟', '🙁', '🚨', '💨',
|
||||
'🤬', '✈', '🎀', '🍺', '🤓', '😙', '💟', '🌱', '😖', '👶',
|
||||
'🥴', '▶', '➡', '❓', '💎', '💸', '⬇', '😨', '🌚', '🦋',
|
||||
'😷', '🕺', '⚠', '🙅', '😟', '😵', '👎', '🤲', '🤠', '🤧',
|
||||
'📌', '🔵', '💅', '🧐', '🐾', '🍒', '😗', '🤑', '🌊', '🤯',
|
||||
'🐷', '☎', '💧', '😯', '💆', '👆', '🎤', '🙇', '🍑', '❄',
|
||||
'🌴', '💣', '🐸', '💌', '📍', '🥀', '🤢', '👅', '💡', '💩',
|
||||
'👐', '📸', '👻', '🤐', '🤮', '🎼', '🥵', '🚩', '🍎', '🍊',
|
||||
'👼', '💍', '📣', '🥂',
|
||||
}
|
||||
|
||||
var base256emojiReverseTable map[rune]byte
|
||||
|
||||
func init() {
|
||||
base256emojiReverseTable = make(map[rune]byte, len(base256emojiTable))
|
||||
for i, v := range base256emojiTable {
|
||||
base256emojiReverseTable[v] = byte(i)
|
||||
}
|
||||
}
|
||||
|
||||
func base256emojiEncode(in []byte) string {
|
||||
var l int
|
||||
for _, v := range in {
|
||||
l += utf8.RuneLen(base256emojiTable[v])
|
||||
}
|
||||
var out strings.Builder
|
||||
out.Grow(l)
|
||||
for _, v := range in {
|
||||
out.WriteRune(base256emojiTable[v])
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
|
||||
type base256emojiCorruptInputError struct {
|
||||
index int
|
||||
char rune
|
||||
}
|
||||
|
||||
func (e base256emojiCorruptInputError) Error() string {
|
||||
return "illegal base256emoji data at input byte " + strconv.FormatInt(int64(e.index), 10) + ", char: '" + string(e.char) + "'"
|
||||
}
|
||||
|
||||
func (e base256emojiCorruptInputError) String() string {
|
||||
return e.Error()
|
||||
}
|
||||
|
||||
func base256emojiDecode(in string) ([]byte, error) {
|
||||
out := make([]byte, utf8.RuneCountInString(in))
|
||||
var stri int
|
||||
for i := 0; len(in) > 0; i++ {
|
||||
r, n := utf8.DecodeRuneInString(in)
|
||||
in = in[n:]
|
||||
var ok bool
|
||||
out[i], ok = base256emojiReverseTable[r]
|
||||
if !ok {
|
||||
return nil, base256emojiCorruptInputError{stri, r}
|
||||
}
|
||||
stri += n
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
17
vendor/github.com/multiformats/go-multibase/base32.go
generated
vendored
Normal file
17
vendor/github.com/multiformats/go-multibase/base32.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package multibase
|
||||
|
||||
import (
|
||||
b32 "github.com/multiformats/go-base32"
|
||||
)
|
||||
|
||||
var base32StdLowerPad = b32.NewEncodingCI("abcdefghijklmnopqrstuvwxyz234567")
|
||||
var base32StdLowerNoPad = base32StdLowerPad.WithPadding(b32.NoPadding)
|
||||
|
||||
var base32StdUpperPad = b32.NewEncodingCI("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")
|
||||
var base32StdUpperNoPad = base32StdUpperPad.WithPadding(b32.NoPadding)
|
||||
|
||||
var base32HexLowerPad = b32.NewEncodingCI("0123456789abcdefghijklmnopqrstuv")
|
||||
var base32HexLowerNoPad = base32HexLowerPad.WithPadding(b32.NoPadding)
|
||||
|
||||
var base32HexUpperPad = b32.NewEncodingCI("0123456789ABCDEFGHIJKLMNOPQRSTUV")
|
||||
var base32HexUpperNoPad = base32HexUpperPad.WithPadding(b32.NoPadding)
|
||||
65
vendor/github.com/multiformats/go-multibase/encoder.go
generated
vendored
Normal file
65
vendor/github.com/multiformats/go-multibase/encoder.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
package multibase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Encoder is a multibase encoding that is verified to be supported and
|
||||
// supports an Encode method that does not return an error
|
||||
type Encoder struct {
|
||||
enc Encoding
|
||||
}
|
||||
|
||||
// NewEncoder create a new Encoder from an Encoding
|
||||
func NewEncoder(base Encoding) (Encoder, error) {
|
||||
_, ok := EncodingToStr[base]
|
||||
if !ok {
|
||||
return Encoder{-1}, fmt.Errorf("unsupported multibase encoding: %d", base)
|
||||
}
|
||||
return Encoder{base}, nil
|
||||
}
|
||||
|
||||
// MustNewEncoder is like NewEncoder but will panic if the encoding is
|
||||
// invalid.
|
||||
func MustNewEncoder(base Encoding) Encoder {
|
||||
_, ok := EncodingToStr[base]
|
||||
if !ok {
|
||||
panic("Unsupported multibase encoding")
|
||||
}
|
||||
return Encoder{base}
|
||||
}
|
||||
|
||||
// EncoderByName creates an encoder from a string, the string can
|
||||
// either be the multibase name or single character multibase prefix
|
||||
func EncoderByName(str string) (Encoder, error) {
|
||||
var base Encoding
|
||||
var ok bool
|
||||
if len(str) == 0 {
|
||||
return Encoder{-1}, fmt.Errorf("empty multibase encoding")
|
||||
} else if utf8.RuneCountInString(str) == 1 {
|
||||
r, _ := utf8.DecodeRuneInString(str)
|
||||
base = Encoding(r)
|
||||
_, ok = EncodingToStr[base]
|
||||
} else {
|
||||
base, ok = Encodings[str]
|
||||
}
|
||||
if !ok {
|
||||
return Encoder{-1}, fmt.Errorf("unsupported multibase encoding: %s", str)
|
||||
}
|
||||
return Encoder{base}, nil
|
||||
}
|
||||
|
||||
func (p Encoder) Encoding() Encoding {
|
||||
return p.enc
|
||||
}
|
||||
|
||||
// Encode encodes the multibase using the given Encoder.
|
||||
func (p Encoder) Encode(data []byte) string {
|
||||
str, err := Encode(p.enc, data)
|
||||
if err != nil {
|
||||
// should not happen
|
||||
panic(err)
|
||||
}
|
||||
return str
|
||||
}
|
||||
194
vendor/github.com/multiformats/go-multibase/multibase.go
generated
vendored
Normal file
194
vendor/github.com/multiformats/go-multibase/multibase.go
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
package multibase
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
|
||||
b58 "github.com/mr-tron/base58/base58"
|
||||
b32 "github.com/multiformats/go-base32"
|
||||
b36 "github.com/multiformats/go-base36"
|
||||
)
|
||||
|
||||
// Encoding identifies the type of base-encoding that a multibase is carrying.
|
||||
type Encoding int
|
||||
|
||||
// These are the encodings specified in the standard, not are all
|
||||
// supported yet
|
||||
const (
|
||||
Identity = 0x00
|
||||
Base2 = '0'
|
||||
Base8 = '7'
|
||||
Base10 = '9'
|
||||
Base16 = 'f'
|
||||
Base16Upper = 'F'
|
||||
Base32 = 'b'
|
||||
Base32Upper = 'B'
|
||||
Base32pad = 'c'
|
||||
Base32padUpper = 'C'
|
||||
Base32hex = 'v'
|
||||
Base32hexUpper = 'V'
|
||||
Base32hexPad = 't'
|
||||
Base32hexPadUpper = 'T'
|
||||
Base36 = 'k'
|
||||
Base36Upper = 'K'
|
||||
Base58BTC = 'z'
|
||||
Base58Flickr = 'Z'
|
||||
Base64 = 'm'
|
||||
Base64url = 'u'
|
||||
Base64pad = 'M'
|
||||
Base64urlPad = 'U'
|
||||
Base256Emoji = '🚀'
|
||||
)
|
||||
|
||||
// EncodingToStr is a map of the supported encoding, unsupported encoding
|
||||
// specified in standard are left out
|
||||
var EncodingToStr = map[Encoding]string{
|
||||
0x00: "identity",
|
||||
'0': "base2",
|
||||
'f': "base16",
|
||||
'F': "base16upper",
|
||||
'b': "base32",
|
||||
'B': "base32upper",
|
||||
'c': "base32pad",
|
||||
'C': "base32padupper",
|
||||
'v': "base32hex",
|
||||
'V': "base32hexupper",
|
||||
't': "base32hexpad",
|
||||
'T': "base32hexpadupper",
|
||||
'k': "base36",
|
||||
'K': "base36upper",
|
||||
'z': "base58btc",
|
||||
'Z': "base58flickr",
|
||||
'm': "base64",
|
||||
'u': "base64url",
|
||||
'M': "base64pad",
|
||||
'U': "base64urlpad",
|
||||
Base256Emoji: "base256emoji",
|
||||
}
|
||||
|
||||
var Encodings = map[string]Encoding{}
|
||||
|
||||
func init() {
|
||||
for e, n := range EncodingToStr {
|
||||
Encodings[n] = e
|
||||
}
|
||||
}
|
||||
|
||||
// ErrUnsupportedEncoding is returned when the selected encoding is not known or
|
||||
// implemented.
|
||||
var ErrUnsupportedEncoding = fmt.Errorf("selected encoding not supported")
|
||||
|
||||
// Encode encodes a given byte slice with the selected encoding and returns a
|
||||
// multibase string (<encoding><base-encoded-string>). It will return
|
||||
// an error if the selected base is not known.
|
||||
func Encode(base Encoding, data []byte) (string, error) {
|
||||
switch base {
|
||||
case Identity:
|
||||
// 0x00 inside a string is OK in golang and causes no problems with the length calculation.
|
||||
return string(rune(Identity)) + string(data), nil
|
||||
case Base2:
|
||||
return string(Base2) + binaryEncodeToString(data), nil
|
||||
case Base16:
|
||||
return string(Base16) + hex.EncodeToString(data), nil
|
||||
case Base16Upper:
|
||||
return string(Base16Upper) + hexEncodeToStringUpper(data), nil
|
||||
case Base32:
|
||||
return string(Base32) + base32StdLowerNoPad.EncodeToString(data), nil
|
||||
case Base32Upper:
|
||||
return string(Base32Upper) + base32StdUpperNoPad.EncodeToString(data), nil
|
||||
case Base32hex:
|
||||
return string(Base32hex) + base32HexLowerNoPad.EncodeToString(data), nil
|
||||
case Base32hexUpper:
|
||||
return string(Base32hexUpper) + base32HexUpperNoPad.EncodeToString(data), nil
|
||||
case Base32pad:
|
||||
return string(Base32pad) + base32StdLowerPad.EncodeToString(data), nil
|
||||
case Base32padUpper:
|
||||
return string(Base32padUpper) + base32StdUpperPad.EncodeToString(data), nil
|
||||
case Base32hexPad:
|
||||
return string(Base32hexPad) + base32HexLowerPad.EncodeToString(data), nil
|
||||
case Base32hexPadUpper:
|
||||
return string(Base32hexPadUpper) + base32HexUpperPad.EncodeToString(data), nil
|
||||
case Base36:
|
||||
return string(Base36) + b36.EncodeToStringLc(data), nil
|
||||
case Base36Upper:
|
||||
return string(Base36Upper) + b36.EncodeToStringUc(data), nil
|
||||
case Base58BTC:
|
||||
return string(Base58BTC) + b58.EncodeAlphabet(data, b58.BTCAlphabet), nil
|
||||
case Base58Flickr:
|
||||
return string(Base58Flickr) + b58.EncodeAlphabet(data, b58.FlickrAlphabet), nil
|
||||
case Base64pad:
|
||||
return string(Base64pad) + base64.StdEncoding.EncodeToString(data), nil
|
||||
case Base64urlPad:
|
||||
return string(Base64urlPad) + base64.URLEncoding.EncodeToString(data), nil
|
||||
case Base64url:
|
||||
return string(Base64url) + base64.RawURLEncoding.EncodeToString(data), nil
|
||||
case Base64:
|
||||
return string(Base64) + base64.RawStdEncoding.EncodeToString(data), nil
|
||||
case Base256Emoji:
|
||||
return string(Base256Emoji) + base256emojiEncode(data), nil
|
||||
default:
|
||||
return "", ErrUnsupportedEncoding
|
||||
}
|
||||
}
|
||||
|
||||
// Decode takes a multibase string and decodes into a bytes buffer.
|
||||
// It will return an error if the selected base is not known.
|
||||
func Decode(data string) (Encoding, []byte, error) {
|
||||
if len(data) == 0 {
|
||||
return 0, nil, fmt.Errorf("cannot decode multibase for zero length string")
|
||||
}
|
||||
|
||||
r, _ := utf8.DecodeRuneInString(data)
|
||||
enc := Encoding(r)
|
||||
|
||||
switch enc {
|
||||
case Identity:
|
||||
return Identity, []byte(data[1:]), nil
|
||||
case Base2:
|
||||
bytes, err := decodeBinaryString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base16, Base16Upper:
|
||||
bytes, err := hex.DecodeString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base32, Base32Upper:
|
||||
bytes, err := b32.RawStdEncoding.DecodeString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base32hex, Base32hexUpper:
|
||||
bytes, err := b32.RawHexEncoding.DecodeString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base32pad, Base32padUpper:
|
||||
bytes, err := b32.StdEncoding.DecodeString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base32hexPad, Base32hexPadUpper:
|
||||
bytes, err := b32.HexEncoding.DecodeString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base36, Base36Upper:
|
||||
bytes, err := b36.DecodeString(data[1:])
|
||||
return enc, bytes, err
|
||||
case Base58BTC:
|
||||
bytes, err := b58.DecodeAlphabet(data[1:], b58.BTCAlphabet)
|
||||
return Base58BTC, bytes, err
|
||||
case Base58Flickr:
|
||||
bytes, err := b58.DecodeAlphabet(data[1:], b58.FlickrAlphabet)
|
||||
return Base58Flickr, bytes, err
|
||||
case Base64pad:
|
||||
bytes, err := base64.StdEncoding.DecodeString(data[1:])
|
||||
return Base64pad, bytes, err
|
||||
case Base64urlPad:
|
||||
bytes, err := base64.URLEncoding.DecodeString(data[1:])
|
||||
return Base64urlPad, bytes, err
|
||||
case Base64:
|
||||
bytes, err := base64.RawStdEncoding.DecodeString(data[1:])
|
||||
return Base64, bytes, err
|
||||
case Base64url:
|
||||
bytes, err := base64.RawURLEncoding.DecodeString(data[1:])
|
||||
return Base64url, bytes, err
|
||||
case Base256Emoji:
|
||||
bytes, err := base256emojiDecode(data[4:])
|
||||
return Base256Emoji, bytes, err
|
||||
default:
|
||||
return -1, nil, ErrUnsupportedEncoding
|
||||
}
|
||||
}
|
||||
10
vendor/github.com/multiformats/go-multibase/package.json
generated
vendored
Normal file
10
vendor/github.com/multiformats/go-multibase/package.json
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"bugs": {
|
||||
"url": "https://github.com/multiformats/go-multibase"
|
||||
},
|
||||
"language": "go",
|
||||
"license": "",
|
||||
"name": "go-multibase",
|
||||
"version": "0.3.0"
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-multibase/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multibase/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.2.0"
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-multicodec/.gitmodules
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multicodec/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "multicodec"]
|
||||
path = multicodec
|
||||
url = https://github.com/multiformats/multicodec
|
||||
14
vendor/github.com/multiformats/go-multicodec/LICENSE
generated
vendored
Normal file
14
vendor/github.com/multiformats/go-multicodec/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
This library is dual-licensed under either of Apache 2.0 or MIT terms:
|
||||
|
||||
- Apache-2.0 Software License: https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
- MIT Software License: https://opensource.org/licenses/MIT
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the terms listed in this notice is distributed on
|
||||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
either express or implied. See each License for the specific language
|
||||
governing permissions and limitations under that License.
|
||||
|
||||
<!--- SPDX-License-Identifier: Apache-2.0 OR MIT -->
|
||||
`SPDX-License-Identifier: Apache-2.0 OR MIT`
|
||||
7
vendor/github.com/multiformats/go-multicodec/LICENSE-APACHE
generated
vendored
Normal file
7
vendor/github.com/multiformats/go-multicodec/LICENSE-APACHE
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Copyright (c) 2020 The Contributors
|
||||
|
||||
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.
|
||||
21
vendor/github.com/multiformats/go-multicodec/LICENSE-MIT
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multicodec/LICENSE-MIT
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 The Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
109
vendor/github.com/multiformats/go-multicodec/README.md
generated
vendored
Normal file
109
vendor/github.com/multiformats/go-multicodec/README.md
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
# go-multicodec
|
||||
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
|
||||
> Generated Go constants for the [multicodec table](https://github.com/multiformats/multicodec) used by the [multiformats](https://github.com/multiformats/multiformats) projects.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Type](#type)
|
||||
- [Usage](#usage)
|
||||
- [Importing Code constant](#importing-code-constant)
|
||||
- [Code from string](#code-from-string)
|
||||
- [Code from uint64](#code-from-uint64)
|
||||
- [Generator](#generator)
|
||||
- [With old table.csv](#with-old-tablecsv)
|
||||
- [With updated table.csv](#with-updated-tablecsv)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
`go-multicodec` is a standard Go module:
|
||||
|
||||
go get github.com/multiformats/go-multicodec
|
||||
|
||||
|
||||
## Type
|
||||
|
||||
`Code` describes an integer reserved in the multicodec table, defined at [multiformats/multicodec/table.csv](https://github.com/multiformats/multicodec/blob/master/table.csv).
|
||||
|
||||
```go
|
||||
type Code uint64
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Importing Code constant
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/multiformats/go-multicodec"
|
||||
|
||||
func main() {
|
||||
code := multicodec.Sha2_256 // Code
|
||||
name := multicodec.Sha2_256.String()
|
||||
}
|
||||
```
|
||||
|
||||
The corresponding `name` value for each codec from the [multicodecs table](https://raw.githubusercontent.com/multiformats/multicodec/master/table.csv) can be accessed via its `String` method. For example, `multicodec.Sha2_256.String()` will return `sha2-256`.
|
||||
|
||||
### Code from string
|
||||
|
||||
```go
|
||||
var multicodec.Code code
|
||||
err := code.Set("libp2p-key")
|
||||
```
|
||||
|
||||
|
||||
### Code from uint64
|
||||
|
||||
```go
|
||||
rawCode := multicodec.Code(0x55)
|
||||
```
|
||||
|
||||
## Generator
|
||||
|
||||
### With old table.csv
|
||||
|
||||
To generate the constants yourself:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/multiformats/go-multicodec
|
||||
$ cd go-multicodec
|
||||
$ git submodule init && git submodule update
|
||||
$ go generate
|
||||
```
|
||||
|
||||
Note: You may need to install `stringer` via `go install golang.org/x/tools/cmd/stringer`.
|
||||
|
||||
### With updated table.csv
|
||||
|
||||
To generate the constants for the latest [table.csv](https://github.com/multiformats/multicodec/blob/master/table.csv):
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/multiformats/go-multicodec
|
||||
$ cd go-multicodec
|
||||
$ git submodule init
|
||||
$ git submodule update --remote # updates ./multicodec/table.csv to upstream version
|
||||
$ go generate
|
||||
```
|
||||
|
||||
## Maintainers
|
||||
|
||||
[@mvdan](https://github.com/mvdan).
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multicodec/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
88
vendor/github.com/multiformats/go-multicodec/code.go
generated
vendored
Normal file
88
vendor/github.com/multiformats/go-multicodec/code.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Package multicodec exposes the multicodec table as Go constants.
|
||||
package multicodec
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//go:generate go run gen.go
|
||||
//go:generate gofmt -w code_table.go
|
||||
//go:generate go run golang.org/x/tools/cmd/stringer@v0.5.0 -type=Code -linecomment
|
||||
|
||||
// Code describes an integer reserved in the multicodec table, defined at
|
||||
// github.com/multiformats/multicodec.
|
||||
type Code uint64
|
||||
|
||||
// Assert that Code implements flag.Value.
|
||||
// Requires a pointer, since Set modifies the receiver.
|
||||
//
|
||||
// Note that we don't implement encoding.TextMarshaler and encoding.TextUnmarshaler.
|
||||
// That's on purpose; even though multicodec names are stable just like the codes,
|
||||
// Go should still generally encode and decode multicodecs by their code number.
|
||||
// Many encoding libraries like xml and json default to TextMarshaler if it exists.
|
||||
//
|
||||
// Conversely, implementing flag.Value makes sense;
|
||||
// --someflag=sha1 is useful as it would often be typed by a human.
|
||||
var _ flag.Value = (*Code)(nil)
|
||||
|
||||
// Assert that Code implements fmt.Stringer without a pointer.
|
||||
var _ fmt.Stringer = Code(0)
|
||||
|
||||
// ReservedStart is the (inclusive) start of the reserved range of codes that
|
||||
// are safe to use for internal purposes.
|
||||
const ReservedStart = 0x300000
|
||||
|
||||
// ReservedEnd is the (inclusive) end of the reserved range of codes that are
|
||||
// safe to use for internal purposes.
|
||||
const ReservedEnd = 0x3FFFFF
|
||||
|
||||
// Set implements flag.Value, interpreting the input string as a multicodec and
|
||||
// setting the receiver to it.
|
||||
//
|
||||
// The input string can be the name or number for a known code. A number can be
|
||||
// in any format accepted by strconv.ParseUint with base 0, including decimal
|
||||
// and hexadecimal.
|
||||
//
|
||||
// Numbers in the reserved range 0x300000-0x3FFFFF are also accepted.
|
||||
func (c *Code) Set(text string) error {
|
||||
// Checking if the text is a valid number is cheap, so do it first.
|
||||
// It should be impossible for a string to be both a valid number and a
|
||||
// valid name, anyway.
|
||||
if n, err := strconv.ParseUint(text, 0, 64); err == nil {
|
||||
code := Code(n)
|
||||
if code >= 0x300000 && code <= 0x3FFFFF { // reserved range
|
||||
*c = code
|
||||
return nil
|
||||
}
|
||||
if _, ok := _Code_map[code]; ok { // known code
|
||||
*c = code
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// For now, checking if the text is a valid name is a linear operation,
|
||||
// so do it after.
|
||||
// Right now we have ~450 codes, so a linear search isn't too bad.
|
||||
// Consider generating a map[string]Code later on if linear search
|
||||
// starts being a problem.
|
||||
for code, name := range _Code_map {
|
||||
if name == text {
|
||||
*c = code
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("unknown multicodec: %q", text)
|
||||
}
|
||||
|
||||
// Note that KnownCodes is a function backed by a code-generated slice.
|
||||
// Later on, if the slice gets too large, we could codegen a packed form
|
||||
// and only expand to a regular slice via a sync.Once.
|
||||
// A function also makes it a bit clearer that the list should be read-only.
|
||||
|
||||
// KnownCodes returns a list of all codes registered in the multicodec table.
|
||||
// The returned slice should be treated as read-only.
|
||||
func KnownCodes() []Code {
|
||||
return knownCodes
|
||||
}
|
||||
1085
vendor/github.com/multiformats/go-multicodec/code_string.go
generated
vendored
Normal file
1085
vendor/github.com/multiformats/go-multicodec/code_string.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2703
vendor/github.com/multiformats/go-multicodec/code_table.go
generated
vendored
Normal file
2703
vendor/github.com/multiformats/go-multicodec/code_table.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
vendor/github.com/multiformats/go-multicodec/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multicodec/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.9.0"
|
||||
}
|
||||
1
vendor/github.com/multiformats/go-multihash/.gitignore
generated
vendored
Normal file
1
vendor/github.com/multiformats/go-multihash/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.vscode/
|
||||
6
vendor/github.com/multiformats/go-multihash/.gitmodules
generated
vendored
Normal file
6
vendor/github.com/multiformats/go-multihash/.gitmodules
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "spec/multicodec"]
|
||||
path = spec/multicodec
|
||||
url = https://github.com/multiformats/multicodec.git
|
||||
[submodule "spec/multihash"]
|
||||
path = spec/multihash
|
||||
url = https://github.com/multiformats/multihash.git
|
||||
21
vendor/github.com/multiformats/go-multihash/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multihash/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Juan Batiz-Benet
|
||||
|
||||
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.
|
||||
90
vendor/github.com/multiformats/go-multihash/README.md
generated
vendored
Normal file
90
vendor/github.com/multiformats/go-multihash/README.md
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
# go-multihash
|
||||
|
||||
[](http://ipn.io)
|
||||
[](https://github.com/multiformats/multiformats)
|
||||
[](https://webchat.freenode.net/?channels=%23ipfs)
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
[](https://godoc.org/github.com/multiformats/go-multihash)
|
||||
[](https://travis-ci.org/multiformats/go-multihash)
|
||||
[](https://codecov.io/github/multiformats/go-multihash?branch=master)
|
||||
|
||||
> [multihash](https://github.com/multiformats/multihash) implementation in Go
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
`go-multihash` is a standard Go module which can be installed with:
|
||||
|
||||
```sh
|
||||
go get github.com/multiformats/go-multihash
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
This example takes a standard hex-encoded data and uses `EncodeName` to calculate the SHA1 multihash value for the buffer.
|
||||
|
||||
The resulting hex-encoded data corresponds to: `<hash function code><digest size><hash function output>`, which could be re-parsed
|
||||
with `Multihash.FromHexString()`.
|
||||
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// ignores errors for simplicity.
|
||||
// don't do that at home.
|
||||
// Decode a SHA1 hash to a binary buffer
|
||||
buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
|
||||
|
||||
// Create a new multihash with it.
|
||||
mHashBuf, _ := multihash.EncodeName(buf, "sha1")
|
||||
// Print the multihash as hex string
|
||||
fmt.Printf("hex: %s\n", hex.EncodeToString(mHashBuf))
|
||||
|
||||
// Parse the binary multihash to a DecodedMultihash
|
||||
mHash, _ := multihash.Decode(mHashBuf)
|
||||
// Convert the sha1 value to hex string
|
||||
sha1hex := hex.EncodeToString(mHash.Digest)
|
||||
// Print all the information in the multihash
|
||||
fmt.Printf("obj: %v 0x%x %d %s\n", mHash.Name, mHash.Code, mHash.Length, sha1hex)
|
||||
}
|
||||
```
|
||||
|
||||
To run, copy to [example/foo.go](example/foo.go) and:
|
||||
|
||||
```
|
||||
> cd example/
|
||||
> go build
|
||||
> ./example
|
||||
hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
||||
obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multihash/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © 2014 Juan Batiz-Benet
|
||||
3
vendor/github.com/multiformats/go-multihash/codecov.yml
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multihash/codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
coverage:
|
||||
range: "50...100"
|
||||
comment: off
|
||||
34
vendor/github.com/multiformats/go-multihash/core/errata.go
generated
vendored
Normal file
34
vendor/github.com/multiformats/go-multihash/core/errata.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package multihash
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
)
|
||||
|
||||
type identityMultihash struct {
|
||||
bytes.Buffer
|
||||
}
|
||||
|
||||
func (identityMultihash) BlockSize() int {
|
||||
return 32 // A prefered block size is nonsense for the "identity" "hash". An arbitrary but unsurprising and positive nonzero number has been chosen to minimize the odds of fascinating bugs.
|
||||
}
|
||||
|
||||
func (x *identityMultihash) Size() int {
|
||||
return x.Len()
|
||||
}
|
||||
|
||||
func (x *identityMultihash) Sum(digest []byte) []byte {
|
||||
return x.Bytes()
|
||||
}
|
||||
|
||||
type doubleSha256 struct {
|
||||
hash.Hash
|
||||
}
|
||||
|
||||
func (x doubleSha256) Sum(digest []byte) []byte {
|
||||
digest = x.Hash.Sum(digest)
|
||||
h2 := sha256.New()
|
||||
h2.Write(digest)
|
||||
return h2.Sum(digest[0:0])
|
||||
}
|
||||
35
vendor/github.com/multiformats/go-multihash/core/magic.go
generated
vendored
Normal file
35
vendor/github.com/multiformats/go-multihash/core/magic.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package multihash
|
||||
|
||||
import "errors"
|
||||
|
||||
// ErrSumNotSupported is returned when the Sum function code is not implemented
|
||||
var ErrSumNotSupported = errors.New("no such hash registered")
|
||||
|
||||
// ErrLenTooLarge is returned when the hash function cannot produce the requested number of bytes
|
||||
var ErrLenTooLarge = errors.New("requested length was too large for digest")
|
||||
|
||||
// constants
|
||||
const (
|
||||
IDENTITY = 0x00
|
||||
SHA1 = 0x11
|
||||
SHA2_224 = 0x1013
|
||||
SHA2_256 = 0x12
|
||||
SHA2_384 = 0x20
|
||||
SHA2_512 = 0x13
|
||||
SHA2_512_224 = 0x1014
|
||||
SHA2_512_256 = 0x1015
|
||||
SHA3_224 = 0x17
|
||||
SHA3_256 = 0x16
|
||||
SHA3_384 = 0x15
|
||||
SHA3_512 = 0x14
|
||||
KECCAK_224 = 0x1A
|
||||
KECCAK_256 = 0x1B
|
||||
KECCAK_384 = 0x1C
|
||||
KECCAK_512 = 0x1D
|
||||
BLAKE3 = 0x1E
|
||||
SHAKE_128 = 0x18
|
||||
SHAKE_256 = 0x19
|
||||
MURMUR3X64_64 = 0x22
|
||||
MD5 = 0xd5
|
||||
DBL_SHA2_256 = 0x56
|
||||
)
|
||||
123
vendor/github.com/multiformats/go-multihash/core/registry.go
generated
vendored
Normal file
123
vendor/github.com/multiformats/go-multihash/core/registry.go
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
package multihash
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"hash"
|
||||
)
|
||||
|
||||
// registry is a simple map which maps a multihash indicator number
|
||||
// to a function : (size:int) -> ((hasher:hash.Hash), (bool:success))
|
||||
// The function may error (i.e., return (nil, false)) to signify that the hasher can't return that many bytes.
|
||||
//
|
||||
// Multihash indicator numbers are reserved and described in
|
||||
// https://github.com/multiformats/multicodec/blob/master/table.csv .
|
||||
// The keys used in this map must match those reservations.
|
||||
//
|
||||
// Hashers which are available in the golang stdlib will be registered automatically.
|
||||
// Others can be added using the Register function.
|
||||
var registry = make(map[uint64]func(int) (h hash.Hash, ok bool))
|
||||
|
||||
// Register adds a new hash to the set available from GetHasher and Sum.
|
||||
//
|
||||
// Register has a global effect and should only be used at package init time to avoid data races.
|
||||
//
|
||||
// The indicator code should be per the numbers reserved and described in
|
||||
// https://github.com/multiformats/multicodec/blob/master/table.csv .
|
||||
//
|
||||
// If Register is called with the same indicator code more than once, the last call wins.
|
||||
// In practice, this means that if an application has a strong opinion about what implementation to use for a certain hash
|
||||
// (e.g., perhaps they want to override the sha256 implementation to use a special hand-rolled assembly variant
|
||||
// rather than the stdlib one which is registered by default),
|
||||
// then this can be done by making a Register call with that effect at init time in the application's main package.
|
||||
// This should have the desired effect because the root of the import tree has its init time effect last.
|
||||
func Register(indicator uint64, hasherFactory func() hash.Hash) {
|
||||
if hasherFactory == nil {
|
||||
panic("not sensible to attempt to register a nil function")
|
||||
}
|
||||
maxSize := hasherFactory().Size()
|
||||
registry[indicator] = func(size int) (hash.Hash, bool) {
|
||||
if size > maxSize {
|
||||
return nil, false
|
||||
}
|
||||
return hasherFactory(), true
|
||||
}
|
||||
DefaultLengths[indicator] = maxSize
|
||||
}
|
||||
|
||||
// RegisterVariableSize is like Register, but adds a new variable-sized hasher factory that takes a
|
||||
// size hint.
|
||||
//
|
||||
// When passed -1, the hasher should produce digests with the hash-function's default length. When
|
||||
// passed a non-negative integer, the hasher should try to produce digests of at least the specified
|
||||
// size.
|
||||
func RegisterVariableSize(indicator uint64, hasherFactory func(sizeHint int) (hash.Hash, bool)) {
|
||||
if hasherFactory == nil {
|
||||
panic("not sensible to attempt to register a nil function")
|
||||
}
|
||||
|
||||
if hasher, ok := hasherFactory(-1); !ok {
|
||||
panic("failed to determine default hash length for hasher")
|
||||
} else {
|
||||
DefaultLengths[indicator] = hasher.Size()
|
||||
}
|
||||
|
||||
registry[indicator] = hasherFactory
|
||||
}
|
||||
|
||||
// GetHasher returns a new hash.Hash according to the indicator code number provided.
|
||||
//
|
||||
// The indicator code should be per the numbers reserved and described in
|
||||
// https://github.com/multiformats/multicodec/blob/master/table.csv .
|
||||
//
|
||||
// The actual hashers available are determined by what has been registered.
|
||||
// The registry automatically contains those hashers which are available in the golang standard libraries
|
||||
// (which includes md5, sha1, sha256, sha384, sha512, and the "identity" mulithash, among others).
|
||||
// Other hash implementations can be made available by using the Register function.
|
||||
// The 'go-mulithash/register/*' packages can also be imported to gain more common hash functions.
|
||||
//
|
||||
// If an error is returned, it will match `errors.Is(err, ErrSumNotSupported)`.
|
||||
func GetHasher(indicator uint64) (hash.Hash, error) {
|
||||
return GetVariableHasher(indicator, -1)
|
||||
}
|
||||
|
||||
// GetVariableHasher returns a new hash.Hash according to the indicator code number provided, with
|
||||
// the specified size hint.
|
||||
//
|
||||
// NOTE: The size hint is only a hint. Hashers will attempt to produce at least the number of requested bytes, but may not.
|
||||
//
|
||||
// This function can fail if either the hash code is not registered, or the passed size hint is
|
||||
// statically incompatible with the specified hash function.
|
||||
func GetVariableHasher(indicator uint64, sizeHint int) (hash.Hash, error) {
|
||||
factory, exists := registry[indicator]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported)
|
||||
}
|
||||
hasher, ok := factory(sizeHint)
|
||||
if !ok {
|
||||
return nil, ErrLenTooLarge
|
||||
}
|
||||
return hasher, nil
|
||||
}
|
||||
|
||||
// DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes.
|
||||
//
|
||||
// This map is populated when a hash function is registered by the Register function.
|
||||
// It's effectively a shortcut for asking Size() on the hash.Hash.
|
||||
var DefaultLengths = map[uint64]int{}
|
||||
|
||||
func init() {
|
||||
RegisterVariableSize(IDENTITY, func(_ int) (hash.Hash, bool) { return &identityMultihash{}, true })
|
||||
Register(MD5, md5.New)
|
||||
Register(SHA1, sha1.New)
|
||||
Register(SHA2_224, sha256.New224)
|
||||
Register(SHA2_256, sha256.New)
|
||||
Register(SHA2_384, sha512.New384)
|
||||
Register(SHA2_512, sha512.New)
|
||||
Register(SHA2_512_224, sha512.New512_224)
|
||||
Register(SHA2_512_256, sha512.New512_256)
|
||||
Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} })
|
||||
}
|
||||
98
vendor/github.com/multiformats/go-multihash/io.go
generated
vendored
Normal file
98
vendor/github.com/multiformats/go-multihash/io.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
package multihash
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
// Reader is an io.Reader wrapper that exposes a function
|
||||
// to read a whole multihash, parse it, and return it.
|
||||
type Reader interface {
|
||||
io.Reader
|
||||
|
||||
ReadMultihash() (Multihash, error)
|
||||
}
|
||||
|
||||
// Writer is an io.Writer wrapper that exposes a function
|
||||
// to write a whole multihash.
|
||||
type Writer interface {
|
||||
io.Writer
|
||||
|
||||
WriteMultihash(Multihash) error
|
||||
}
|
||||
|
||||
// NewReader wraps an io.Reader with a multihash.Reader
|
||||
func NewReader(r io.Reader) Reader {
|
||||
return &mhReader{r}
|
||||
}
|
||||
|
||||
// NewWriter wraps an io.Writer with a multihash.Writer
|
||||
func NewWriter(w io.Writer) Writer {
|
||||
return &mhWriter{w}
|
||||
}
|
||||
|
||||
type mhReader struct {
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func (r *mhReader) Read(buf []byte) (n int, err error) {
|
||||
return r.r.Read(buf)
|
||||
}
|
||||
|
||||
func (r *mhReader) ReadByte() (byte, error) {
|
||||
if br, ok := r.r.(io.ByteReader); ok {
|
||||
return br.ReadByte()
|
||||
}
|
||||
var b [1]byte
|
||||
n, err := r.r.Read(b[:])
|
||||
if n == 1 {
|
||||
return b[0], nil
|
||||
}
|
||||
if err == nil {
|
||||
if n != 0 {
|
||||
panic("reader returned an invalid length")
|
||||
}
|
||||
err = io.ErrNoProgress
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func (r *mhReader) ReadMultihash() (Multihash, error) {
|
||||
code, err := varint.ReadUvarint(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
length, err := varint.ReadUvarint(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if length > math.MaxInt32 {
|
||||
return nil, errors.New("digest too long, supporting only <= 2^31-1")
|
||||
}
|
||||
|
||||
buf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(length)+int(length))
|
||||
n := varint.PutUvarint(buf, code)
|
||||
n += varint.PutUvarint(buf[n:], length)
|
||||
if _, err := io.ReadFull(r.r, buf[n:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return Cast(buf)
|
||||
}
|
||||
|
||||
type mhWriter struct {
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func (w *mhWriter) Write(buf []byte) (n int, err error) {
|
||||
return w.w.Write(buf)
|
||||
}
|
||||
|
||||
func (w *mhWriter) WriteMultihash(m Multihash) error {
|
||||
_, err := w.w.Write([]byte(m))
|
||||
return err
|
||||
}
|
||||
322
vendor/github.com/multiformats/go-multihash/multihash.go
generated
vendored
Normal file
322
vendor/github.com/multiformats/go-multihash/multihash.go
generated
vendored
Normal file
@@ -0,0 +1,322 @@
|
||||
// Package multihash is the Go implementation of
|
||||
// https://github.com/multiformats/multihash, or self-describing
|
||||
// hashes.
|
||||
package multihash
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
b58 "github.com/mr-tron/base58/base58"
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
// errors
|
||||
var (
|
||||
ErrUnknownCode = errors.New("unknown multihash code")
|
||||
ErrTooShort = errors.New("multihash too short. must be >= 2 bytes")
|
||||
ErrTooLong = errors.New("multihash too long. must be < 129 bytes")
|
||||
ErrLenNotSupported = errors.New("multihash does not yet support digests longer than 127 bytes")
|
||||
ErrInvalidMultihash = errors.New("input isn't valid multihash")
|
||||
|
||||
ErrVarintBufferShort = errors.New("uvarint: buffer too small")
|
||||
ErrVarintTooLong = errors.New("uvarint: varint too big (max 64bit)")
|
||||
)
|
||||
|
||||
// ErrInconsistentLen is returned when a decoded multihash has an inconsistent length
|
||||
type ErrInconsistentLen struct {
|
||||
dm DecodedMultihash
|
||||
lengthFound int
|
||||
}
|
||||
|
||||
func (e ErrInconsistentLen) Error() string {
|
||||
return fmt.Sprintf("multihash length inconsistent: expected %d; got %d", e.dm.Length, e.lengthFound)
|
||||
}
|
||||
|
||||
// constants
|
||||
const (
|
||||
IDENTITY = 0x00
|
||||
// Deprecated: use IDENTITY
|
||||
ID = IDENTITY
|
||||
SHA1 = 0x11
|
||||
SHA2_256 = 0x12
|
||||
SHA2_512 = 0x13
|
||||
SHA3_224 = 0x17
|
||||
SHA3_256 = 0x16
|
||||
SHA3_384 = 0x15
|
||||
SHA3_512 = 0x14
|
||||
SHA3 = SHA3_512
|
||||
KECCAK_224 = 0x1A
|
||||
KECCAK_256 = 0x1B
|
||||
KECCAK_384 = 0x1C
|
||||
KECCAK_512 = 0x1D
|
||||
BLAKE3 = 0x1E
|
||||
|
||||
SHAKE_128 = 0x18
|
||||
SHAKE_256 = 0x19
|
||||
|
||||
BLAKE2B_MIN = 0xb201
|
||||
BLAKE2B_MAX = 0xb240
|
||||
BLAKE2S_MIN = 0xb241
|
||||
BLAKE2S_MAX = 0xb260
|
||||
|
||||
MD5 = 0xd5
|
||||
|
||||
DBL_SHA2_256 = 0x56
|
||||
|
||||
MURMUR3X64_64 = 0x22
|
||||
// Deprecated: use MURMUR3X64_64
|
||||
MURMUR3 = MURMUR3X64_64
|
||||
|
||||
SHA2_256_TRUNC254_PADDED = 0x1012
|
||||
X11 = 0x1100
|
||||
POSEIDON_BLS12_381_A1_FC1 = 0xb401
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Add blake2b (64 codes)
|
||||
for c := uint64(BLAKE2B_MIN); c <= BLAKE2B_MAX; c++ {
|
||||
n := c - BLAKE2B_MIN + 1
|
||||
name := fmt.Sprintf("blake2b-%d", n*8)
|
||||
Names[name] = c
|
||||
Codes[c] = name
|
||||
}
|
||||
|
||||
// Add blake2s (32 codes)
|
||||
for c := uint64(BLAKE2S_MIN); c <= BLAKE2S_MAX; c++ {
|
||||
n := c - BLAKE2S_MIN + 1
|
||||
name := fmt.Sprintf("blake2s-%d", n*8)
|
||||
Names[name] = c
|
||||
Codes[c] = name
|
||||
}
|
||||
}
|
||||
|
||||
// Names maps the name of a hash to the code
|
||||
var Names = map[string]uint64{
|
||||
"identity": IDENTITY,
|
||||
"sha1": SHA1,
|
||||
"sha2-256": SHA2_256,
|
||||
"sha2-512": SHA2_512,
|
||||
"sha3": SHA3_512,
|
||||
"sha3-224": SHA3_224,
|
||||
"sha3-256": SHA3_256,
|
||||
"sha3-384": SHA3_384,
|
||||
"sha3-512": SHA3_512,
|
||||
"dbl-sha2-256": DBL_SHA2_256,
|
||||
"murmur3-x64-64": MURMUR3X64_64,
|
||||
"keccak-224": KECCAK_224,
|
||||
"keccak-256": KECCAK_256,
|
||||
"keccak-384": KECCAK_384,
|
||||
"keccak-512": KECCAK_512,
|
||||
"blake3": BLAKE3,
|
||||
"shake-128": SHAKE_128,
|
||||
"shake-256": SHAKE_256,
|
||||
"sha2-256-trunc254-padded": SHA2_256_TRUNC254_PADDED,
|
||||
"x11": X11,
|
||||
"md5": MD5,
|
||||
"poseidon-bls12_381-a2-fc1": POSEIDON_BLS12_381_A1_FC1,
|
||||
}
|
||||
|
||||
// Codes maps a hash code to it's name
|
||||
var Codes = map[uint64]string{
|
||||
IDENTITY: "identity",
|
||||
SHA1: "sha1",
|
||||
SHA2_256: "sha2-256",
|
||||
SHA2_512: "sha2-512",
|
||||
SHA3_224: "sha3-224",
|
||||
SHA3_256: "sha3-256",
|
||||
SHA3_384: "sha3-384",
|
||||
SHA3_512: "sha3-512",
|
||||
DBL_SHA2_256: "dbl-sha2-256",
|
||||
MURMUR3X64_64: "murmur3-x64-64",
|
||||
KECCAK_224: "keccak-224",
|
||||
KECCAK_256: "keccak-256",
|
||||
KECCAK_384: "keccak-384",
|
||||
KECCAK_512: "keccak-512",
|
||||
BLAKE3: "blake3",
|
||||
SHAKE_128: "shake-128",
|
||||
SHAKE_256: "shake-256",
|
||||
SHA2_256_TRUNC254_PADDED: "sha2-256-trunc254-padded",
|
||||
X11: "x11",
|
||||
POSEIDON_BLS12_381_A1_FC1: "poseidon-bls12_381-a2-fc1",
|
||||
MD5: "md5",
|
||||
}
|
||||
|
||||
// reads a varint from buf and returns bytes read.
|
||||
func uvarint(buf []byte) (uint64, []byte, error) {
|
||||
n, c, err := varint.FromUvarint(buf)
|
||||
if err != nil {
|
||||
return n, buf, err
|
||||
}
|
||||
|
||||
if c == 0 {
|
||||
return n, buf, ErrVarintBufferShort
|
||||
} else if c < 0 {
|
||||
return n, buf[-c:], ErrVarintTooLong
|
||||
} else {
|
||||
return n, buf[c:], nil
|
||||
}
|
||||
}
|
||||
|
||||
// DecodedMultihash represents a parsed multihash and allows
|
||||
// easy access to the different parts of a multihash.
|
||||
type DecodedMultihash struct {
|
||||
Code uint64
|
||||
Name string
|
||||
Length int // Length is just int as it is type of len() opearator
|
||||
Digest []byte // Digest holds the raw multihash bytes
|
||||
}
|
||||
|
||||
// Multihash is byte slice with the following form:
|
||||
// <hash function code><digest size><hash function output>.
|
||||
// See the spec for more information.
|
||||
type Multihash []byte
|
||||
|
||||
// HexString returns the hex-encoded representation of a multihash.
|
||||
func (m Multihash) HexString() string {
|
||||
return hex.EncodeToString([]byte(m))
|
||||
}
|
||||
|
||||
// String is an alias to HexString().
|
||||
func (m Multihash) String() string {
|
||||
return m.HexString()
|
||||
}
|
||||
|
||||
// FromHexString parses a hex-encoded multihash.
|
||||
func FromHexString(s string) (Multihash, error) {
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return Multihash{}, err
|
||||
}
|
||||
|
||||
return Cast(b)
|
||||
}
|
||||
|
||||
// B58String returns the B58-encoded representation of a multihash.
|
||||
func (m Multihash) B58String() string {
|
||||
return b58.Encode([]byte(m))
|
||||
}
|
||||
|
||||
// FromB58String parses a B58-encoded multihash.
|
||||
func FromB58String(s string) (m Multihash, err error) {
|
||||
b, err := b58.Decode(s)
|
||||
if err != nil {
|
||||
return Multihash{}, ErrInvalidMultihash
|
||||
}
|
||||
|
||||
return Cast(b)
|
||||
}
|
||||
|
||||
// Cast casts a buffer onto a multihash, and returns an error
|
||||
// if it does not work.
|
||||
func Cast(buf []byte) (Multihash, error) {
|
||||
_, err := Decode(buf)
|
||||
if err != nil {
|
||||
return Multihash{}, err
|
||||
}
|
||||
|
||||
return Multihash(buf), nil
|
||||
}
|
||||
|
||||
// Decode parses multihash bytes into a DecodedMultihash.
|
||||
func Decode(buf []byte) (*DecodedMultihash, error) {
|
||||
// outline decode allowing the &dm expression to be inlined into the caller.
|
||||
// This moves the heap allocation into the caller and if the caller doesn't
|
||||
// leak dm the compiler will use a stack allocation instead.
|
||||
// If you do not outline this &dm always heap allocate since the pointer is
|
||||
// returned which cause a heap allocation because Decode's stack frame is
|
||||
// about to disapear.
|
||||
dm, err := decode(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &dm, nil
|
||||
}
|
||||
|
||||
func decode(buf []byte) (dm DecodedMultihash, err error) {
|
||||
rlen, code, hdig, err := readMultihashFromBuf(buf)
|
||||
if err != nil {
|
||||
return DecodedMultihash{}, err
|
||||
}
|
||||
|
||||
dm = DecodedMultihash{
|
||||
Code: code,
|
||||
Name: Codes[code],
|
||||
Length: len(hdig),
|
||||
Digest: hdig,
|
||||
}
|
||||
|
||||
if len(buf) != rlen {
|
||||
return dm, ErrInconsistentLen{dm, rlen}
|
||||
}
|
||||
|
||||
return dm, nil
|
||||
}
|
||||
|
||||
// Encode a hash digest along with the specified function code.
|
||||
// Note: the length is derived from the length of the digest itself.
|
||||
//
|
||||
// The error return is legacy; it is always nil.
|
||||
func Encode(buf []byte, code uint64) ([]byte, error) {
|
||||
// FUTURE: this function always causes heap allocs... but when used, this value is almost always going to be appended to another buffer (either as part of CID creation, or etc) -- should this whole function be rethought and alternatives offered?
|
||||
newBuf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(uint64(len(buf)))+len(buf))
|
||||
n := varint.PutUvarint(newBuf, code)
|
||||
n += varint.PutUvarint(newBuf[n:], uint64(len(buf)))
|
||||
|
||||
copy(newBuf[n:], buf)
|
||||
return newBuf, nil
|
||||
}
|
||||
|
||||
// EncodeName is like Encode() but providing a string name
|
||||
// instead of a numeric code. See Names for allowed values.
|
||||
func EncodeName(buf []byte, name string) ([]byte, error) {
|
||||
return Encode(buf, Names[name])
|
||||
}
|
||||
|
||||
// readMultihashFromBuf reads a multihash from the given buffer, returning the
|
||||
// individual pieces of the multihash.
|
||||
// Note: the returned digest is a slice over the passed in data and should be
|
||||
// copied if the buffer will be reused
|
||||
func readMultihashFromBuf(buf []byte) (int, uint64, []byte, error) {
|
||||
initBufLength := len(buf)
|
||||
if initBufLength < 2 {
|
||||
return 0, 0, nil, ErrTooShort
|
||||
}
|
||||
|
||||
var err error
|
||||
var code, length uint64
|
||||
|
||||
code, buf, err = uvarint(buf)
|
||||
if err != nil {
|
||||
return 0, 0, nil, err
|
||||
}
|
||||
|
||||
length, buf, err = uvarint(buf)
|
||||
if err != nil {
|
||||
return 0, 0, nil, err
|
||||
}
|
||||
|
||||
if length > math.MaxInt32 {
|
||||
return 0, 0, nil, errors.New("digest too long, supporting only <= 2^31-1")
|
||||
}
|
||||
if int(length) > len(buf) {
|
||||
return 0, 0, nil, errors.New("length greater than remaining number of bytes in buffer")
|
||||
}
|
||||
|
||||
// rlen is the advertised size of the CID
|
||||
rlen := (initBufLength - len(buf)) + int(length)
|
||||
return rlen, code, buf[:length], nil
|
||||
}
|
||||
|
||||
// MHFromBytes reads a multihash from the given byte buffer, returning the
|
||||
// number of bytes read as well as the multihash
|
||||
func MHFromBytes(buf []byte) (int, Multihash, error) {
|
||||
nr, _, _, err := readMultihashFromBuf(buf)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return nr, Multihash(buf[:nr]), nil
|
||||
}
|
||||
24
vendor/github.com/multiformats/go-multihash/register/all/multihash_all.go
generated
vendored
Normal file
24
vendor/github.com/multiformats/go-multihash/register/all/multihash_all.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
This package has no purpose except to perform registration of mulithashes.
|
||||
|
||||
It is meant to be used as a side-effecting import, e.g.
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/all"
|
||||
)
|
||||
|
||||
This package registers many multihashes at once.
|
||||
Importing it will increase the size of your dependency tree significantly.
|
||||
It's recommended that you import this package if you're building some
|
||||
kind of data broker application, which may need to handle many different kinds of hashes;
|
||||
if you're building an application which you know only handles a specific hash,
|
||||
importing this package may bloat your builds unnecessarily.
|
||||
*/
|
||||
package all
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/blake2"
|
||||
_ "github.com/multiformats/go-multihash/register/blake3"
|
||||
_ "github.com/multiformats/go-multihash/register/murmur3"
|
||||
_ "github.com/multiformats/go-multihash/register/sha3"
|
||||
)
|
||||
55
vendor/github.com/multiformats/go-multihash/register/blake2/multihash_blake2.go
generated
vendored
Normal file
55
vendor/github.com/multiformats/go-multihash/register/blake2/multihash_blake2.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
This package has no purpose except to perform registration of multihashes.
|
||||
|
||||
It is meant to be used as a side-effecting import, e.g.
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/blake2"
|
||||
)
|
||||
|
||||
This package registers several multihashes for the blake2 family
|
||||
(both the 's' and the 'b' variants, and in a variety of sizes).
|
||||
*/
|
||||
package blake2
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
|
||||
multihash "github.com/multiformats/go-multihash/core"
|
||||
)
|
||||
|
||||
const (
|
||||
blake2b_min = 0xb201
|
||||
blake2b_max = 0xb240
|
||||
blake2s_min = 0xb241
|
||||
blake2s_max = 0xb260
|
||||
)
|
||||
|
||||
func init() {
|
||||
// blake2s
|
||||
// This package only enables support for 32byte (256 bit) blake2s.
|
||||
multihash.Register(blake2s_min+31, func() hash.Hash {
|
||||
h, err := blake2s.New256(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return h
|
||||
})
|
||||
|
||||
// blake2b
|
||||
// There's a whole range of these.
|
||||
for c := uint64(blake2b_min); c <= blake2b_max; c++ {
|
||||
size := int(c - blake2b_min + 1)
|
||||
|
||||
multihash.Register(c, func() hash.Hash {
|
||||
hasher, err := blake2b.New(size, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hasher
|
||||
})
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/multiformats/go-multihash/register/blake3/multihash_blake3.go
generated
vendored
Normal file
33
vendor/github.com/multiformats/go-multihash/register/blake3/multihash_blake3.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
This package has no purpose except to register the blake3 hash function.
|
||||
|
||||
It is meant to be used as a side-effecting import, e.g.
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/blake3"
|
||||
)
|
||||
*/
|
||||
package blake3
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
"lukechampine.com/blake3"
|
||||
|
||||
multihash "github.com/multiformats/go-multihash/core"
|
||||
)
|
||||
|
||||
const DefaultSize = 32
|
||||
const MaxSize = 128
|
||||
|
||||
func init() {
|
||||
multihash.RegisterVariableSize(multihash.BLAKE3, func(size int) (hash.Hash, bool) {
|
||||
if size == -1 {
|
||||
size = DefaultSize
|
||||
} else if size > MaxSize || size <= 0 {
|
||||
return nil, false
|
||||
}
|
||||
h := blake3.New(size, nil)
|
||||
return h, true
|
||||
})
|
||||
}
|
||||
22
vendor/github.com/multiformats/go-multihash/register/miniosha256/post_go1.21.go
generated
vendored
Normal file
22
vendor/github.com/multiformats/go-multihash/register/miniosha256/post_go1.21.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
//go:build go1.21
|
||||
|
||||
// This package has no purpose except to perform registration of multihashes.
|
||||
//
|
||||
// It is meant to be used as a side-effecting import, e.g.
|
||||
//
|
||||
// import (
|
||||
// _ "github.com/multiformats/go-multihash/register/miniosha256"
|
||||
// )
|
||||
//
|
||||
// This package registers alternative implementations for sha2-256, using
|
||||
// the github.com/minio/sha256-simd library for go1.20 and bellow. Go 1.21 and
|
||||
// later fallback to [github.com/multiformats/go-multihash/register/sha256].
|
||||
//
|
||||
// Deprecated: please switch to [github.com/multiformats/go-multihash/register/sha256]
|
||||
// as of go1.21 the go std has a SHANI implementation that is just as fast. See https://go.dev/issue/50543.
|
||||
// This will be removed shortly after go1.22 is released.
|
||||
package miniosha256
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/sha256"
|
||||
)
|
||||
29
vendor/github.com/multiformats/go-multihash/register/miniosha256/pre_go1_21.go
generated
vendored
Normal file
29
vendor/github.com/multiformats/go-multihash/register/miniosha256/pre_go1_21.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
//go:build !go1.21
|
||||
|
||||
// This package has no purpose except to perform registration of multihashes.
|
||||
//
|
||||
// It is meant to be used as a side-effecting import, e.g.
|
||||
//
|
||||
// import (
|
||||
// _ "github.com/multiformats/go-multihash/register/miniosha256"
|
||||
// )
|
||||
//
|
||||
// This package registers alternative implementations for sha2-256, using
|
||||
// the github.com/minio/sha256-simd library for go1.20 and bellow. Go 1.21 and
|
||||
// later fallback to [github.com/multiformats/go-multihash/register/sha256].
|
||||
//
|
||||
// Note if you are using go1.21 or above this package is deprecated in favor of
|
||||
// [github.com/multiformats/go-multihash/register/sha256] because as of go1.21
|
||||
// the go std has a SHANI implementation that is just as fast. See https://go.dev/issue/50543.
|
||||
// This will be removed shortly after go1.22 is released.
|
||||
package miniosha256
|
||||
|
||||
import (
|
||||
"github.com/minio/sha256-simd"
|
||||
|
||||
multihash "github.com/multiformats/go-multihash/core"
|
||||
)
|
||||
|
||||
func init() {
|
||||
multihash.Register(multihash.SHA2_256, sha256.New)
|
||||
}
|
||||
40
vendor/github.com/multiformats/go-multihash/register/murmur3/multihash_murmur3.go
generated
vendored
Normal file
40
vendor/github.com/multiformats/go-multihash/register/murmur3/multihash_murmur3.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
This package has no purpose except to perform registration of multihashes.
|
||||
|
||||
It is meant to be used as a side-effecting import, e.g.
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/murmur3"
|
||||
)
|
||||
|
||||
This package registers multihashes for murmur3
|
||||
*/
|
||||
package murmur3
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
multihash "github.com/multiformats/go-multihash/core"
|
||||
"github.com/spaolacci/murmur3"
|
||||
)
|
||||
|
||||
func init() {
|
||||
multihash.Register(multihash.MURMUR3X64_64, func() hash.Hash { return murmur64{murmur3.New64()} })
|
||||
}
|
||||
|
||||
// A wrapper is needed to export the correct size, because murmur3 incorrectly advertises Hash64 as a 128bit hash.
|
||||
type murmur64 struct {
|
||||
hash.Hash64
|
||||
}
|
||||
|
||||
func (murmur64) BlockSize() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (x murmur64) Size() int {
|
||||
return 8
|
||||
}
|
||||
|
||||
func (x murmur64) Sum(digest []byte) []byte {
|
||||
return x.Hash64.Sum(digest)
|
||||
}
|
||||
21
vendor/github.com/multiformats/go-multihash/register/sha256/sha256.go
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multihash/register/sha256/sha256.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// This package has no purpose except to perform registration of multihashes.
|
||||
//
|
||||
// It is meant to be used as a side-effecting import, e.g.
|
||||
//
|
||||
// import (
|
||||
// _ "github.com/multiformats/go-multihash/register/sha256"
|
||||
// )
|
||||
//
|
||||
// This package an implementation of sha256 using the go std, this is recomanded
|
||||
// if you are using go1.21 or above.
|
||||
package sha256
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
multihash "github.com/multiformats/go-multihash/core"
|
||||
)
|
||||
|
||||
func init() {
|
||||
multihash.Register(multihash.SHA2_256, sha256.New)
|
||||
}
|
||||
62
vendor/github.com/multiformats/go-multihash/register/sha3/multihash_sha3.go
generated
vendored
Normal file
62
vendor/github.com/multiformats/go-multihash/register/sha3/multihash_sha3.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
This package has no purpose except to perform registration of multihashes.
|
||||
|
||||
It is meant to be used as a side-effecting import, e.g.
|
||||
|
||||
import (
|
||||
_ "github.com/multiformats/go-multihash/register/sha3"
|
||||
)
|
||||
|
||||
This package registers several multihashes for the sha3 family.
|
||||
This also includes some functions known as "shake" and "keccak",
|
||||
since they share much of their implementation and come in the same repos.
|
||||
*/
|
||||
package sha3
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
multihash "github.com/multiformats/go-multihash/core"
|
||||
)
|
||||
|
||||
func init() {
|
||||
multihash.Register(multihash.SHA3_512, sha3.New512)
|
||||
multihash.Register(multihash.SHA3_384, sha3.New384)
|
||||
multihash.Register(multihash.SHA3_256, sha3.New256)
|
||||
multihash.Register(multihash.SHA3_224, sha3.New224)
|
||||
multihash.Register(multihash.SHAKE_128, func() hash.Hash { return shakeNormalizer{sha3.NewShake128(), 128 / 8 * 2} })
|
||||
multihash.Register(multihash.SHAKE_256, func() hash.Hash { return shakeNormalizer{sha3.NewShake256(), 256 / 8 * 2} })
|
||||
multihash.Register(multihash.KECCAK_256, sha3.NewLegacyKeccak256)
|
||||
multihash.Register(multihash.KECCAK_512, sha3.NewLegacyKeccak512)
|
||||
}
|
||||
|
||||
// sha3.ShakeHash presents a somewhat odd interface, and requires a wrapper to normalize it to the usual hash.Hash interface.
|
||||
//
|
||||
// Some of the fiddly bits required by this normalization probably makes it undesirable for use in the highest performance applications;
|
||||
// There's at least one extra allocation in constructing it (sha3.ShakeHash is an interface, so that's one heap escape; and there's a second heap escape when this normalizer struct gets boxed into a hash.Hash interface),
|
||||
// and there's at least one extra allocation in getting a sum out of it (because reading a shake hash is a mutation (!) and the API only provides cloning as a way to escape this).
|
||||
// Fun.
|
||||
type shakeNormalizer struct {
|
||||
sha3.ShakeHash
|
||||
size int
|
||||
}
|
||||
|
||||
func (shakeNormalizer) BlockSize() int {
|
||||
return 32 // Shake doesn't have a prefered block size, apparently. An arbitrary but unsurprising and positive nonzero number has been chosen to minimize the odds of fascinating bugs.
|
||||
}
|
||||
|
||||
func (x shakeNormalizer) Size() int {
|
||||
return x.size
|
||||
}
|
||||
|
||||
func (x shakeNormalizer) Sum(digest []byte) []byte {
|
||||
if len(digest) < x.size {
|
||||
digest = make([]byte, x.size)
|
||||
}
|
||||
digest = digest[0:x.size]
|
||||
h2 := x.Clone() // clone it, because reading mutates this kind of hash (!) which is not the standard contract for a Hash.Sum method.
|
||||
h2.Read(digest) // not capable of underreading. See sha3.ShakeSum256 for similar usage.
|
||||
return digest
|
||||
}
|
||||
31
vendor/github.com/multiformats/go-multihash/registry.go
generated
vendored
Normal file
31
vendor/github.com/multiformats/go-multihash/registry.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package multihash
|
||||
|
||||
import (
|
||||
"hash"
|
||||
|
||||
mhreg "github.com/multiformats/go-multihash/core"
|
||||
|
||||
_ "github.com/multiformats/go-multihash/register/all"
|
||||
_ "github.com/multiformats/go-multihash/register/miniosha256"
|
||||
)
|
||||
|
||||
// Register is an alias for Register in the core package.
|
||||
//
|
||||
// Consider using the core package instead of this multihash package;
|
||||
// that package does not introduce transitive dependencies except for those you opt into,
|
||||
// and will can result in smaller application builds.
|
||||
func Register(indicator uint64, hasherFactory func() hash.Hash) {
|
||||
mhreg.Register(indicator, hasherFactory)
|
||||
}
|
||||
|
||||
// Register is an alias for Register in the core package.
|
||||
//
|
||||
// Consider using the core package instead of this multihash package;
|
||||
// that package does not introduce transitive dependencies except for those you opt into,
|
||||
// and will can result in smaller application builds.
|
||||
func GetHasher(indicator uint64) (hash.Hash, error) {
|
||||
return mhreg.GetHasher(indicator)
|
||||
}
|
||||
|
||||
// DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes.
|
||||
var DefaultLengths = mhreg.DefaultLengths
|
||||
66
vendor/github.com/multiformats/go-multihash/set.go
generated
vendored
Normal file
66
vendor/github.com/multiformats/go-multihash/set.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package multihash
|
||||
|
||||
// Set is a set of Multihashes, holding one copy per Multihash.
|
||||
type Set struct {
|
||||
set map[string]struct{}
|
||||
}
|
||||
|
||||
// NewSet creates a new set correctly initialized.
|
||||
func NewSet() *Set {
|
||||
return &Set{
|
||||
set: make(map[string]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a new multihash to the set.
|
||||
func (s *Set) Add(m Multihash) {
|
||||
s.set[string(m)] = struct{}{}
|
||||
}
|
||||
|
||||
// Len returns the number of elements in the set.
|
||||
func (s *Set) Len() int {
|
||||
return len(s.set)
|
||||
}
|
||||
|
||||
// Has returns true if the element is in the set.
|
||||
func (s *Set) Has(m Multihash) bool {
|
||||
_, ok := s.set[string(m)]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Visit adds a multihash only if it is not in the set already. Returns true
|
||||
// if the multihash was added (was not in the set before).
|
||||
func (s *Set) Visit(m Multihash) bool {
|
||||
_, ok := s.set[string(m)]
|
||||
if !ok {
|
||||
s.set[string(m)] = struct{}{}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ForEach runs f(m) with each multihash in the set. If returns immediately if
|
||||
// f(m) returns an error.
|
||||
func (s *Set) ForEach(f func(m Multihash) error) error {
|
||||
for elem := range s.set {
|
||||
mh := Multihash(elem)
|
||||
if err := f(mh); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove removes an element from the set.
|
||||
func (s *Set) Remove(m Multihash) {
|
||||
delete(s.set, string(m))
|
||||
}
|
||||
|
||||
// All returns a slice with all the elements in the set.
|
||||
func (s *Set) All() []Multihash {
|
||||
out := make([]Multihash, 0, len(s.set))
|
||||
for m := range s.set {
|
||||
out = append(out, Multihash(m))
|
||||
}
|
||||
return out
|
||||
}
|
||||
77
vendor/github.com/multiformats/go-multihash/sum.go
generated
vendored
Normal file
77
vendor/github.com/multiformats/go-multihash/sum.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package multihash
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
mhreg "github.com/multiformats/go-multihash/core"
|
||||
)
|
||||
|
||||
// ErrSumNotSupported is returned when the Sum function code is not implemented
|
||||
var ErrSumNotSupported = mhreg.ErrSumNotSupported
|
||||
|
||||
var ErrLenTooLarge = mhreg.ErrLenTooLarge
|
||||
|
||||
// Sum obtains the cryptographic sum of a given buffer. The length parameter
|
||||
// indicates the length of the resulting digest. Passing a negative value uses
|
||||
// default length values for the selected hash function.
|
||||
func Sum(data []byte, code uint64, length int) (Multihash, error) {
|
||||
// Get the algorithm.
|
||||
hasher, err := mhreg.GetVariableHasher(code, length)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Feed data in.
|
||||
if _, err := hasher.Write(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return encodeHash(hasher, code, length)
|
||||
}
|
||||
|
||||
// SumStream obtains the cryptographic sum of a given stream. The length
|
||||
// parameter indicates the length of the resulting digest. Passing a negative
|
||||
// value uses default length values for the selected hash function.
|
||||
func SumStream(r io.Reader, code uint64, length int) (Multihash, error) {
|
||||
// Get the algorithm.
|
||||
hasher, err := mhreg.GetVariableHasher(code, length)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Feed data in.
|
||||
if _, err = io.Copy(hasher, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return encodeHash(hasher, code, length)
|
||||
}
|
||||
|
||||
func encodeHash(hasher hash.Hash, code uint64, length int) (Multihash, error) {
|
||||
// Compute final hash.
|
||||
// A new slice is allocated. FUTURE: see other comment below about allocation, and review together with this line to try to improve.
|
||||
sum := hasher.Sum(nil)
|
||||
|
||||
// Deal with any truncation.
|
||||
// Unless it's an identity multihash. Those have different rules.
|
||||
if length < 0 {
|
||||
length = hasher.Size()
|
||||
}
|
||||
if len(sum) < length {
|
||||
return nil, ErrLenTooLarge
|
||||
}
|
||||
if length >= 0 {
|
||||
if code == IDENTITY {
|
||||
if length != len(sum) {
|
||||
return nil, fmt.Errorf("the length of the identity hash (%d) must be equal to the length of the data (%d)", length, len(sum))
|
||||
}
|
||||
}
|
||||
sum = sum[:length]
|
||||
}
|
||||
|
||||
// Put the multihash metainfo bytes at the front of the buffer.
|
||||
// FUTURE: try to improve allocations here. Encode does several which are probably avoidable, but it's the shape of the Encode method arguments that forces this.
|
||||
return Encode(sum, code)
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-multihash/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multihash/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.2.3"
|
||||
}
|
||||
21
vendor/github.com/multiformats/go-multistream/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-multistream/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Jeromy Johnson
|
||||
|
||||
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.
|
||||
128
vendor/github.com/multiformats/go-multistream/README.md
generated
vendored
Normal file
128
vendor/github.com/multiformats/go-multistream/README.md
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
# go-multistream
|
||||
|
||||
[](http://ipn.io)
|
||||
[](https://github.com/multiformats/multiformats)
|
||||
[](https://webchat.freenode.net/?channels=%23ipfs)
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
[](https://godoc.org/github.com/multiformats/go-multistream)
|
||||
[](https://travis-ci.org/multiformats/go-multistream)
|
||||
[](https://codecov.io/github/multiformats/go-multistream?branch=master)
|
||||
|
||||
> an implementation of the multistream protocol in go
|
||||
|
||||
This package implements a simple stream router for the multistream-select protocol.
|
||||
The protocol is defined [here](https://github.com/multiformats/multistream-select).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
`go-multistream` is a standard Go module which can be installed with:
|
||||
|
||||
```sh
|
||||
go get github.com/multiformats/go-multistream
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Example
|
||||
|
||||
This example shows how to use a multistream muxer. A muxer uses user-added handlers to handle different "protocols". The first step when interacting with a connection handler by the muxer is to select the protocol (the example uses `SelectProtoOrFail`). This will then let the muxer use the right handler.
|
||||
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
|
||||
ms "github.com/multiformats/go-multistream"
|
||||
)
|
||||
|
||||
// This example creates a multistream muxer, adds handlers for the protocols
|
||||
// "/cats" and "/dogs" and exposes it on a localhost:8765. It then opens connections
|
||||
// to that port, selects the protocols and tests that the handlers are working.
|
||||
func main() {
|
||||
mux := ms.NewMultistreamMuxer[string]()
|
||||
mux.AddHandler("/cats", func(proto string, rwc io.ReadWriteCloser) error {
|
||||
fmt.Fprintln(rwc, proto, ": HELLO I LIKE CATS")
|
||||
return rwc.Close()
|
||||
})
|
||||
mux.AddHandler("/dogs", func(proto string, rwc io.ReadWriteCloser) error {
|
||||
fmt.Fprintln(rwc, proto, ": HELLO I LIKE DOGS")
|
||||
return rwc.Close()
|
||||
})
|
||||
|
||||
list, err := net.Listen("tcp", ":8765")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
con, err := list.Accept()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go mux.Handle(con)
|
||||
}
|
||||
}()
|
||||
|
||||
// The Muxer is ready, let's test it
|
||||
conn, err := net.Dial("tcp", ":8765")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create a new multistream to talk to the muxer
|
||||
// which will negotiate that we want to talk with /cats
|
||||
mstream := ms.NewMSSelect(conn, "/cats")
|
||||
cats, err := ioutil.ReadAll(mstream)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%s", cats)
|
||||
mstream.Close()
|
||||
|
||||
// A different way of talking to the muxer
|
||||
// is to manually selecting the protocol ourselves
|
||||
conn, err = net.Dial("tcp", ":8765")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
err = ms.SelectProtoOrFail("/dogs", conn)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dogs, err := ioutil.ReadAll(conn)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%s", dogs)
|
||||
conn.Close()
|
||||
}
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multistream/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © 2016 Jeromy Johnson
|
||||
151
vendor/github.com/multiformats/go-multistream/client.go
generated
vendored
Normal file
151
vendor/github.com/multiformats/go-multistream/client.go
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
package multistream
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
// ErrNotSupported is the error returned when the muxer doesn't support
|
||||
// the protocols tried for the handshake.
|
||||
type ErrNotSupported[T StringLike] struct {
|
||||
|
||||
// Slice of protocols that were not supported by the muxer
|
||||
Protos []T
|
||||
}
|
||||
|
||||
func (e ErrNotSupported[T]) Error() string {
|
||||
return fmt.Sprintf("protocols not supported: %v", e.Protos)
|
||||
}
|
||||
|
||||
func (e ErrNotSupported[T]) Is(target error) bool {
|
||||
_, ok := target.(ErrNotSupported[T])
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrNoProtocols is the error returned when the no protocols have been
|
||||
// specified.
|
||||
var ErrNoProtocols = errors.New("no protocols specified")
|
||||
|
||||
// SelectProtoOrFail performs the initial multistream handshake
|
||||
// to inform the muxer of the protocol that will be used to communicate
|
||||
// on this ReadWriteCloser. It returns an error if, for example,
|
||||
// the muxer does not know how to handle this protocol.
|
||||
func SelectProtoOrFail[T StringLike](proto T, rwc io.ReadWriteCloser) (err error) {
|
||||
defer func() {
|
||||
if rerr := recover(); rerr != nil {
|
||||
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
|
||||
err = fmt.Errorf("panic selecting protocol: %s", rerr)
|
||||
}
|
||||
}()
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
var buf bytes.Buffer
|
||||
if err := delitmWriteAll(&buf, []byte(ProtocolID), []byte(proto)); err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
}
|
||||
_, err := io.Copy(rwc, &buf)
|
||||
errCh <- err
|
||||
}()
|
||||
// We have to read *both* errors.
|
||||
err1 := readMultistreamHeader(rwc)
|
||||
err2 := readProto(proto, rwc)
|
||||
if werr := <-errCh; werr != nil {
|
||||
return werr
|
||||
}
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SelectOneOf will perform handshakes with the protocols on the given slice
|
||||
// until it finds one which is supported by the muxer.
|
||||
func SelectOneOf[T StringLike](protos []T, rwc io.ReadWriteCloser) (proto T, err error) {
|
||||
defer func() {
|
||||
if rerr := recover(); rerr != nil {
|
||||
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
|
||||
err = fmt.Errorf("panic selecting one of protocols: %s", rerr)
|
||||
}
|
||||
}()
|
||||
|
||||
if len(protos) == 0 {
|
||||
return "", ErrNoProtocols
|
||||
}
|
||||
|
||||
// Use SelectProtoOrFail to pipeline the /multistream/1.0.0 handshake
|
||||
// with an attempt to negotiate the first protocol. If that fails, we
|
||||
// can continue negotiating the rest of the protocols normally.
|
||||
//
|
||||
// This saves us a round trip.
|
||||
switch err := SelectProtoOrFail(protos[0], rwc); err.(type) {
|
||||
case nil:
|
||||
return protos[0], nil
|
||||
case ErrNotSupported[T]: // try others
|
||||
default:
|
||||
return "", err
|
||||
}
|
||||
proto, err = selectProtosOrFail(protos[1:], rwc)
|
||||
if _, ok := err.(ErrNotSupported[T]); ok {
|
||||
return "", ErrNotSupported[T]{protos}
|
||||
}
|
||||
return proto, err
|
||||
}
|
||||
|
||||
func selectProtosOrFail[T StringLike](protos []T, rwc io.ReadWriteCloser) (T, error) {
|
||||
for _, p := range protos {
|
||||
err := trySelect(p, rwc)
|
||||
switch err := err.(type) {
|
||||
case nil:
|
||||
return p, nil
|
||||
case ErrNotSupported[T]:
|
||||
default:
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return "", ErrNotSupported[T]{protos}
|
||||
}
|
||||
|
||||
func readMultistreamHeader(r io.Reader) error {
|
||||
tok, err := ReadNextToken[string](r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tok != ProtocolID {
|
||||
return errors.New("received mismatch in protocol id")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func trySelect[T StringLike](proto T, rwc io.ReadWriteCloser) error {
|
||||
err := delimWriteBuffered(rwc, []byte(proto))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return readProto(proto, rwc)
|
||||
}
|
||||
|
||||
func readProto[T StringLike](proto T, r io.Reader) error {
|
||||
tok, err := ReadNextToken[T](r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tok {
|
||||
case proto:
|
||||
return nil
|
||||
case "na":
|
||||
return ErrNotSupported[T]{[]T{proto}}
|
||||
default:
|
||||
return fmt.Errorf("unrecognized response: %s", tok)
|
||||
}
|
||||
}
|
||||
160
vendor/github.com/multiformats/go-multistream/lazyClient.go
generated
vendored
Normal file
160
vendor/github.com/multiformats/go-multistream/lazyClient.go
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
package multistream
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// NewMSSelect returns a new Multistream which is able to perform
|
||||
// protocol selection with a MultistreamMuxer.
|
||||
func NewMSSelect[T StringLike](c io.ReadWriteCloser, proto T) LazyConn {
|
||||
return &lazyClientConn[T]{
|
||||
protos: []T{ProtocolID, proto},
|
||||
con: c,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMultistream returns a multistream for the given protocol. This will not
|
||||
// perform any protocol selection. If you are using a MultistreamMuxer, use
|
||||
// NewMSSelect.
|
||||
func NewMultistream[T StringLike](c io.ReadWriteCloser, proto T) LazyConn {
|
||||
return &lazyClientConn[T]{
|
||||
protos: []T{proto},
|
||||
con: c,
|
||||
}
|
||||
}
|
||||
|
||||
// lazyClientConn is a ReadWriteCloser adapter that lazily negotiates a protocol
|
||||
// using multistream-select on first use.
|
||||
//
|
||||
// It *does not* block writes waiting for the other end to respond. Instead, it
|
||||
// simply assumes the negotiation went successfully and starts writing data.
|
||||
// See: https://github.com/multiformats/go-multistream/issues/20
|
||||
type lazyClientConn[T StringLike] struct {
|
||||
// Used to ensure we only trigger the write half of the handshake once.
|
||||
rhandshakeOnce sync.Once
|
||||
rerr error
|
||||
|
||||
// Used to ensure we only trigger the read half of the handshake once.
|
||||
whandshakeOnce sync.Once
|
||||
werr error
|
||||
|
||||
// The sequence of protocols to negotiate.
|
||||
protos []T
|
||||
|
||||
// The inner connection.
|
||||
con io.ReadWriteCloser
|
||||
}
|
||||
|
||||
// Read reads data from the io.ReadWriteCloser.
|
||||
//
|
||||
// If the protocol hasn't yet been negotiated, this method triggers the write
|
||||
// half of the handshake and then waits for the read half to complete.
|
||||
//
|
||||
// It returns an error if the read half of the handshake fails.
|
||||
func (l *lazyClientConn[T]) Read(b []byte) (int, error) {
|
||||
l.rhandshakeOnce.Do(func() {
|
||||
go l.whandshakeOnce.Do(l.doWriteHandshake)
|
||||
l.doReadHandshake()
|
||||
})
|
||||
if l.rerr != nil {
|
||||
return 0, l.rerr
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return l.con.Read(b)
|
||||
}
|
||||
|
||||
func (l *lazyClientConn[T]) doReadHandshake() {
|
||||
for _, proto := range l.protos {
|
||||
// read protocol
|
||||
tok, err := ReadNextToken[T](l.con)
|
||||
if err != nil {
|
||||
l.rerr = err
|
||||
return
|
||||
}
|
||||
|
||||
if tok == "na" {
|
||||
l.rerr = ErrNotSupported[T]{[]T{proto}}
|
||||
return
|
||||
}
|
||||
if tok != proto {
|
||||
l.rerr = fmt.Errorf("protocol mismatch in lazy handshake ( %s != %s )", tok, proto)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *lazyClientConn[T]) doWriteHandshake() {
|
||||
l.doWriteHandshakeWithData(nil)
|
||||
}
|
||||
|
||||
// Perform the write handshake but *also* write some extra data.
|
||||
func (l *lazyClientConn[T]) doWriteHandshakeWithData(extra []byte) int {
|
||||
buf := getWriter(l.con)
|
||||
defer putWriter(buf)
|
||||
|
||||
for _, proto := range l.protos {
|
||||
l.werr = delimWrite(buf, []byte(proto))
|
||||
if l.werr != nil {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
n := 0
|
||||
if len(extra) > 0 {
|
||||
n, l.werr = buf.Write(extra)
|
||||
if l.werr != nil {
|
||||
return n
|
||||
}
|
||||
}
|
||||
l.werr = buf.Flush()
|
||||
return n
|
||||
}
|
||||
|
||||
// Write writes the given buffer to the underlying connection.
|
||||
//
|
||||
// If the protocol has not yet been negotiated, write waits for the write half
|
||||
// of the handshake to complete triggers (but does not wait for) the read half.
|
||||
//
|
||||
// Write *also* ignores errors from the read half of the handshake (in case the
|
||||
// stream is actually write only).
|
||||
func (l *lazyClientConn[T]) Write(b []byte) (int, error) {
|
||||
n := 0
|
||||
l.whandshakeOnce.Do(func() {
|
||||
go l.rhandshakeOnce.Do(l.doReadHandshake)
|
||||
n = l.doWriteHandshakeWithData(b)
|
||||
})
|
||||
if l.werr != nil || n > 0 {
|
||||
return n, l.werr
|
||||
}
|
||||
return l.con.Write(b)
|
||||
}
|
||||
|
||||
// Close closes the underlying io.ReadWriteCloser
|
||||
//
|
||||
// This does not flush anything.
|
||||
func (l *lazyClientConn[T]) Close() error {
|
||||
// As the client, we flush the handshake on close to cover an
|
||||
// interesting edge-case where the server only speaks a single protocol
|
||||
// and responds eagerly with that protocol before waiting for out
|
||||
// handshake.
|
||||
//
|
||||
// Again, we must not read the error because the other end may have
|
||||
// closed the stream for reading. I mean, we're the initiator so that's
|
||||
// strange... but it's still allowed
|
||||
_ = l.Flush()
|
||||
return l.con.Close()
|
||||
}
|
||||
|
||||
// Flush sends the handshake.
|
||||
func (l *lazyClientConn[T]) Flush() error {
|
||||
l.whandshakeOnce.Do(func() {
|
||||
go l.rhandshakeOnce.Do(l.doReadHandshake)
|
||||
l.doWriteHandshake()
|
||||
})
|
||||
return l.werr
|
||||
}
|
||||
344
vendor/github.com/multiformats/go-multistream/multistream.go
generated
vendored
Normal file
344
vendor/github.com/multiformats/go-multistream/multistream.go
generated
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
// Package multistream implements a simple stream router for the
|
||||
// multistream-select protocoli. The protocol is defined at
|
||||
// https://github.com/multiformats/multistream-select
|
||||
package multistream
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
|
||||
"github.com/multiformats/go-varint"
|
||||
)
|
||||
|
||||
// ErrTooLarge is an error to signal that an incoming message was too large
|
||||
var ErrTooLarge = errors.New("incoming message was too large")
|
||||
|
||||
// ProtocolID identifies the multistream protocol itself and makes sure
|
||||
// the multistream muxers on both sides of a channel can work with each other.
|
||||
const ProtocolID = "/multistream/1.0.0"
|
||||
|
||||
var writerPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return bufio.NewWriter(nil)
|
||||
},
|
||||
}
|
||||
|
||||
// StringLike is an interface that supports all types with underlying type
|
||||
// string
|
||||
type StringLike interface {
|
||||
~string
|
||||
}
|
||||
|
||||
// HandlerFunc is a user-provided function used by the MultistreamMuxer to
|
||||
// handle a protocol/stream.
|
||||
type HandlerFunc[T StringLike] func(protocol T, rwc io.ReadWriteCloser) error
|
||||
|
||||
// Handler is a wrapper to HandlerFunc which attaches a name (protocol) and a
|
||||
// match function which can optionally be used to select a handler by other
|
||||
// means than the name.
|
||||
type Handler[T StringLike] struct {
|
||||
MatchFunc func(T) bool
|
||||
Handle HandlerFunc[T]
|
||||
AddName T
|
||||
}
|
||||
|
||||
// MultistreamMuxer is a muxer for multistream. Depending on the stream
|
||||
// protocol tag it will select the right handler and hand the stream off to it.
|
||||
type MultistreamMuxer[T StringLike] struct {
|
||||
handlerlock sync.RWMutex
|
||||
handlers []Handler[T]
|
||||
}
|
||||
|
||||
// NewMultistreamMuxer creates a muxer.
|
||||
func NewMultistreamMuxer[T StringLike]() *MultistreamMuxer[T] {
|
||||
return new(MultistreamMuxer[T])
|
||||
}
|
||||
|
||||
// LazyConn is the connection type returned by the lazy negotiation functions.
|
||||
type LazyConn interface {
|
||||
io.ReadWriteCloser
|
||||
// Flush flushes the lazy negotiation, if any.
|
||||
Flush() error
|
||||
}
|
||||
|
||||
func writeUvarint(w io.Writer, i uint64) error {
|
||||
varintbuf := make([]byte, 16)
|
||||
n := varint.PutUvarint(varintbuf, i)
|
||||
_, err := w.Write(varintbuf[:n])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func delimWriteBuffered(w io.Writer, mes []byte) error {
|
||||
bw := getWriter(w)
|
||||
defer putWriter(bw)
|
||||
|
||||
err := delimWrite(bw, mes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bw.Flush()
|
||||
}
|
||||
|
||||
func delitmWriteAll(w io.Writer, messages ...[]byte) error {
|
||||
for _, mes := range messages {
|
||||
if err := delimWrite(w, mes); err != nil {
|
||||
return fmt.Errorf("failed to write messages %s, err: %v ", string(mes), err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func delimWrite(w io.Writer, mes []byte) error {
|
||||
err := writeUvarint(w, uint64(len(mes)+1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.Write(mes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.Write([]byte{'\n'})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fulltextMatch[T StringLike](s T) func(T) bool {
|
||||
return func(a T) bool {
|
||||
return a == s
|
||||
}
|
||||
}
|
||||
|
||||
// AddHandler attaches a new protocol handler to the muxer.
|
||||
func (msm *MultistreamMuxer[T]) AddHandler(protocol T, handler HandlerFunc[T]) {
|
||||
msm.AddHandlerWithFunc(protocol, fulltextMatch(protocol), handler)
|
||||
}
|
||||
|
||||
// AddHandlerWithFunc attaches a new protocol handler to the muxer with a match.
|
||||
// If the match function returns true for a given protocol tag, the protocol
|
||||
// will be selected even if the handler name and protocol tags are different.
|
||||
func (msm *MultistreamMuxer[T]) AddHandlerWithFunc(protocol T, match func(T) bool, handler HandlerFunc[T]) {
|
||||
msm.handlerlock.Lock()
|
||||
defer msm.handlerlock.Unlock()
|
||||
|
||||
msm.removeHandler(protocol)
|
||||
msm.handlers = append(msm.handlers, Handler[T]{
|
||||
MatchFunc: match,
|
||||
Handle: handler,
|
||||
AddName: protocol,
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveHandler removes the handler with the given name from the muxer.
|
||||
func (msm *MultistreamMuxer[T]) RemoveHandler(protocol T) {
|
||||
msm.handlerlock.Lock()
|
||||
defer msm.handlerlock.Unlock()
|
||||
|
||||
msm.removeHandler(protocol)
|
||||
}
|
||||
|
||||
func (msm *MultistreamMuxer[T]) removeHandler(protocol T) {
|
||||
for i, h := range msm.handlers {
|
||||
if h.AddName == protocol {
|
||||
msm.handlers = append(msm.handlers[:i], msm.handlers[i+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Protocols returns the list of handler-names added to this this muxer.
|
||||
func (msm *MultistreamMuxer[T]) Protocols() []T {
|
||||
msm.handlerlock.RLock()
|
||||
defer msm.handlerlock.RUnlock()
|
||||
|
||||
var out []T
|
||||
for _, h := range msm.handlers {
|
||||
out = append(out, h.AddName)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// ErrIncorrectVersion is an error reported when the muxer protocol negotiation
|
||||
// fails because of a ProtocolID mismatch.
|
||||
var ErrIncorrectVersion = errors.New("client connected with incorrect version")
|
||||
|
||||
func (msm *MultistreamMuxer[T]) findHandler(proto T) *Handler[T] {
|
||||
msm.handlerlock.RLock()
|
||||
defer msm.handlerlock.RUnlock()
|
||||
|
||||
for _, h := range msm.handlers {
|
||||
if h.MatchFunc(proto) {
|
||||
return &h
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Negotiate performs protocol selection and returns the protocol name and
|
||||
// the matching handler function for it (or an error).
|
||||
func (msm *MultistreamMuxer[T]) Negotiate(rwc io.ReadWriteCloser) (proto T, handler HandlerFunc[T], err error) {
|
||||
defer func() {
|
||||
if rerr := recover(); rerr != nil {
|
||||
fmt.Fprintf(os.Stderr, "caught panic: %s\n%s\n", rerr, debug.Stack())
|
||||
err = fmt.Errorf("panic in multistream negotiation: %s", rerr)
|
||||
}
|
||||
}()
|
||||
|
||||
// Send the multistream protocol ID
|
||||
// Ignore the error here. We want the handshake to finish, even if the
|
||||
// other side has closed this rwc for writing. They may have sent us a
|
||||
// message and closed. Future writers will get an error anyways.
|
||||
_ = delimWriteBuffered(rwc, []byte(ProtocolID))
|
||||
line, err := ReadNextToken[T](rwc)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if line != ProtocolID {
|
||||
rwc.Close()
|
||||
return "", nil, ErrIncorrectVersion
|
||||
}
|
||||
|
||||
loop:
|
||||
for {
|
||||
// Now read and respond to commands until they send a valid protocol id
|
||||
tok, err := ReadNextToken[T](rwc)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
h := msm.findHandler(tok)
|
||||
if h == nil {
|
||||
if err := delimWriteBuffered(rwc, []byte("na")); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
continue loop
|
||||
}
|
||||
|
||||
// Ignore the error here. We want the handshake to finish, even if the
|
||||
// other side has closed this rwc for writing. They may have sent us a
|
||||
// message and closed. Future writers will get an error anyways.
|
||||
_ = delimWriteBuffered(rwc, []byte(tok))
|
||||
|
||||
// hand off processing to the sub-protocol handler
|
||||
return tok, h.Handle, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Handle performs protocol negotiation on a ReadWriteCloser
|
||||
// (i.e. a connection). It will find a matching handler for the
|
||||
// incoming protocol and pass the ReadWriteCloser to it.
|
||||
func (msm *MultistreamMuxer[T]) Handle(rwc io.ReadWriteCloser) error {
|
||||
p, h, err := msm.Negotiate(rwc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return h(p, rwc)
|
||||
}
|
||||
|
||||
// ReadNextToken extracts a token from a Reader. It is used during
|
||||
// protocol negotiation and returns a string.
|
||||
func ReadNextToken[T StringLike](r io.Reader) (T, error) {
|
||||
tok, err := ReadNextTokenBytes(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return T(tok), nil
|
||||
}
|
||||
|
||||
// ReadNextTokenBytes extracts a token from a Reader. It is used
|
||||
// during protocol negotiation and returns a byte slice.
|
||||
func ReadNextTokenBytes(r io.Reader) ([]byte, error) {
|
||||
data, err := lpReadBuf(r)
|
||||
switch err {
|
||||
case nil:
|
||||
return data, nil
|
||||
case ErrTooLarge:
|
||||
return nil, ErrTooLarge
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func lpReadBuf(r io.Reader) ([]byte, error) {
|
||||
br, ok := r.(io.ByteReader)
|
||||
if !ok {
|
||||
br = &byteReader{r}
|
||||
}
|
||||
|
||||
length, err := varint.ReadUvarint(br)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if length > 1024 {
|
||||
return nil, ErrTooLarge
|
||||
}
|
||||
|
||||
buf := make([]byte, length)
|
||||
_, err = io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(buf) == 0 || buf[length-1] != '\n' {
|
||||
return nil, errors.New("message did not have trailing newline")
|
||||
}
|
||||
|
||||
// slice off the trailing newline
|
||||
buf = buf[:length-1]
|
||||
|
||||
return buf, nil
|
||||
|
||||
}
|
||||
|
||||
// byteReader implements the ByteReader interface that ReadUVarint requires
|
||||
type byteReader struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
func (br *byteReader) ReadByte() (byte, error) {
|
||||
var b [1]byte
|
||||
n, err := br.Read(b[:])
|
||||
if n == 1 {
|
||||
return b[0], nil
|
||||
}
|
||||
if err == nil {
|
||||
if n != 0 {
|
||||
panic("read more bytes than buffer size")
|
||||
}
|
||||
err = io.ErrNoProgress
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func getWriter(w io.Writer) *bufio.Writer {
|
||||
bw := writerPool.Get().(*bufio.Writer)
|
||||
bw.Reset(w)
|
||||
return bw
|
||||
}
|
||||
|
||||
func putWriter(bw *bufio.Writer) {
|
||||
bw.Reset(nil)
|
||||
writerPool.Put(bw)
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-multistream/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-multistream/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.4.1"
|
||||
}
|
||||
21
vendor/github.com/multiformats/go-varint/LICENSE
generated
vendored
Normal file
21
vendor/github.com/multiformats/go-varint/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Protocol Labs
|
||||
|
||||
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.
|
||||
35
vendor/github.com/multiformats/go-varint/README.md
generated
vendored
Normal file
35
vendor/github.com/multiformats/go-varint/README.md
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# go-varint
|
||||
|
||||
[](https://protocol.ai)
|
||||
[](https://github.com/multiformats/multiformats)
|
||||
[](https://webchat.freenode.net/?channels=%23ipfs)
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
[](https://godoc.org/github.com/multiformats/go-varint)
|
||||
[](https://travis-ci.org/multiformats/go-varint)
|
||||
[](https://codecov.io/github/multiformats/go-varint?branch=master)
|
||||
|
||||
> Varint helpers that enforce minimal encoding.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
go get github.com/multiformats/go-varint
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multiaddr/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © 2019 Protocol Labs
|
||||
2
vendor/github.com/multiformats/go-varint/codecov.yml
generated
vendored
Normal file
2
vendor/github.com/multiformats/go-varint/codecov.yml
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
ignore:
|
||||
- "multiaddr"
|
||||
115
vendor/github.com/multiformats/go-varint/varint.go
generated
vendored
Normal file
115
vendor/github.com/multiformats/go-varint/varint.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
package varint
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrOverflow = errors.New("varints larger than uint63 not supported")
|
||||
ErrUnderflow = errors.New("varints malformed, could not reach the end")
|
||||
ErrNotMinimal = errors.New("varint not minimally encoded")
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxLenUvarint63 is the maximum number of bytes representing an uvarint in
|
||||
// this encoding, supporting a maximum value of 2^63 (uint63), aka
|
||||
// MaxValueUvarint63.
|
||||
MaxLenUvarint63 = 9
|
||||
|
||||
// MaxValueUvarint63 is the maximum encodable uint63 value.
|
||||
MaxValueUvarint63 = (1 << 63) - 1
|
||||
)
|
||||
|
||||
// UvarintSize returns the size (in bytes) of `num` encoded as a unsigned varint.
|
||||
//
|
||||
// This may return a size greater than MaxUvarintLen63, which would be an
|
||||
// illegal value, and would be rejected by readers.
|
||||
func UvarintSize(num uint64) int {
|
||||
bits := bits.Len64(num)
|
||||
q, r := bits/7, bits%7
|
||||
size := q
|
||||
if r > 0 || size == 0 {
|
||||
size++
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// ToUvarint converts an unsigned integer to a varint-encoded []byte
|
||||
func ToUvarint(num uint64) []byte {
|
||||
buf := make([]byte, UvarintSize(num))
|
||||
n := binary.PutUvarint(buf, uint64(num))
|
||||
return buf[:n]
|
||||
}
|
||||
|
||||
// FromUvarint reads an unsigned varint from the beginning of buf, returns the
|
||||
// varint, and the number of bytes read.
|
||||
func FromUvarint(buf []byte) (uint64, int, error) {
|
||||
// Modified from the go standard library. Copyright the Go Authors and
|
||||
// released under the BSD License.
|
||||
var x uint64
|
||||
var s uint
|
||||
for i, b := range buf {
|
||||
if (i == 8 && b >= 0x80) || i >= MaxLenUvarint63 {
|
||||
// this is the 9th and last byte we're willing to read, but it
|
||||
// signals there's more (1 in MSB).
|
||||
// or this is the >= 10th byte, and for some reason we're still here.
|
||||
return 0, 0, ErrOverflow
|
||||
}
|
||||
if b < 0x80 {
|
||||
if b == 0 && s > 0 {
|
||||
return 0, 0, ErrNotMinimal
|
||||
}
|
||||
return x | uint64(b)<<s, i + 1, nil
|
||||
}
|
||||
x |= uint64(b&0x7f) << s
|
||||
s += 7
|
||||
}
|
||||
return 0, 0, ErrUnderflow
|
||||
}
|
||||
|
||||
// ReadUvarint reads a unsigned varint from the given reader.
|
||||
func ReadUvarint(r io.ByteReader) (uint64, error) {
|
||||
// Modified from the go standard library. Copyright the Go Authors and
|
||||
// released under the BSD License.
|
||||
var x uint64
|
||||
var s uint
|
||||
for s = 0; ; s += 7 {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
if err == io.EOF && s != 0 {
|
||||
// "eof" will look like a success.
|
||||
// If we've read part of a value, this is not a
|
||||
// success.
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
if (s == 56 && b >= 0x80) || s >= (7*MaxLenUvarint63) {
|
||||
// this is the 9th and last byte we're willing to read, but it
|
||||
// signals there's more (1 in MSB).
|
||||
// or this is the >= 10th byte, and for some reason we're still here.
|
||||
return 0, ErrOverflow
|
||||
}
|
||||
if b < 0x80 {
|
||||
if b == 0 && s > 0 {
|
||||
return 0, ErrNotMinimal
|
||||
}
|
||||
return x | uint64(b)<<s, nil
|
||||
}
|
||||
x |= uint64(b&0x7f) << s
|
||||
}
|
||||
}
|
||||
|
||||
// PutUvarint is an alias for binary.PutUvarint.
|
||||
//
|
||||
// This is provided for convenience so users of this library can avoid built-in
|
||||
// varint functions and easily audit code for uses of those functions.
|
||||
//
|
||||
// Make sure that x is smaller or equal to MaxValueUvarint63, otherwise this
|
||||
// function will produce values that may be rejected by readers.
|
||||
func PutUvarint(buf []byte, x uint64) int {
|
||||
return binary.PutUvarint(buf, x)
|
||||
}
|
||||
3
vendor/github.com/multiformats/go-varint/version.json
generated
vendored
Normal file
3
vendor/github.com/multiformats/go-varint/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.0.7"
|
||||
}
|
||||
Reference in New Issue
Block a user