mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-02 20:53:24 -04:00
update the common library to the master branch
This commit is contained in:
@ -75,7 +75,10 @@ func (c *Certificate) RawBytes() []byte {
|
|||||||
|
|
||||||
// ExcessBytes returns the excess bytes in a certificate found after the specified payload length.
|
// ExcessBytes returns the excess bytes in a certificate found after the specified payload length.
|
||||||
func (c *Certificate) ExcessBytes() []byte {
|
func (c *Certificate) ExcessBytes() []byte {
|
||||||
return c.payload[c.len.Int():]
|
if len(c.payload) >= c.len.Int() {
|
||||||
|
return c.payload[c.len.Int():]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the entire certificate in []byte form, trims payload to specified length.
|
// Bytes returns the entire certificate in []byte form, trims payload to specified length.
|
||||||
@ -116,8 +119,8 @@ func (c *Certificate) Data() (data []byte) {
|
|||||||
|
|
||||||
// NewCertificate creates a new Certficiate from []byte
|
// NewCertificate creates a new Certficiate from []byte
|
||||||
// returns err if the certificate is too short or if the payload doesn't match specified length.
|
// returns err if the certificate is too short or if the payload doesn't match specified length.
|
||||||
func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
func NewCertificate(data []byte) (certificate Certificate, err error) {
|
||||||
certificate = &Certificate{}
|
certificate = Certificate{}
|
||||||
switch len(data) {
|
switch len(data) {
|
||||||
case 0:
|
case 0:
|
||||||
certificate.kind = Integer([]byte{0})
|
certificate.kind = Integer([]byte{0})
|
||||||
@ -126,29 +129,19 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
|||||||
"at": "(Certificate) NewCertificate",
|
"at": "(Certificate) NewCertificate",
|
||||||
"certificate_bytes_length": len(data),
|
"certificate_bytes_length": len(data),
|
||||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
||||||
}).Error("invalid certificate")
|
}).Error("invalid certificate, empty")
|
||||||
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
err = fmt.Errorf("error parsing certificate: certificate is empty")
|
||||||
return
|
return
|
||||||
case 1:
|
case 1, 2:
|
||||||
certificate.kind = Integer(data[0:0])
|
certificate.kind = Integer(data[0 : len(data)-1])
|
||||||
certificate.len = Integer([]byte{0})
|
certificate.len = Integer([]byte{0})
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Certificate) NewCertificate",
|
"at": "(Certificate) NewCertificate",
|
||||||
"certificate_bytes_length": len(data),
|
"certificate_bytes_length": len(data),
|
||||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
||||||
}).Error("invalid certificate")
|
}).Error("invalid certificate, too short")
|
||||||
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
err = fmt.Errorf("error parsing certificate: certificate is too short")
|
||||||
return
|
return
|
||||||
case 2:
|
|
||||||
certificate.kind = Integer(data[0:1])
|
|
||||||
certificate.len = Integer([]byte{0})
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(Certificate) NewCertificate",
|
|
||||||
"certificate_bytes_length": len(data),
|
|
||||||
"reason": "too short (len < CERT_MIN_SIZE)" + fmt.Sprintf("%d", certificate.kind.Int()),
|
|
||||||
}).Error("invalid certificate")
|
|
||||||
err = fmt.Errorf("error parsing certificate length: certificate is too short")
|
|
||||||
return
|
|
||||||
default:
|
default:
|
||||||
certificate.kind = Integer(data[0:1])
|
certificate.kind = Integer(data[0:1])
|
||||||
certificate.len = Integer(data[1:3])
|
certificate.len = Integer(data[1:3])
|
||||||
@ -160,17 +153,11 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
|||||||
"at": "(Certificate) NewCertificate",
|
"at": "(Certificate) NewCertificate",
|
||||||
"certificate_bytes_length": certificate.len.Int(),
|
"certificate_bytes_length": certificate.len.Int(),
|
||||||
"certificate_payload_length": payleng,
|
"certificate_payload_length": payleng,
|
||||||
|
"data_bytes:": string(data),
|
||||||
|
"kind_bytes": data[0:1],
|
||||||
|
"len_bytes": data[1:3],
|
||||||
"reason": err.Error(),
|
"reason": err.Error(),
|
||||||
}).Error("invalid certificate")
|
}).Error("invalid certificate, shorter than specified by length")
|
||||||
return
|
|
||||||
} else if certificate.len.Int() < len(data)-CERT_MIN_SIZE {
|
|
||||||
err = fmt.Errorf("certificate parsing warning: certificate data is longer than specified by length")
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(Certificate) NewCertificate",
|
|
||||||
"certificate_bytes_length": certificate.len.Int(),
|
|
||||||
"certificate_payload_length": payleng,
|
|
||||||
"reason": err.Error(),
|
|
||||||
}).Error("invalid certificate")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -179,11 +166,11 @@ func NewCertificate(data []byte) (certificate *Certificate, err error) {
|
|||||||
|
|
||||||
// ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at the end of the input.
|
// ReadCertificate creates a Certificate from []byte and returns any ExcessBytes at the end of the input.
|
||||||
// returns err if the certificate could not be read.
|
// returns err if the certificate could not be read.
|
||||||
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
|
func ReadCertificate(data []byte) (certificate Certificate, remainder []byte, err error) {
|
||||||
certificate, err = NewCertificate(data)
|
certificate, err = NewCertificate(data)
|
||||||
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
|
if err != nil && err.Error() == "certificate parsing warning: certificate data is longer than specified by length" {
|
||||||
remainder = certificate.ExcessBytes()
|
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
|
remainder = certificate.ExcessBytes()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,12 @@ func TestCertificateLengthErrWhenTooShort(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
bytes := []byte{0x03, 0x01}
|
bytes := []byte{0x03, 0x01}
|
||||||
certificate, err := NewCertificate(bytes)
|
certificate, _, err := ReadCertificate(bytes)
|
||||||
cert_len := certificate.Length()
|
cert_len := certificate.Length()
|
||||||
|
|
||||||
assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data")
|
assert.Equal(cert_len, 0, "certificate.Length() did not return zero length for missing length data")
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned")
|
assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,13 +71,10 @@ func TestCertificateDataWhenTooLong(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
|
bytes := []byte{0x03, 0x00, 0x02, 0xff, 0xff, 0xaa, 0xaa}
|
||||||
certificate, err := NewCertificate(bytes)
|
certificate, _, _ := ReadCertificate(bytes)
|
||||||
cert_data := certificate.Data()
|
cert_data := certificate.Data()
|
||||||
|
|
||||||
if assert.NotNil(err) {
|
cert_len := certificate.Length() // len(cert_data)
|
||||||
assert.Equal("certificate parsing warning: certificate data is longer than specified by length", err.Error(), "correct error message should be returned")
|
|
||||||
}
|
|
||||||
cert_len := certificate.Length() //len(cert_data)
|
|
||||||
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long")
|
assert.Equal(cert_len, 2, "certificate.Length() did not return indicated length when data was too long")
|
||||||
if cert_data[0] != 0xff || cert_data[1] != 0xff {
|
if cert_data[0] != 0xff || cert_data[1] != 0xff {
|
||||||
t.Fatal("certificate.Data() returned incorrect data when data was too long")
|
t.Fatal("certificate.Data() returned incorrect data when data was too long")
|
||||||
@ -144,6 +141,6 @@ func TestReadCertificateWithInvalidLength(t *testing.T) {
|
|||||||
assert.Equal(cert.length(), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid")
|
assert.Equal(cert.length(), 2, "ReadCertificate() should populate the certificate with the provided data even when invalid")
|
||||||
assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate")
|
assert.Equal(len(remainder), 0, "ReadCertificate() returned non-zero length remainder on invalid certificate")
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("error parsing certificate length: certificate is too short", err.Error(), "correct error message should be returned")
|
assert.Equal("error parsing certificate: certificate is too short", err.Error(), "correct error message should be returned")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,13 @@ Contents
|
|||||||
// https://geti2p.net/spec/common-structures#hash
|
// https://geti2p.net/spec/common-structures#hash
|
||||||
type Hash [32]byte
|
type Hash [32]byte
|
||||||
|
|
||||||
|
func (h Hash) Bytes() [32]byte {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
// HashData returns the SHA256 sum of a []byte input as Hash.
|
// HashData returns the SHA256 sum of a []byte input as Hash.
|
||||||
func HashData(data []byte) (h Hash) {
|
func HashData(data []byte) (h Hash) {
|
||||||
|
// log.Println("Hashing Data:", data)
|
||||||
h = sha256.Sum256(data)
|
h = sha256.Sum256(data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,9 @@ func NewInteger(bytes []byte, size int) (integer *Integer, remainder []byte, err
|
|||||||
if size < MAX_INTEGER_SIZE {
|
if size < MAX_INTEGER_SIZE {
|
||||||
integerSize = size
|
integerSize = size
|
||||||
}
|
}
|
||||||
i, remainder := ReadInteger(bytes, integerSize)
|
intBytes := bytes[:integerSize]
|
||||||
|
remainder = bytes[integerSize:]
|
||||||
|
i, _ := ReadInteger(intBytes, integerSize)
|
||||||
integer = &i
|
integer = &i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -126,28 +126,25 @@ func beginsWith(bytes []byte, chr byte) bool {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
|
func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error) {
|
||||||
if len(bytes) == 0 {
|
if len(bytes) < 3 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "ReadMapping",
|
"at": "ReadMapping",
|
||||||
"reason": "zero length",
|
"reason": "zero length",
|
||||||
}).Warn("mapping format violation")
|
}).Warn("mapping format violation")
|
||||||
e := errors.New("zero length")
|
e := errors.New("zero length")
|
||||||
err = append(err, e)
|
err = append(err, e)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
size, remainder, e := NewInteger(bytes, 2)
|
size, remainder, e := NewInteger(bytes, 2)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
err = append(err, e)
|
err = append(err, e)
|
||||||
}
|
}
|
||||||
|
if size.Int() == 0 {
|
||||||
mapping.size = size
|
return
|
||||||
if e != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "ReadMapping",
|
|
||||||
"reason": "error parsing integer",
|
|
||||||
}).Warn("mapping format violation")
|
|
||||||
e := errors.New("error parsing integer")
|
|
||||||
err = append(err, e)
|
|
||||||
}
|
}
|
||||||
|
mapping.size = size
|
||||||
|
map_bytes := remainder[:mapping.size.Int()]
|
||||||
|
remainder = remainder[mapping.size.Int():]
|
||||||
if len(remainder) == 0 {
|
if len(remainder) == 0 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "ReadMapping",
|
"at": "ReadMapping",
|
||||||
@ -156,7 +153,10 @@ func ReadMapping(bytes []byte) (mapping Mapping, remainder []byte, err []error)
|
|||||||
e := errors.New("zero length")
|
e := errors.New("zero length")
|
||||||
err = append(err, e)
|
err = append(err, e)
|
||||||
}
|
}
|
||||||
vals, remainder, mappingValueErrs := ReadMappingValues(bytes)
|
// TODO: this should take the remainder and the length we already parsed above, as a parameter.
|
||||||
|
// Like tomorrow morning.
|
||||||
|
// ReadMappingValues should not attempt to figure out the length of the bytes it's reading over.
|
||||||
|
vals, _, mappingValueErrs := ReadMappingValues(map_bytes, *mapping.size)
|
||||||
|
|
||||||
err = append(err, mappingValueErrs...)
|
err = append(err, mappingValueErrs...)
|
||||||
mapping.vals = vals
|
mapping.vals = vals
|
||||||
|
@ -27,7 +27,6 @@ func TestValuesExclusesPairWithBadData(t *testing.T) {
|
|||||||
assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key")
|
assert.Equal(key, "a", "Values() returned by data with invalid key contains incorrect present key")
|
||||||
assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key")
|
assert.Equal(val, "b", "Values() returned by data with invalid key contains incorrect present key")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValuesWarnsMissingData(t *testing.T) {
|
func TestValuesWarnsMissingData(t *testing.T) {
|
||||||
|
@ -10,6 +10,17 @@ import (
|
|||||||
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
|
// MappingValues represents the parsed key value pairs inside of an I2P Mapping.
|
||||||
type MappingValues [][2]I2PString
|
type MappingValues [][2]I2PString
|
||||||
|
|
||||||
|
func (m MappingValues) Get(key I2PString) I2PString {
|
||||||
|
keyBytes, _ := key.Data()
|
||||||
|
for _, pair := range m {
|
||||||
|
kb, _ := pair[0][0:].Data()
|
||||||
|
if kb == keyBytes {
|
||||||
|
return pair[1][1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ValuesToMapping creates a *Mapping using MappingValues.
|
// ValuesToMapping creates a *Mapping using MappingValues.
|
||||||
// The values are sorted in the order defined in mappingOrder.
|
// The values are sorted in the order defined in mappingOrder.
|
||||||
func ValuesToMapping(values MappingValues) *Mapping {
|
func ValuesToMapping(values MappingValues) *Mapping {
|
||||||
@ -46,11 +57,11 @@ func mappingOrder(values MappingValues) {
|
|||||||
// ReadMappingValues returns *MappingValues from a []byte.
|
// ReadMappingValues returns *MappingValues from a []byte.
|
||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
func ReadMappingValues(remainder []byte, map_length Integer) (values *MappingValues, remainder_bytes []byte, errs []error) {
|
||||||
mapping := remainder
|
// mapping := remainder
|
||||||
//var remainder = mapping
|
// var remainder = mapping
|
||||||
//var err error
|
// var err error
|
||||||
if remainder == nil || len(remainder) < 0 {
|
if remainder == nil || len(remainder) < 1 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "data shorter than expected",
|
"reason": "data shorter than expected",
|
||||||
@ -59,31 +70,21 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
map_values := make(MappingValues, 0)
|
map_values := make(MappingValues, 0)
|
||||||
if len(remainder) < 1 {
|
int_map_length := map_length.Int()
|
||||||
log.WithFields(log.Fields{
|
mapping_len := len(remainder)
|
||||||
"at": "(Mapping) Values",
|
if mapping_len > int_map_length {
|
||||||
"reason": "data shorter than expected",
|
|
||||||
}).Error("mapping contained no data")
|
|
||||||
errs = []error{errors.New("mapping contained no data")}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
l := Integer(remainder[:2])
|
|
||||||
length := l.Int()
|
|
||||||
// - 2 bytes for map length bits
|
|
||||||
mapping_len := len(mapping) - 2
|
|
||||||
if mapping_len > length {
|
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"mapping_bytes_length": mapping_len,
|
"mapping_bytes_length": mapping_len,
|
||||||
"mapping_length_field": length,
|
"mapping_length_field": int_map_length,
|
||||||
"reason": "data longer than expected",
|
"reason": "data longer than expected",
|
||||||
}).Warn("mapping format warning")
|
}).Warn("mapping format warning")
|
||||||
errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping"))
|
errs = append(errs, errors.New("warning parsing mapping: data exists beyond length of mapping"))
|
||||||
} else if length > mapping_len {
|
} else if int_map_length > mapping_len {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"mapping_bytes_length": mapping_len,
|
"mapping_bytes_length": mapping_len,
|
||||||
"mapping_length_field": length,
|
"mapping_length_field": int_map_length,
|
||||||
"reason": "data shorter than expected",
|
"reason": "data shorter than expected",
|
||||||
}).Warn("mapping format warning")
|
}).Warn("mapping format warning")
|
||||||
errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data"))
|
errs = append(errs, errors.New("warning parsing mapping: mapping length exceeds provided data"))
|
||||||
@ -91,7 +92,7 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
|||||||
|
|
||||||
encounteredKeysMap := map[string]bool{}
|
encounteredKeysMap := map[string]bool{}
|
||||||
// pop off length bytes before parsing kv pairs
|
// pop off length bytes before parsing kv pairs
|
||||||
remainder = remainder[2:]
|
// remainder = remainder[2:]
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// Read a key, breaking on fatal errors
|
// Read a key, breaking on fatal errors
|
||||||
@ -111,16 +112,16 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
str, more, err := ReadI2PString(remainder)
|
key_str, more, err := ReadI2PString(remainder)
|
||||||
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
|
||||||
remainder = more
|
|
||||||
key_str := str
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if stopValueRead(err) {
|
if stopValueRead(err) {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
//return
|
// return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
||||||
|
remainder = more
|
||||||
|
// log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
|
||||||
|
|
||||||
// Check if key has already been encountered in this mapping
|
// Check if key has already been encountered in this mapping
|
||||||
keyBytes, _ := key_str.Data()
|
keyBytes, _ := key_str.Data()
|
||||||
@ -130,7 +131,9 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
|||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "duplicate key in mapping",
|
"reason": "duplicate key in mapping",
|
||||||
|
"key": string(key_str),
|
||||||
}).Error("mapping format violation")
|
}).Error("mapping format violation")
|
||||||
|
log.Printf("DUPE: %s", key_str)
|
||||||
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
|
errs = append(errs, errors.New("mapping format violation, duplicate key in mapping"))
|
||||||
// Based on other implementations this does not seem to happen often?
|
// Based on other implementations this does not seem to happen often?
|
||||||
// Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown.
|
// Java throws an exception in this case, the base object is a Hashmap so the value is overwritten and an exception is thrown.
|
||||||
@ -142,33 +145,39 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
|||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "expected =",
|
"reason": "expected =",
|
||||||
|
"value:": string(remainder),
|
||||||
}).Warn("mapping format violation")
|
}).Warn("mapping format violation")
|
||||||
errs = append(errs, errors.New("mapping format violation, expected ="))
|
errs = append(errs, errors.New("mapping format violation, expected ="))
|
||||||
|
log.Printf("ERRVAL: %s", remainder)
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
remainder = remainder[1:]
|
||||||
}
|
}
|
||||||
remainder = remainder[1:]
|
|
||||||
|
|
||||||
// Read a value, breaking on fatal errors
|
// Read a value, breaking on fatal errors
|
||||||
// and appending warnings
|
// and appending warnings
|
||||||
str, more, err = ReadI2PString(remainder)
|
val_str, more, err := ReadI2PString(remainder)
|
||||||
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
|
||||||
remainder = more
|
|
||||||
val_str := str
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if stopValueRead(err) {
|
if stopValueRead(err) {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
//return
|
// return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// overwriting remainder with more as another var to prevent memory weirdness in loops
|
||||||
|
remainder = more
|
||||||
|
// log.Printf("(MAPPING VALUES DEBUG) Remainder: %s\n", remainder)
|
||||||
|
// log.Printf("(MAPPING VALUES DEBUG) String: value: %s", val_str)
|
||||||
if !beginsWith(remainder, 0x3b) {
|
if !beginsWith(remainder, 0x3b) {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(Mapping) Values",
|
"at": "(Mapping) Values",
|
||||||
"reason": "expected ;",
|
"reason": "expected ;",
|
||||||
|
"value:": string(remainder),
|
||||||
}).Warn("mapping format violation")
|
}).Warn("mapping format violation")
|
||||||
errs = append(errs, errors.New("mapping format violation, expected ;"))
|
errs = append(errs, errors.New("mapping format violation, expected ;"))
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
remainder = remainder[1:]
|
||||||
}
|
}
|
||||||
remainder = remainder[1:]
|
|
||||||
|
|
||||||
// Append the key-value pair and break if there is no more data to read
|
// Append the key-value pair and break if there is no more data to read
|
||||||
map_values = append(map_values, [2]I2PString{key_str, val_str})
|
map_values = append(map_values, [2]I2PString{key_str, val_str})
|
||||||
@ -181,5 +190,4 @@ func ReadMappingValues(remainder []byte) (values *MappingValues, remainder_bytes
|
|||||||
}
|
}
|
||||||
values = &map_values
|
values = &map_values
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package data
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -38,28 +39,21 @@ func (str I2PString) Length() (length int, err error) {
|
|||||||
err = errors.New("error parsing string: zero length")
|
err = errors.New("error parsing string: zero length")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l := Integer([]byte{byte(str[0])})
|
l, _, err := NewInteger(str[:], 1)
|
||||||
|
if err != nil {
|
||||||
|
return l.Int(), err
|
||||||
|
}
|
||||||
length = l.Int()
|
length = l.Int()
|
||||||
inferred_len := length + 1
|
|
||||||
str_len := len(str)
|
str_len := len(str)
|
||||||
if inferred_len > str_len {
|
if length > str_len {
|
||||||
log.WithFields(log.Fields{
|
/*log.WithFields(log.Fields{
|
||||||
"at": "(I2PString) Length",
|
"at": "(I2PString) Length",
|
||||||
"string_bytes_length": str_len,
|
"string_bytes_length": str_len,
|
||||||
"string_length_field": length,
|
"string_length_field": length,
|
||||||
"expected_bytes_length": inferred_len,
|
"data": string(str),
|
||||||
"reason": "data shorter than specified",
|
"reason": "data less than specified by length",
|
||||||
}).Warn("string format warning")
|
}).Error("string format warning")*/
|
||||||
err = errors.New("string parsing warning: string data is shorter than specified by length")
|
err = errors.New("string parsing warning: string data is shorter than specified by length")
|
||||||
} else if str_len > inferred_len {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(I2PString) Length",
|
|
||||||
"string_bytes_length": str_len,
|
|
||||||
"string_length_field": length,
|
|
||||||
"expected_bytes_length": inferred_len,
|
|
||||||
"reason": "data longer than specified",
|
|
||||||
}).Warn("string format warning")
|
|
||||||
err = errors.New("string parsing warning: string contains data beyond length")
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -73,14 +67,20 @@ func (str I2PString) Data() (data string, err error) {
|
|||||||
case "error parsing string: zero length":
|
case "error parsing string: zero length":
|
||||||
return
|
return
|
||||||
case "string parsing warning: string data is shorter than specified by length":
|
case "string parsing warning: string data is shorter than specified by length":
|
||||||
data = string(str[1:])
|
if is, e := ToI2PString(string(str[:])); e != nil {
|
||||||
return
|
return "", e
|
||||||
|
} else {
|
||||||
|
return is.Data()
|
||||||
|
}
|
||||||
case "string parsing warning: string contains data beyond length":
|
case "string parsing warning: string contains data beyond length":
|
||||||
data = string(str[1 : length+1])
|
data = string(str[1:])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = string(str[1:])
|
if length == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data = string(str[1 : length+1])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,20 +113,25 @@ func ToI2PString(data string) (str I2PString, err error) {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
func ReadI2PString(data []byte) (str I2PString, remainder []byte, err error) {
|
||||||
str = I2PString(data)
|
length, _, err := NewInteger(data, 1)
|
||||||
length, err := I2PString(data).Length()
|
if err != nil {
|
||||||
if err != nil && err.Error() == "string parsing warning: string contains data beyond length" {
|
return
|
||||||
str = I2PString(data[:length+1])
|
}
|
||||||
remainder = data[length+1:]
|
data_len := length.Int() + 1
|
||||||
err = nil
|
str = data[:data_len]
|
||||||
|
remainder = data[data_len:]
|
||||||
|
l, err := str.Length()
|
||||||
|
if l != data_len-1 {
|
||||||
|
err = fmt.Errorf("error reading I2P string, length does not match data")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewI2PString creates a new *I2PString from []byte using ReadI2PString.
|
// NewI2PString creates a new *I2PString from []byte using ReadI2PString.
|
||||||
// Returns a pointer to I2PString unlike ReadI2PString.
|
// Returns a pointer to I2PString unlike ReadI2PString.
|
||||||
func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) {
|
/*func NewI2PString(data []byte) (str *I2PString, remainder []byte, err error) {
|
||||||
objstr, remainder, err := ReadI2PString(data)
|
objstr, remainder, err := ReadI2PString(data)
|
||||||
str = &objstr
|
str = &objstr
|
||||||
return
|
return
|
||||||
}
|
}*/
|
||||||
|
@ -26,7 +26,7 @@ Identical to KeysAndCert.
|
|||||||
//
|
//
|
||||||
// https://geti2p.net/spec/common-structures#destination
|
// https://geti2p.net/spec/common-structures#destination
|
||||||
type Destination struct {
|
type Destination struct {
|
||||||
*KeysAndCert
|
KeysAndCert
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base32Address returns the I2P base32 address for this Destination.
|
// Base32Address returns the I2P base32 address for this Destination.
|
||||||
@ -48,17 +48,9 @@ func (destination Destination) Base64() string {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
|
func ReadDestination(data []byte) (destination Destination, remainder []byte, err error) {
|
||||||
keys_and_cert, remainder, err := NewKeysAndCert(data)
|
keys_and_cert, remainder, err := ReadKeysAndCert(data)
|
||||||
destination = Destination{
|
destination = Destination{
|
||||||
keys_and_cert,
|
keys_and_cert,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDestination creates a new *Destination from []byte using ReadDestination.
|
|
||||||
// Returns a pointer to Destination unlike ReadDestination.
|
|
||||||
func NewDestination(data []byte) (destination *Destination, remainder []byte, err error) {
|
|
||||||
objdestination, remainder, err := ReadDestination(data)
|
|
||||||
destination = &objdestination
|
|
||||||
return destination, remainder, err
|
|
||||||
}
|
|
||||||
|
@ -52,6 +52,10 @@ const (
|
|||||||
// Key Certificate Public Key Types
|
// Key Certificate Public Key Types
|
||||||
const (
|
const (
|
||||||
KEYCERT_CRYPTO_ELG = iota
|
KEYCERT_CRYPTO_ELG = iota
|
||||||
|
KEYCERT_CRYPTO_P256
|
||||||
|
KEYCERT_CRYPTO_P384
|
||||||
|
KEYCERT_CRYPTO_P521
|
||||||
|
KEYCERT_CRYPTO_X25519
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -73,7 +77,11 @@ const (
|
|||||||
|
|
||||||
// PublicKey sizes for Public Key Types
|
// PublicKey sizes for Public Key Types
|
||||||
const (
|
const (
|
||||||
KEYCERT_CRYPTO_ELG_SIZE = 256
|
KEYCERT_CRYPTO_ELG_SIZE = 256
|
||||||
|
KEYCERT_CRYPTO_P256_SIZE = 64
|
||||||
|
KEYCERT_CRYPTO_P384_SIZE = 96
|
||||||
|
KEYCERT_CRYPTO_P521_SIZE = 132
|
||||||
|
KEYCERT_CRYPTO_X25519_SIZE = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sizes of structures in KeyCertificates
|
// Sizes of structures in KeyCertificates
|
||||||
@ -82,9 +90,9 @@ const (
|
|||||||
KEYCERT_SPK_SIZE = 128
|
KEYCERT_SPK_SIZE = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
//type KeyCertificate []byte
|
// type KeyCertificate []byte
|
||||||
type KeyCertificate struct {
|
type KeyCertificate struct {
|
||||||
*Certificate
|
Certificate
|
||||||
spkType Integer
|
spkType Integer
|
||||||
cpkType Integer
|
cpkType Integer
|
||||||
}
|
}
|
||||||
@ -112,7 +120,7 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
data_len := len(data)
|
data_len := len(data)
|
||||||
if data_len < KEYCERT_PUBKEY_SIZE {
|
if data_len < key_certificate.CryptoSize() {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(KeyCertificate) ConstructPublicKey",
|
"at": "(KeyCertificate) ConstructPublicKey",
|
||||||
"data_len": data_len,
|
"data_len": data_len,
|
||||||
@ -127,6 +135,10 @@ func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_ke
|
|||||||
var elg_key crypto.ElgPublicKey
|
var elg_key crypto.ElgPublicKey
|
||||||
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
||||||
public_key = elg_key
|
public_key = elg_key
|
||||||
|
case KEYCERT_CRYPTO_X25519:
|
||||||
|
var ed25519_key crypto.Ed25519PublicKey
|
||||||
|
copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
|
||||||
|
public_key = ed25519_key
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -139,7 +151,7 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
data_len := len(data)
|
data_len := len(data)
|
||||||
if data_len < KEYCERT_SPK_SIZE {
|
if data_len < key_certificate.SignatureSize() {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(KeyCertificate) ConstructSigningPublicKey",
|
"at": "(KeyCertificate) ConstructSigningPublicKey",
|
||||||
"data_len": data_len,
|
"data_len": data_len,
|
||||||
@ -169,11 +181,11 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
|||||||
copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra])
|
copy(ec_key[KEYCERT_SPK_SIZE:], key_certificate.Certificate.RawBytes()[4:4+extra])
|
||||||
signing_public_key = ec_key
|
signing_public_key = ec_key
|
||||||
case KEYCERT_SIGN_RSA2048:
|
case KEYCERT_SIGN_RSA2048:
|
||||||
//var rsa_key crypto.RSA2048PublicKey
|
// var rsa_key crypto.RSA2048PublicKey
|
||||||
//extra := KEYCERT_SIGN_RSA2048_SIZE - 128
|
// extra := KEYCERT_SIGN_RSA2048_SIZE - 128
|
||||||
//copy(rsa_key[:], data)
|
// copy(rsa_key[:], data)
|
||||||
//copy(rsa_key[128:], key_certificate[4:4+extra])
|
// copy(rsa_key[128:], key_certificate[4:4+extra])
|
||||||
//signing_public_key = rsa_key
|
// signing_public_key = rsa_key
|
||||||
case KEYCERT_SIGN_RSA3072:
|
case KEYCERT_SIGN_RSA3072:
|
||||||
case KEYCERT_SIGN_RSA4096:
|
case KEYCERT_SIGN_RSA4096:
|
||||||
case KEYCERT_SIGN_ED25519:
|
case KEYCERT_SIGN_ED25519:
|
||||||
@ -185,65 +197,60 @@ func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (si
|
|||||||
// SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type.
|
// SignatureSize return the size of a Signature corresponding to the Key Certificate's SigningPublicKey type.
|
||||||
func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
func (key_certificate KeyCertificate) SignatureSize() (size int) {
|
||||||
sizes := map[int]int{
|
sizes := map[int]int{
|
||||||
KEYCERT_SIGN_DSA_SHA1: 40,
|
KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE,
|
||||||
KEYCERT_SIGN_P256: 64,
|
KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE,
|
||||||
KEYCERT_SIGN_P384: 96,
|
KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE,
|
||||||
KEYCERT_SIGN_P521: 132,
|
KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE,
|
||||||
KEYCERT_SIGN_RSA2048: 256,
|
KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE,
|
||||||
KEYCERT_SIGN_RSA3072: 384,
|
KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE,
|
||||||
KEYCERT_SIGN_RSA4096: 512,
|
KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE,
|
||||||
KEYCERT_SIGN_ED25519: 64,
|
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
|
||||||
KEYCERT_SIGN_ED25519PH: 64,
|
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
|
||||||
}
|
}
|
||||||
key_type := key_certificate.SigningPublicKeyType()
|
key_type := key_certificate.SigningPublicKeyType()
|
||||||
return sizes[int(key_type)]
|
return sizes[int(key_type)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's PublicKey type.
|
||||||
|
func (key_certificate KeyCertificate) CryptoSize() (size int) {
|
||||||
|
sizes := map[int]int{
|
||||||
|
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
|
||||||
|
KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE,
|
||||||
|
KEYCERT_CRYPTO_P384: KEYCERT_CRYPTO_P384_SIZE,
|
||||||
|
KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE,
|
||||||
|
KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE,
|
||||||
|
}
|
||||||
|
key_type := key_certificate.PublicKeyType()
|
||||||
|
return sizes[int(key_type)]
|
||||||
|
}
|
||||||
|
|
||||||
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
|
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
|
||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
|
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
|
||||||
var certificate *Certificate
|
var certificate Certificate
|
||||||
certificate, remainder, err = ReadCertificate(bytes)
|
certificate, remainder, err = ReadCertificate(bytes)
|
||||||
//if err != nil {
|
if err != nil {
|
||||||
// return nil, err
|
return
|
||||||
//}
|
}
|
||||||
if len(bytes) < KEYCERT_MIN_SIZE {
|
if len(bytes) < KEYCERT_MIN_SIZE {
|
||||||
err = errors.New("error parsing key certificate: not enough data")
|
err = errors.New("error parsing key certificate: not enough data")
|
||||||
|
remainder = bytes[KEYCERT_MIN_SIZE:]
|
||||||
}
|
}
|
||||||
switch len(bytes) {
|
key_certificate = &KeyCertificate{
|
||||||
case 4:
|
Certificate: certificate,
|
||||||
key_certificate = &KeyCertificate{
|
}
|
||||||
Certificate: certificate,
|
if len(bytes) >= 5 {
|
||||||
spkType: Integer(bytes[4:]),
|
key_certificate.spkType = Integer(bytes[4:5])
|
||||||
cpkType: Integer([]byte{0}),
|
}
|
||||||
}
|
if len(bytes) >= 7 {
|
||||||
case 5:
|
key_certificate.cpkType = Integer(bytes[6:7])
|
||||||
key_certificate = &KeyCertificate{
|
|
||||||
Certificate: certificate,
|
|
||||||
spkType: Integer(bytes[4:5]),
|
|
||||||
cpkType: Integer([]byte{0}),
|
|
||||||
}
|
|
||||||
case 6:
|
|
||||||
key_certificate = &KeyCertificate{
|
|
||||||
Certificate: certificate,
|
|
||||||
spkType: Integer(bytes[4:5]),
|
|
||||||
cpkType: Integer(bytes[6:]),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
key_certificate = &KeyCertificate{
|
|
||||||
Certificate: certificate,
|
|
||||||
spkType: Integer(bytes[4:5]),
|
|
||||||
cpkType: Integer(bytes[6:7]),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
remainder = bytes[7:]
|
|
||||||
//key_certificate.PublicKey = NewPublicKey(bytes)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
|
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
|
||||||
func KeyCertificateFromCertificate(certificate *Certificate) *KeyCertificate {
|
func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate {
|
||||||
k, _, _ := NewKeyCertificate(certificate.RawBytes())
|
k, _, _ := NewKeyCertificate(certificate.RawBytes())
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
@ -79,103 +79,41 @@ type KeysAndCert struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length.
|
// Bytes returns the entire KeyCertificate in []byte form, trims payload to specified length.
|
||||||
func (keys_and_cert *KeysAndCert) Bytes() []byte {
|
func (keys_and_cert KeysAndCert) Bytes() []byte {
|
||||||
return keys_and_cert.KeyCertificate.Bytes()
|
return keys_and_cert.KeyCertificate.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PublicKey returns the public key as a crypto.PublicKey.
|
// PublicKey returns the public key as a crypto.PublicKey.
|
||||||
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
|
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
|
||||||
/*cert := keys_and_cert.Certificate()
|
|
||||||
cert_len := cert.Length()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cert_len == 0 {
|
|
||||||
// No Certificate is present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
|
|
||||||
// PublicKey space as ElgPublicKey.
|
|
||||||
var elg_key crypto.ElgPublicKey
|
|
||||||
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
|
|
||||||
key = elg_key
|
|
||||||
} else {
|
|
||||||
// A Certificate is present in this KeysAndCert
|
|
||||||
cert_type := cert.Type()
|
|
||||||
if cert_type == CERT_KEY {
|
|
||||||
// This KeysAndCert contains a Key Certificate, construct
|
|
||||||
// a PublicKey from the data in the KeysAndCert and
|
|
||||||
// any additional data in the Certificate.
|
|
||||||
key, err = KeyCertificateFromCertificate(cert).ConstructPublicKey(
|
|
||||||
keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE],
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Key Certificate is not present, return the KEYS_AND_CERT_PUBKEY_SIZE byte
|
|
||||||
// PublicKey space as ElgPublicKey. No other Certificate
|
|
||||||
// types are currently in use.
|
|
||||||
var elg_key crypto.ElgPublicKey
|
|
||||||
copy(keys_and_cert[:KEYS_AND_CERT_PUBKEY_SIZE], elg_key[:])
|
|
||||||
key = elg_key
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(KeysAndCert) PublicKey",
|
|
||||||
"cert_type": cert_type,
|
|
||||||
}).Warn("unused certificate type observed")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return*/
|
|
||||||
return keys_and_cert.publicKey
|
return keys_and_cert.publicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// SigningPublicKey returns the signing public key.
|
// SigningPublicKey returns the signing public key.
|
||||||
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) {
|
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) {
|
||||||
/*cert := keys_and_cert.Certificate()
|
|
||||||
cert_len := cert.Length()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cert_len == 0 {
|
|
||||||
// No Certificate is present, return the KEYS_AND_CERT_SPK_SIZE byte
|
|
||||||
// SigningPublicKey space as legacy DSA SHA1 SigningPublicKey.
|
|
||||||
var dsa_pk crypto.DSAPublicKey
|
|
||||||
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
|
|
||||||
signing_public_key = dsa_pk
|
|
||||||
} else {
|
|
||||||
// A Certificate is present in this KeysAndCert
|
|
||||||
cert_type := cert.Type()
|
|
||||||
if cert_type == CERT_KEY {
|
|
||||||
// This KeysAndCert contains a Key Certificate, construct
|
|
||||||
// a SigningPublicKey from the data in the KeysAndCert and
|
|
||||||
// any additional data in the Certificate.
|
|
||||||
signing_public_key, err = KeyCertificateFromCertificate(cert).ConstructSigningPublicKey(
|
|
||||||
keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE],
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Key Certificate is not present, return the KEYS_AND_CERT_SPK_SIZE byte
|
|
||||||
// SigningPublicKey space as legacy SHA DSA1 SigningPublicKey.
|
|
||||||
// No other Certificate types are currently in use.
|
|
||||||
var dsa_pk crypto.DSAPublicKey
|
|
||||||
copy(dsa_pk[:], keys_and_cert[KEYS_AND_CERT_PUBKEY_SIZE:KEYS_AND_CERT_PUBKEY_SIZE+KEYS_AND_CERT_SPK_SIZE])
|
|
||||||
signing_public_key = dsa_pk
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
return keys_and_cert.signingPublicKey
|
return keys_and_cert.signingPublicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Certfificate returns the certificate.
|
// Certfificate returns the certificate.
|
||||||
func (keys_and_cert *KeysAndCert) Certificate() (cert *Certificate) {
|
func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) {
|
||||||
return keys_and_cert.KeyCertificate.Certificate
|
return keys_and_cert.KeyCertificate.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
|
||||||
// Read a KeysAndCert from a slice of bytes, retuning it and the remaining data as well as any errors
|
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
||||||
// encoutered parsing the KeysAndCert.
|
|
||||||
//
|
|
||||||
|
|
||||||
// ReadKeysAndCert returns KeysAndCert from a []byte.
|
|
||||||
// The remaining bytes after the specified length are also returned.
|
|
||||||
// Returns a list of errors that occurred during parsing.
|
|
||||||
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
|
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
|
||||||
/*data_len := len(data)
|
data_len := len(data)
|
||||||
if data_len < KEYS_AND_CERT_MIN_SIZE {
|
// keys_and_cert = KeysAndCert{}
|
||||||
|
if data_len < KEYS_AND_CERT_MIN_SIZE && data_len > KEYS_AND_CERT_DATA_SIZE {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"at": "ReadKeysAndCert",
|
||||||
|
"data_len": data_len,
|
||||||
|
"required_len": KEYS_AND_CERT_MIN_SIZE,
|
||||||
|
"reason": "not enough data",
|
||||||
|
}).Error("error parsing keys and cert")
|
||||||
|
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
||||||
|
keys_and_cert.KeyCertificate, remainder, _ = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
|
||||||
|
return
|
||||||
|
} else if data_len < KEYS_AND_CERT_DATA_SIZE {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "ReadKeysAndCert",
|
"at": "ReadKeysAndCert",
|
||||||
"data_len": data_len,
|
"data_len": data_len,
|
||||||
@ -185,56 +123,22 @@ func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte,
|
|||||||
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
keys_and_cert = KeysAndCert(data[:KEYS_AND_CERT_MIN_SIZE])
|
keys_and_cert.KeyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
|
||||||
cert, _ := keys_and_cert.Certificate()
|
if err != nil {
|
||||||
cert_len := cert.Length()
|
|
||||||
if cert_len == 0 {
|
|
||||||
remainder = data[KEYS_AND_CERT_MIN_SIZE:]
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if data_len < KEYS_AND_CERT_MIN_SIZE+cert_len {
|
// TODO: this only supports one key type right now and it's the old key type, but the layout is the same.
|
||||||
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:]...)
|
// a case-switch which sets the size of the SPK and the PK should be used to replace the referenced KEYS_AND_CERT_PUBKEY_SIZE
|
||||||
//err = cert_len_err
|
// and KEYS_AND_CERT_SPK_SIZE constants in the future.
|
||||||
} else {
|
keys_and_cert.publicKey, err = keys_and_cert.KeyCertificate.ConstructPublicKey(data[:keys_and_cert.KeyCertificate.CryptoSize()])
|
||||||
keys_and_cert = append(keys_and_cert, data[KEYS_AND_CERT_MIN_SIZE:KEYS_AND_CERT_MIN_SIZE+cert_len]...)
|
if err != nil {
|
||||||
remainder = data[KEYS_AND_CERT_MIN_SIZE+cert_len:]
|
return
|
||||||
}*/
|
}
|
||||||
keys_and_cert_pointer, remainder, err := NewKeysAndCert(data)
|
keys_and_cert.signingPublicKey, err = keys_and_cert.KeyCertificate.ConstructSigningPublicKey(data[KEYS_AND_CERT_DATA_SIZE-keys_and_cert.KeyCertificate.SignatureSize() : KEYS_AND_CERT_DATA_SIZE])
|
||||||
keys_and_cert = *keys_and_cert_pointer
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
padding := data[KEYS_AND_CERT_PUBKEY_SIZE : KEYS_AND_CERT_DATA_SIZE-KEYS_AND_CERT_SPK_SIZE]
|
||||||
|
keys_and_cert.padding = padding
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
|
|
||||||
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
|
||||||
func NewKeysAndCert(data []byte) (keys_and_cert *KeysAndCert, remainder []byte, err error) {
|
|
||||||
data_len := len(data)
|
|
||||||
keys_and_cert = &KeysAndCert{}
|
|
||||||
if data_len < KEYS_AND_CERT_MIN_SIZE {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "ReadKeysAndCert",
|
|
||||||
"data_len": data_len,
|
|
||||||
"required_len": KEYS_AND_CERT_MIN_SIZE,
|
|
||||||
"reason": "not enough data",
|
|
||||||
}).Error("error parsing keys and cert")
|
|
||||||
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cert, remainder, err := NewKeyCertificate(data)
|
|
||||||
keys_and_cert.KeyCertificate = cert
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
padding := data[KEYS_AND_CERT_MIN_SIZE+cert.Length():]
|
|
||||||
keys_and_cert.padding = padding
|
|
||||||
publicKey, err := cert.ConstructPublicKey(padding)
|
|
||||||
keys_and_cert.publicKey = publicKey
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
signingPublicKey, err := cert.ConstructSigningPublicKey(padding)
|
|
||||||
keys_and_cert.signingPublicKey = signingPublicKey
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return keys_and_cert, remainder, err
|
|
||||||
}
|
|
||||||
|
@ -6,23 +6,17 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCertificateWithMissingData(t *testing.T) {
|
/*func TestCertificateWithMissingData(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
|
cert_data := []byte{0x05, 0x00, 0x04, 0x00, 0x01}
|
||||||
data := make([]byte, 128+256)
|
data := make([]byte, 128+256)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
_, _, err := NewKeysAndCert(data)
|
||||||
|
|
||||||
cert := keys_and_cert.Certificate()
|
|
||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
|
assert.Equal("certificate parsing warning: certificate data is shorter than specified by length", err.Error())
|
||||||
}
|
}
|
||||||
cert_bytes := cert.Bytes()
|
}*/
|
||||||
if assert.Equal(len(cert_data), len(cert_bytes)) {
|
|
||||||
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return available data when cert was missing some data")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCertificateWithValidData(t *testing.T) {
|
func TestCertificateWithValidData(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
@ -31,9 +25,10 @@ func TestCertificateWithValidData(t *testing.T) {
|
|||||||
data := make([]byte, 128+256)
|
data := make([]byte, 128+256)
|
||||||
data = append(data, cert_data...)
|
data = append(data, cert_data...)
|
||||||
keys_and_cert, _, err := ReadKeysAndCert(data)
|
keys_and_cert, _, err := ReadKeysAndCert(data)
|
||||||
|
assert.Nil(err)
|
||||||
|
|
||||||
cert := keys_and_cert.Certificate()
|
cert := keys_and_cert.Certificate()
|
||||||
assert.Nil(err)
|
|
||||||
cert_bytes := cert.Bytes()
|
cert_bytes := cert.Bytes()
|
||||||
if assert.Equal(len(cert_data), len(cert_bytes)) {
|
if assert.Equal(len(cert_data), len(cert_bytes)) {
|
||||||
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return correct data with valid cert")
|
assert.Equal(cert_bytes, cert_data, "keys_and_cert.Certificate() did not return correct data with valid cert")
|
||||||
@ -168,7 +163,7 @@ func TestSigningPublicKeyWithKeyCertificate(t *testing.T) {
|
|||||||
assert.Equal(len(signing_pub_key_data), signing_pub_key.Len())
|
assert.Equal(len(signing_pub_key_data), signing_pub_key.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadKeysAndCertWithMissingData(t *testing.T) {
|
func TestNewKeysAndCertWithMissingData(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128)
|
cert_data := make([]byte, 128)
|
||||||
@ -177,10 +172,9 @@ func TestReadKeysAndCertWithMissingData(t *testing.T) {
|
|||||||
if assert.NotNil(err) {
|
if assert.NotNil(err) {
|
||||||
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
|
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadKeysAndCertWithMissingCertData(t *testing.T) {
|
func TestNewKeysAndCertWithMissingCertData(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
@ -192,7 +186,7 @@ func TestReadKeysAndCertWithMissingCertData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadKeysAndCertWithValidDataWithCertificate(t *testing.T) {
|
func TestNewKeysAndCertWithValidDataWithCertificate(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
@ -202,7 +196,7 @@ func TestReadKeysAndCertWithValidDataWithCertificate(t *testing.T) {
|
|||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
func TestNewKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
@ -212,7 +206,7 @@ func TestReadKeysAndCertWithValidDataWithoutCertificate(t *testing.T) {
|
|||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
func TestNewKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
@ -224,7 +218,7 @@ func TestReadKeysAndCertWithValidDataWithCertificateAndRemainder(t *testing.T) {
|
|||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
|
func TestNewKeysAndCertWithValidDataWithoutCertificateAndRemainder(t *testing.T) {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
cert_data := make([]byte, 128+256)
|
cert_data := make([]byte, 128+256)
|
||||||
|
@ -133,6 +133,9 @@ type LeaseSet struct {
|
|||||||
// Destination returns the Destination as []byte.
|
// Destination returns the Destination as []byte.
|
||||||
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
func (lease_set LeaseSet) Destination() (destination Destination, err error) {
|
||||||
keys_and_cert, _, err := ReadKeysAndCert(lease_set)
|
keys_and_cert, _, err := ReadKeysAndCert(lease_set)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
destination, _, err = ReadDestination(keys_and_cert.Bytes())
|
destination, _, err = ReadDestination(keys_and_cert.Bytes())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ import (
|
|||||||
func buildDestination() *router_identity.RouterIdentity {
|
func buildDestination() *router_identity.RouterIdentity {
|
||||||
router_ident_data := make([]byte, 128+256)
|
router_ident_data := make([]byte, 128+256)
|
||||||
router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
|
router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
|
||||||
ident, _, err := router_identity.NewRouterIdentity(router_ident_data)
|
ident, _, err := router_identity.ReadRouterIdentity(router_ident_data)
|
||||||
panic(err)
|
panic(err)
|
||||||
return ident
|
return &ident
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPublicKey() []byte {
|
func buildPublicKey() []byte {
|
||||||
@ -77,7 +77,7 @@ func TestDestinationIsCorrect(t *testing.T) {
|
|||||||
dest, err := lease_set.Destination()
|
dest, err := lease_set.Destination()
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
dest_cert := dest.Certificate()
|
dest_cert := dest.Certificate()
|
||||||
//assert.Nil(err)
|
// assert.Nil(err)
|
||||||
cert_type := dest_cert.Type()
|
cert_type := dest_cert.Type()
|
||||||
assert.Nil(err)
|
assert.Nil(err)
|
||||||
assert.Equal(certificate.CERT_KEY, cert_type)
|
assert.Equal(certificate.CERT_KEY, cert_type)
|
||||||
|
@ -3,6 +3,10 @@ package router_address
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -63,71 +67,215 @@ options :: Mapping
|
|||||||
//
|
//
|
||||||
// https://geti2p.net/spec/common-structures#routeraddress
|
// https://geti2p.net/spec/common-structures#routeraddress
|
||||||
type RouterAddress struct {
|
type RouterAddress struct {
|
||||||
cost *Integer
|
TransportCost *Integer
|
||||||
expiration *Date
|
ExpirationDate *Date
|
||||||
Transport_Style *I2PString
|
TransportType I2PString
|
||||||
options *Mapping
|
TransportOptions *Mapping
|
||||||
parserErr error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Network implements net.Addr. It returns the transport type plus 4 or 6
|
||||||
|
func (router_address *RouterAddress) Network() string {
|
||||||
|
if router_address.TransportType == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
str, err := router_address.TransportType.Data()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(str) + router_address.IPVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPVersion returns a string "4" for IPv4 or 6 for IPv6
|
||||||
|
func (router_address *RouterAddress) IPVersion() string {
|
||||||
|
str, err := router_address.CapsString().Data()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(str, "6") {
|
||||||
|
return "6"
|
||||||
|
}
|
||||||
|
return "4"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address *RouterAddress) UDP() bool {
|
||||||
|
return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu")
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements net.Addr. It returns the IP address, followed by the options
|
||||||
|
func (router_address *RouterAddress) String() string {
|
||||||
|
var rv []string
|
||||||
|
rv = append(rv, string(router_address.TransportStyle()))
|
||||||
|
rv = append(rv, string(router_address.HostString()))
|
||||||
|
rv = append(rv, string(router_address.PortString()))
|
||||||
|
rv = append(rv, string(router_address.StaticKeyString()))
|
||||||
|
rv = append(rv, string(router_address.InitializationVectorString()))
|
||||||
|
rv = append(rv, string(router_address.ProtocolVersionString()))
|
||||||
|
if router_address.UDP() {
|
||||||
|
rv = append(rv, string(router_address.IntroducerHashString(0)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerExpirationString(0)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerTagString(0)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerHashString(1)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerExpirationString(1)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerTagString(1)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerHashString(2)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerExpirationString(2)))
|
||||||
|
rv = append(rv, string(router_address.IntroducerTagString(2)))
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(strings.Join(rv, " "))
|
||||||
|
}
|
||||||
|
|
||||||
|
var ex_addr net.Addr = &RouterAddress{}
|
||||||
|
|
||||||
// Bytes returns the router address as a []byte.
|
// Bytes returns the router address as a []byte.
|
||||||
func (router_address RouterAddress) Bytes() []byte {
|
func (router_address RouterAddress) Bytes() []byte {
|
||||||
bytes := make([]byte, 0)
|
bytes := make([]byte, 0)
|
||||||
bytes = append(bytes, router_address.cost.Bytes()...)
|
bytes = append(bytes, router_address.TransportCost.Bytes()...)
|
||||||
bytes = append(bytes, router_address.expiration.Bytes()...)
|
bytes = append(bytes, router_address.ExpirationDate.Bytes()...)
|
||||||
strData, err := router_address.Transport_Style.Data()
|
strData, err := router_address.TransportType.Data()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
}).Error("RouterAddress.Bytes: error getting Transport_Style bytes")
|
}).Error("RouterAddress.Bytes: error getting transport_style bytes")
|
||||||
} else {
|
} else {
|
||||||
bytes = append(bytes, strData...)
|
bytes = append(bytes, strData...)
|
||||||
}
|
}
|
||||||
//bytes = append(bytes, router_address.options.Bytes()...)
|
bytes = append(bytes, router_address.TransportOptions.Data()...)
|
||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cost returns the cost for this RouterAddress as a Go integer.
|
// Cost returns the cost for this RouterAddress as a Go integer.
|
||||||
func (router_address RouterAddress) Cost() int {
|
func (router_address RouterAddress) Cost() int {
|
||||||
return router_address.cost.Int()
|
return router_address.TransportCost.Int()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expiration returns the expiration for this RouterAddress as an I2P Date.
|
// Expiration returns the expiration for this RouterAddress as an I2P Date.
|
||||||
func (router_address RouterAddress) Expiration() Date {
|
func (router_address RouterAddress) Expiration() Date {
|
||||||
return *router_address.expiration
|
return *router_address.ExpirationDate
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
||||||
func (router_address RouterAddress) TransportStyle() I2PString {
|
func (router_address RouterAddress) TransportStyle() I2PString {
|
||||||
return *router_address.Transport_Style
|
return router_address.TransportType
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOption returns the value of the option specified by the key
|
||||||
|
func (router_address RouterAddress) GetOption(key I2PString) I2PString {
|
||||||
|
return router_address.Options().Values().Get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) HostString() I2PString {
|
||||||
|
host, _ := ToI2PString("host")
|
||||||
|
return router_address.GetOption(host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) PortString() I2PString {
|
||||||
|
port, _ := ToI2PString("port")
|
||||||
|
return router_address.GetOption(port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) CapsString() I2PString {
|
||||||
|
caps, _ := ToI2PString("caps")
|
||||||
|
return router_address.GetOption(caps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) StaticKeyString() I2PString {
|
||||||
|
sk, _ := ToI2PString("s")
|
||||||
|
return router_address.GetOption(sk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) InitializationVectorString() I2PString {
|
||||||
|
iv, _ := ToI2PString("i")
|
||||||
|
return router_address.GetOption(iv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) ProtocolVersionString() I2PString {
|
||||||
|
v, _ := ToI2PString("v")
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) IntroducerHashString(num int) I2PString {
|
||||||
|
if num >= 0 && num <= 2 {
|
||||||
|
val := strconv.Itoa(num)
|
||||||
|
v, _ := ToI2PString("ih" + val)
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
v, _ := ToI2PString("ih0")
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString {
|
||||||
|
if num >= 0 && num <= 2 {
|
||||||
|
val := strconv.Itoa(num)
|
||||||
|
v, _ := ToI2PString("iexp" + val)
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
v, _ := ToI2PString("iexp0")
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) IntroducerTagString(num int) I2PString {
|
||||||
|
if num >= 0 && num <= 2 {
|
||||||
|
val := strconv.Itoa(num)
|
||||||
|
v, _ := ToI2PString("itag" + val)
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
v, _ := ToI2PString("itag0")
|
||||||
|
return router_address.GetOption(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) Host() (net.Addr, error) {
|
||||||
|
host := router_address.HostString()
|
||||||
|
hostBytes, err := host.Data()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ip := net.ParseIP(hostBytes)
|
||||||
|
if ip == nil {
|
||||||
|
return nil, fmt.Errorf("null host error")
|
||||||
|
}
|
||||||
|
return net.ResolveIPAddr("", ip.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) Port() (string, error) {
|
||||||
|
port := router_address.PortString()
|
||||||
|
portBytes, err := port.Data()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
val, err := strconv.Atoi(portBytes)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strconv.Itoa(val), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) StaticKey() ([32]byte, error) {
|
||||||
|
sk := router_address.StaticKeyString()
|
||||||
|
if len([]byte(sk)) != 32 {
|
||||||
|
return [32]byte{}, fmt.Errorf("error: invalid static key")
|
||||||
|
}
|
||||||
|
return [32]byte(sk), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) InitializationVector() ([32]byte, error) {
|
||||||
|
iv := router_address.InitializationVectorString()
|
||||||
|
if len([]byte(iv)) != 32 {
|
||||||
|
return [32]byte{}, fmt.Errorf("error: invalid static key")
|
||||||
|
}
|
||||||
|
return [32]byte(iv), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_address RouterAddress) ProtocolVersion() (string, error) {
|
||||||
|
return router_address.ProtocolVersionString().Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options returns the options for this RouterAddress as an I2P Mapping.
|
// Options returns the options for this RouterAddress as an I2P Mapping.
|
||||||
func (router_address RouterAddress) Options() Mapping {
|
func (router_address RouterAddress) Options() Mapping {
|
||||||
return *router_address.options
|
return *router_address.TransportOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the RouterAddress is empty or if it is too small to contain valid data.
|
// Check if the RouterAddress is empty or if it is too small to contain valid data.
|
||||||
func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
||||||
/*addr_len := len(router_address)
|
|
||||||
exit = false
|
|
||||||
if addr_len == 0 {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(RouterAddress) checkValid",
|
|
||||||
"reason": "no data",
|
|
||||||
}).Error("invalid router address")
|
|
||||||
err = errors.New("error parsing RouterAddress: no data")
|
|
||||||
exit = true
|
|
||||||
} else if addr_len < ROUTER_ADDRESS_MIN_SIZE {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(RouterAddress) checkValid",
|
|
||||||
"reason": "data too small (len < ROUTER_ADDRESS_MIN_SIZE)",
|
|
||||||
}).Warn("router address format warning")
|
|
||||||
err = errors.New("warning parsing RouterAddress: data too small")
|
|
||||||
}*/
|
|
||||||
if router_address.parserErr != nil {
|
|
||||||
exit = true
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,62 +283,40 @@ func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
|||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
||||||
if data == nil || len(data) == 0 {
|
if len(data) == 0 {
|
||||||
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("no data")
|
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data")
|
||||||
err = errors.New("error parsing RouterAddress: no data")
|
err = errors.New("error parsing RouterAddress: no data")
|
||||||
router_address.parserErr = err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cost, remainder, err := NewInteger([]byte{data[0]}, 1)
|
router_address.TransportCost, remainder, err = NewInteger(data, 1)
|
||||||
router_address.cost = cost
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing cost",
|
"reason": "error parsing cost",
|
||||||
}).Warn("error parsing RouterAddress")
|
}).Warn("error parsing RouterAddress")
|
||||||
router_address.parserErr = err
|
|
||||||
}
|
}
|
||||||
expiration, remainder, err := NewDate(remainder)
|
router_address.ExpirationDate, remainder, err = NewDate(remainder)
|
||||||
router_address.expiration = expiration
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing expiration",
|
"reason": "error parsing expiration",
|
||||||
}).Error("error parsing RouterAddress")
|
}).Error("error parsing RouterAddress")
|
||||||
router_address.parserErr = err
|
|
||||||
}
|
}
|
||||||
Transport_Style, remainder, err := NewI2PString(remainder)
|
router_address.TransportType, remainder, err = ReadI2PString(remainder)
|
||||||
router_address.Transport_Style = Transport_Style
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing Transport_Style",
|
"reason": "error parsing transport_style",
|
||||||
}).Error("error parsing RouterAddress")
|
}).Error("error parsing RouterAddress")
|
||||||
router_address.parserErr = err
|
|
||||||
}
|
}
|
||||||
options, remainder, errs := NewMapping(remainder)
|
var errs []error
|
||||||
|
router_address.TransportOptions, remainder, errs = NewMapping(remainder)
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
||||||
"reason": "error parsing options",
|
"reason": "error parsing options",
|
||||||
}).Error("error parsing RouterAddress")
|
"error": err,
|
||||||
router_address.parserErr = err
|
}).Error("error parsing RozuterAddress")
|
||||||
}
|
|
||||||
router_address.options = options
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(RouterAddress) ReadNewRouterAddress",
|
|
||||||
"reason": "error parsing options",
|
|
||||||
}).Error("error parsing RouterAddress")
|
|
||||||
router_address.parserErr = err
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouterAddress creates a new *RouterAddress from []byte using ReadRouterAddress.
|
|
||||||
// Returns a pointer to RouterAddress unlike ReadRouterAddress.
|
|
||||||
func NewRouterAddress(data []byte) (router_address *RouterAddress, remainder []byte, err error) {
|
|
||||||
objrouteraddress, remainder, err := ReadRouterAddress(data)
|
|
||||||
router_address = &objrouteraddress
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
@ -31,7 +31,6 @@ func TestCheckRouterAddressValidReportsDataMissing(t *testing.T) {
|
|||||||
|
|
||||||
err, exit := router_address.checkValid()
|
err, exit := router_address.checkValid()
|
||||||
assert.Equal(exit, false, "checkValid indicates to stop parsing when some fields may be present")
|
assert.Equal(exit, false, "checkValid indicates to stop parsing when some fields may be present")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) {
|
func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) {
|
||||||
@ -40,8 +39,8 @@ func TestCheckRouterAddressValidNoErrWithValidData(t *testing.T) {
|
|||||||
router_address, _, _ := ReadRouterAddress([]byte{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
|
router_address, _, _ := ReadRouterAddress([]byte{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
|
||||||
mapping, err := GoMapToMapping(map[string]string{"host": "127.0.0.1", "port": "4567"})
|
mapping, err := GoMapToMapping(map[string]string{"host": "127.0.0.1", "port": "4567"})
|
||||||
assert.Nil(err, "GoMapToMapping() returned error with valid data")
|
assert.Nil(err, "GoMapToMapping() returned error with valid data")
|
||||||
router_address.options = mapping
|
router_address.TransportOptions = mapping
|
||||||
//router_address = append(router_address, mapping...)
|
// router_address = append(router_address, mapping...)
|
||||||
err, exit := router_address.checkValid()
|
err, exit := router_address.checkValid()
|
||||||
|
|
||||||
assert.Nil(err, "checkValid() reported error with valid data")
|
assert.Nil(err, "checkValid() reported error with valid data")
|
||||||
|
@ -20,24 +20,16 @@ Identical to KeysAndCert.
|
|||||||
//
|
//
|
||||||
// https://geti2p.net/spec/common-structures#routeridentity
|
// https://geti2p.net/spec/common-structures#routeridentity
|
||||||
type RouterIdentity struct {
|
type RouterIdentity struct {
|
||||||
*KeysAndCert
|
KeysAndCert
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadRouterIdentity returns RouterIdentity from a []byte.
|
// ReadRouterIdentity returns RouterIdentity from a []byte.
|
||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) {
|
func ReadRouterIdentity(data []byte) (router_identity RouterIdentity, remainder []byte, err error) {
|
||||||
keys_and_cert, remainder, err := NewKeysAndCert(data)
|
keys_and_cert, remainder, err := ReadKeysAndCert(data)
|
||||||
router_identity = RouterIdentity{
|
router_identity = RouterIdentity{
|
||||||
keys_and_cert,
|
keys_and_cert,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouterIdentity creates a new *RouterIdentity from []byte using ReadRouterIdentity.
|
|
||||||
// Returns a pointer to RouterIdentity unlike ReadRouterIdentity.
|
|
||||||
func NewRouterIdentity(data []byte) (router_identity *RouterIdentity, remainder []byte, err error) {
|
|
||||||
objrouter_identity, remainder, err := ReadRouterIdentity(data)
|
|
||||||
router_identity = &objrouter_identity
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@ package router_info
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||||
@ -15,6 +15,11 @@ import (
|
|||||||
|
|
||||||
const ROUTER_INFO_MIN_SIZE = 439
|
const ROUTER_INFO_MIN_SIZE = 439
|
||||||
|
|
||||||
|
const (
|
||||||
|
MIN_GOOD_VERSION = 58
|
||||||
|
MAX_GOOD_VERSION = 99
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[RouterInfo]
|
[RouterInfo]
|
||||||
Accurate for version 0.9.49
|
Accurate for version 0.9.49
|
||||||
@ -99,7 +104,7 @@ signature :: Signature
|
|||||||
//
|
//
|
||||||
// https://geti2p.net/spec/common-structures#routerinfo
|
// https://geti2p.net/spec/common-structures#routerinfo
|
||||||
type RouterInfo struct {
|
type RouterInfo struct {
|
||||||
router_identity *RouterIdentity
|
router_identity RouterIdentity
|
||||||
published *Date
|
published *Date
|
||||||
size *Integer
|
size *Integer
|
||||||
addresses []*RouterAddress
|
addresses []*RouterAddress
|
||||||
@ -108,13 +113,8 @@ type RouterInfo struct {
|
|||||||
signature *Signature
|
signature *Signature
|
||||||
}
|
}
|
||||||
|
|
||||||
var routerInfoTest net.Addr = &RouterInfo{}
|
|
||||||
|
|
||||||
// Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
|
// Bytes returns the RouterInfo as a []byte suitable for writing to a stream.
|
||||||
func (router_info RouterInfo) Bytes() ([]byte, error) {
|
func (router_info RouterInfo) Bytes() (bytes []byte, err error) {
|
||||||
var err error
|
|
||||||
var bytes []byte
|
|
||||||
|
|
||||||
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
|
bytes = append(bytes, router_info.router_identity.KeysAndCert.Bytes()...)
|
||||||
bytes = append(bytes, router_info.published.Bytes()...)
|
bytes = append(bytes, router_info.published.Bytes()...)
|
||||||
bytes = append(bytes, router_info.size.Bytes()...)
|
bytes = append(bytes, router_info.size.Bytes()...)
|
||||||
@ -122,45 +122,34 @@ func (router_info RouterInfo) Bytes() ([]byte, error) {
|
|||||||
bytes = append(bytes, router_address.Bytes()...)
|
bytes = append(bytes, router_address.Bytes()...)
|
||||||
}
|
}
|
||||||
bytes = append(bytes, router_info.peer_size.Bytes()...)
|
bytes = append(bytes, router_info.peer_size.Bytes()...)
|
||||||
//bytes = append(bytes, router_info.options.Bytes()...)
|
bytes = append(bytes, router_info.options.Data()...)
|
||||||
bytes = append(bytes, []byte(*router_info.signature)...)
|
bytes = append(bytes, []byte(*router_info.signature)...)
|
||||||
|
|
||||||
return bytes, err
|
return bytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network Implements net.Addr, returns comma-separated list of transport types
|
func (router_info RouterInfo) String() string {
|
||||||
func (router_info *RouterInfo) Network() string {
|
str := "Certificate: " + string(router_info.router_identity.KeysAndCert.Bytes())
|
||||||
var str []string
|
str += "Published: " + string(router_info.published.Bytes())
|
||||||
for _, addr := range router_info.addresses {
|
str += "Addresses:" + string(router_info.size.Bytes())
|
||||||
t, err := addr.Transport_Style.Data()
|
for index, router_address := range router_info.addresses {
|
||||||
if err != nil {
|
str += "Address " + strconv.Itoa(index) + ": " + router_address.String()
|
||||||
return strings.Join(str, ",")
|
|
||||||
}
|
|
||||||
str = append(str, t)
|
|
||||||
}
|
}
|
||||||
return strings.Join(str, ",")
|
str += "Peer Size: " + string(router_info.peer_size.Bytes())
|
||||||
}
|
str += "Options: " + string(router_info.options.Data())
|
||||||
|
str += "Signature: " + string([]byte(*router_info.signature))
|
||||||
// String Implements net.Addr, returns router-info `Bytes` converted to a string
|
return str
|
||||||
func (router_info *RouterInfo) String() string {
|
|
||||||
bytes, err := router_info.Bytes()
|
|
||||||
if err != nil {
|
|
||||||
// TODO handle this issue
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(bytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RouterIdentity returns the router identity as *RouterIdentity.
|
// RouterIdentity returns the router identity as *RouterIdentity.
|
||||||
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
||||||
return router_info.router_identity
|
return &router_info.router_identity
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndentHash returns the identity hash (sha256 sum) for this RouterInfo.
|
// IndentHash returns the identity hash (sha256 sum) for this RouterInfo.
|
||||||
func (router_info *RouterInfo) IdentHash() Hash {
|
func (router_info *RouterInfo) IdentHash() Hash {
|
||||||
ri := router_info.RouterIdentity()
|
data, _ := router_info.RouterIdentity().KeyCertificate.Data()
|
||||||
h := HashData(ri.KeysAndCert.Certificate().Data())
|
return HashData(data)
|
||||||
return h
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Published returns the date this RouterInfo was published as an I2P Date.
|
// Published returns the date this RouterInfo was published as an I2P Date.
|
||||||
@ -190,73 +179,21 @@ func (router_info RouterInfo) Options() (mapping Mapping) {
|
|||||||
return *router_info.options
|
return *router_info.options
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Return the signature of this router info
|
|
||||||
//
|
|
||||||
|
|
||||||
// Signature returns the signature for this RouterInfo as an I2P Signature.
|
// Signature returns the signature for this RouterInfo as an I2P Signature.
|
||||||
func (router_info RouterInfo) Signature() (signature Signature) {
|
func (router_info RouterInfo) Signature() (signature Signature) {
|
||||||
return *router_info.signature
|
return *router_info.signature
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Network implements net.Addr
|
||||||
// Used during parsing to determine where in the RouterInfo the Mapping data begins.
|
func (router_info RouterInfo) Network() string {
|
||||||
//
|
return "i2p"
|
||||||
/*func (router_info RouterInfo) optionsLocation() (location int) {
|
}
|
||||||
data, remainder, err := ReadRouterIdentity(router_info)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
location += len(data)
|
|
||||||
|
|
||||||
remainder_len := len(remainder)
|
|
||||||
if remainder_len < 9 {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"at": "(RouterInfo) optionsLocation",
|
|
||||||
"data_len": remainder_len,
|
|
||||||
"required_len": 9,
|
|
||||||
"reason": "not enough data",
|
|
||||||
}).Error("error parsing router info")
|
|
||||||
err = errors.New("error parsing router addresses: not enough data")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
location += 9
|
|
||||||
|
|
||||||
remaining := remainder[9:]
|
|
||||||
var router_address RouterAddress
|
|
||||||
var router_addresses []RouterAddress
|
|
||||||
addr_count, cerr := router_info.RouterAddressCount()
|
|
||||||
if cerr != nil {
|
|
||||||
err = cerr
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := 0; i < addr_count; i++ {
|
|
||||||
router_address, remaining, err = ReadRouterAddress(remaining)
|
|
||||||
if err == nil {
|
|
||||||
location += len(router_address)
|
|
||||||
router_addresses = append(router_addresses, router_address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
location += 1
|
|
||||||
return
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Used during parsing to determine the size of the options in the RouterInfo.
|
|
||||||
//
|
|
||||||
/*func (router_info RouterInfo) optionsSize() (size int) {
|
|
||||||
head := router_info.optionsLocation()
|
|
||||||
s := Integer(router_info[head : head+2])
|
|
||||||
size = s.Int() + 2
|
|
||||||
return
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// ReadRouterInfo returns RouterInfo from a []byte.
|
// ReadRouterInfo returns RouterInfo from a []byte.
|
||||||
// The remaining bytes after the specified length are also returned.
|
// The remaining bytes after the specified length are also returned.
|
||||||
// Returns a list of errors that occurred during parsing.
|
// Returns a list of errors that occurred during parsing.
|
||||||
func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) {
|
func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) {
|
||||||
identity, remainder, err := NewRouterIdentity(bytes)
|
info.router_identity, remainder, err = ReadRouterIdentity(bytes)
|
||||||
info.router_identity = identity
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
@ -265,9 +202,9 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
|||||||
"reason": "not enough data",
|
"reason": "not enough data",
|
||||||
}).Error("error parsing router info")
|
}).Error("error parsing router info")
|
||||||
err = errors.New("error parsing router info: not enough data")
|
err = errors.New("error parsing router info: not enough data")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
date, remainder, err := NewDate(remainder)
|
info.published, remainder, err = NewDate(remainder)
|
||||||
info.published = date
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
@ -277,36 +214,32 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
|||||||
}).Error("error parsing router info")
|
}).Error("error parsing router info")
|
||||||
err = errors.New("error parsing router info: not enough data")
|
err = errors.New("error parsing router info: not enough data")
|
||||||
}
|
}
|
||||||
size, remainder, err := NewInteger(remainder, 1)
|
info.size, remainder, err = NewInteger(remainder, 1)
|
||||||
info.size = size
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
"data_len": len(remainder),
|
"data_len": len(remainder),
|
||||||
"required_len": size.Int(),
|
"required_len": info.size.Int(),
|
||||||
"reason": "not enough data",
|
"reason": "read error",
|
||||||
}).Error("error parsing router info")
|
}).Error("error parsing router info size")
|
||||||
err = errors.New("error parsing router info: not enough data")
|
|
||||||
}
|
}
|
||||||
addresses := make([]*RouterAddress, size.Int())
|
for i := 0; i < info.size.Int(); i++ {
|
||||||
for i := 0; i < size.Int(); i++ {
|
address, more, err := ReadRouterAddress(remainder)
|
||||||
address, remainder, err := NewRouterAddress(remainder)
|
remainder = more
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
"data_len": len(remainder),
|
"data_len": len(remainder),
|
||||||
//"required_len": ROUTER_ADDRESS_SIZE,
|
//"required_len": ROUTER_ADDRESS_SIZE,
|
||||||
"reason": "not enough data",
|
"reason": "not enough data",
|
||||||
}).Error("error parsing router info")
|
}).Error("error parsing router address")
|
||||||
err = errors.New("error parsing router info: not enough data")
|
err = errors.New("error parsing router info: not enough data")
|
||||||
}
|
}
|
||||||
addresses = append(addresses, address)
|
info.addresses = append(info.addresses, &address)
|
||||||
}
|
}
|
||||||
info.addresses = addresses
|
info.peer_size, remainder, err = NewInteger(remainder, 1)
|
||||||
peer_size := Integer(remainder[:1])
|
var errs []error
|
||||||
info.peer_size = &peer_size
|
info.options, remainder, errs = NewMapping(remainder)
|
||||||
remainder = remainder[1:]
|
|
||||||
options, remainder, errs := NewMapping(remainder)
|
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
@ -320,7 +253,7 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
|||||||
}
|
}
|
||||||
err = errors.New("error parsing router info: " + estring)
|
err = errors.New("error parsing router info: " + estring)
|
||||||
}
|
}
|
||||||
info.options = options
|
info.signature, remainder, err = NewSignature(remainder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"at": "(RouterInfo) ReadRouterInfo",
|
"at": "(RouterInfo) ReadRouterInfo",
|
||||||
@ -333,10 +266,57 @@ func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouterInfo creates a new *RouterInfo from []byte using ReadRouterInfo.
|
func (router_info *RouterInfo) RouterCapabilities() string {
|
||||||
// Returns a pointer to RouterInfo unlike ReadRouterInfo.
|
str, err := ToI2PString("caps")
|
||||||
func NewRouterInfo(data []byte) (router_info *RouterInfo, remainder []byte, err error) {
|
if err != nil {
|
||||||
routerInfo, remainder, err := ReadRouterInfo(data)
|
return ""
|
||||||
router_info = &routerInfo
|
}
|
||||||
return
|
return string(router_info.options.Values().Get(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_info *RouterInfo) RouterVersion() string {
|
||||||
|
str, err := ToI2PString("router.version")
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(router_info.options.Values().Get(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_info *RouterInfo) GoodVersion() bool {
|
||||||
|
version := router_info.RouterVersion()
|
||||||
|
v := strings.Split(version, ".")
|
||||||
|
if len(v) != 3 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if v[0] == "0" {
|
||||||
|
if v[1] == "9" {
|
||||||
|
val, _ := strconv.Atoi(v[2])
|
||||||
|
if val >= MIN_GOOD_VERSION && val <= MAX_GOOD_VERSION {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_info *RouterInfo) UnCongested() bool {
|
||||||
|
caps := router_info.RouterCapabilities()
|
||||||
|
if strings.Contains(caps, "K") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if strings.Contains(caps, "G") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if strings.Contains(caps, "E") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router_info *RouterInfo) Reachable() bool {
|
||||||
|
caps := router_info.RouterCapabilities()
|
||||||
|
if strings.Contains(caps, "U") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.Contains(caps, "R")
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,6 @@ func TestRouterAddressesReturnsAddresses(t *testing.T) {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) {
|
func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) {
|
||||||
@ -162,7 +161,6 @@ func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPeerSizeIsZero(t *testing.T) {
|
func TestPeerSizeIsZero(t *testing.T) {
|
||||||
@ -200,7 +198,7 @@ func TestRouterIdentityIsCorrect(t *testing.T) {
|
|||||||
|
|
||||||
router_info, _ := buildFullRouterInfo()
|
router_info, _ := buildFullRouterInfo()
|
||||||
router_identity := router_info.RouterIdentity()
|
router_identity := router_info.RouterIdentity()
|
||||||
//assert.Nil(err)
|
// assert.Nil(err)
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
0,
|
0,
|
||||||
bytes.Compare(
|
bytes.Compare(
|
||||||
|
Reference in New Issue
Block a user