mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-07 15:07:16 -04:00
move every struct into it's own directory in order to run tests individually.
This commit is contained in:
279
lib/common/router_info/router_info.go
Normal file
279
lib/common/router_info/router_info.go
Normal file
@ -0,0 +1,279 @@
|
||||
package common
|
||||
|
||||
/*
|
||||
I2P RouterInfo
|
||||
https://geti2p.net/spec/common-structures#routerinfo
|
||||
Accurate for version 0.9.24
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| router_ident |
|
||||
+ +
|
||||
| |
|
||||
~ ~
|
||||
~ ~
|
||||
| |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| published |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
|size| RouterAddress 0 |
|
||||
+----+ +
|
||||
| |
|
||||
~ ~
|
||||
~ ~
|
||||
| |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| RouterAddress 1 |
|
||||
+ +
|
||||
| |
|
||||
~ ~
|
||||
~ ~
|
||||
| |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| RouterAddress ($size-1) |
|
||||
+ +
|
||||
| |
|
||||
~ ~
|
||||
~ ~
|
||||
| |
|
||||
+----+----+----+----+-//-+----+----+----+
|
||||
|psiz| options |
|
||||
+----+----+----+----+-//-+----+----+----+
|
||||
| signature |
|
||||
+ +
|
||||
| |
|
||||
+ +
|
||||
| |
|
||||
+ +
|
||||
| |
|
||||
+ +
|
||||
| |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
|
||||
router_ident :: RouterIdentity
|
||||
length -> >= 387 bytes
|
||||
|
||||
published :: Date
|
||||
length -> 8 bytes
|
||||
|
||||
size :: Integer
|
||||
length -> 1 byte
|
||||
The number of RouterAddresses to follow, 0-255
|
||||
|
||||
addresses :: [RouterAddress]
|
||||
length -> varies
|
||||
|
||||
peer_size :: Integer
|
||||
length -> 1 byte
|
||||
The number of peer Hashes to follow, 0-255, unused, always zero
|
||||
value -> 0
|
||||
|
||||
options :: Mapping
|
||||
|
||||
signature :: Signature
|
||||
length -> 40 bytes
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/router_address"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/router_identity"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/signature"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const ROUTER_INFO_MIN_SIZE = 439
|
||||
|
||||
type RouterInfo struct {
|
||||
router_identity *RouterIdentity
|
||||
published *Date
|
||||
size *Integer
|
||||
addresses []*RouterAddress
|
||||
peer_size *Integer
|
||||
options *Mapping
|
||||
signature *Signature
|
||||
}
|
||||
|
||||
//[]byte
|
||||
|
||||
//
|
||||
// Read a RouterIdentity from the RouterInfo, returning the RouterIdentity and any errors
|
||||
// encountered parsing the RouterIdentity.
|
||||
//
|
||||
func (router_info *RouterInfo) RouterIdentity() *RouterIdentity {
|
||||
return router_info.router_identity
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate this RouterInfo's Identity Hash (the sha256 of the RouterIdentity)
|
||||
// returns error if the RouterIdentity is malformed
|
||||
//
|
||||
func (router_info *RouterInfo) IdentHash() Hash {
|
||||
ri := router_info.RouterIdentity()
|
||||
h := HashData(ri.KeysAndCert.Certificate().Data())
|
||||
return h
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Date the RouterInfo was published and any errors encountered parsing the RouterInfo.
|
||||
//
|
||||
func (router_info *RouterInfo) Published() *Date {
|
||||
return router_info.published
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Integer representing the number of RouterAddresses that are contained in this RouterInfo.
|
||||
//
|
||||
func (router_info *RouterInfo) RouterAddressCount() int {
|
||||
return router_info.size.Int()
|
||||
}
|
||||
|
||||
//
|
||||
// Read the RouterAddresses inside this RouterInfo and return them in a slice, returning
|
||||
// a partial list if data is missing.
|
||||
//
|
||||
func (router_info *RouterInfo) RouterAddresses() []*RouterAddress {
|
||||
return router_info.addresses
|
||||
}
|
||||
|
||||
//
|
||||
// Return the PeerSize value, currently unused and always zero.
|
||||
//
|
||||
func (router_info *RouterInfo) PeerSize() int {
|
||||
// Peer size is unused:
|
||||
// https://geti2p.net/spec/common-structures#routeraddress
|
||||
return 0
|
||||
}
|
||||
|
||||
//
|
||||
// Return the Options Mapping inside this RouterInfo.
|
||||
//
|
||||
func (router_info RouterInfo) Options() (mapping Mapping) {
|
||||
return *router_info.options
|
||||
}
|
||||
|
||||
//
|
||||
// Return the signature of this router info
|
||||
//
|
||||
func (router_info RouterInfo) Signature() (signature Signature) {
|
||||
return *router_info.signature
|
||||
}
|
||||
|
||||
//
|
||||
// Used during parsing to determine where in the RouterInfo the Mapping data begins.
|
||||
//
|
||||
/*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
|
||||
}*/
|
||||
|
||||
func ReadRouterInfo(bytes []byte) (info RouterInfo, remainder []byte, err error) {
|
||||
identity, remainder, err := NewRouterIdentity(bytes)
|
||||
info.router_identity = identity
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(bytes),
|
||||
"required_len": ROUTER_INFO_MIN_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
date, remainder, err := NewDate(remainder)
|
||||
info.published = date
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(remainder),
|
||||
"required_len": DATE_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
size, remainder, err := NewInteger(remainder)
|
||||
info.size = size
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(remainder),
|
||||
"required_len": INTEGER_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
addresses := make([]*RouterAddress, size.Int())
|
||||
for i := 0; i < size.Int(); i++ {
|
||||
address, remainder, err := NewRouterAddress(remainder)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(remainder),
|
||||
//"required_len": ROUTER_ADDRESS_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
addresses = append(addresses, address)
|
||||
}
|
||||
info.addresses = addresses
|
||||
peer_size := Integer(remainder[:1])
|
||||
info.peer_size = &peer_size
|
||||
remainder = remainder[1:]
|
||||
options, remainder, err := NewMapping(remainder)
|
||||
info.options = options
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"at": "(RouterInfo) ReadRouterInfo",
|
||||
"data_len": len(remainder),
|
||||
//"required_len": MAPPING_SIZE,
|
||||
"reason": "not enough data",
|
||||
}).Error("error parsing router info")
|
||||
err = errors.New("error parsing router info: not enough data")
|
||||
}
|
||||
return
|
||||
}
|
191
lib/common/router_info/router_info_test.go
Normal file
191
lib/common/router_info/router_info_test.go
Normal file
@ -0,0 +1,191 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func buildRouterIdentity() RouterIdentity {
|
||||
router_ident_data := make([]byte, 128+256)
|
||||
router_ident_data = append(router_ident_data, []byte{0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00}...)
|
||||
return RouterIdentity(router_ident_data)
|
||||
}
|
||||
|
||||
func buildDate() []byte {
|
||||
date_data := []byte{0x00, 0x00, 0x00, 0x00, 0x05, 0x26, 0x5c, 0x00}
|
||||
return date_data
|
||||
}
|
||||
|
||||
func buildMapping() Mapping {
|
||||
mapping, _ := GoMapToMapping(map[string]string{"host": "127.0.0.1", "port": "4567"})
|
||||
return mapping
|
||||
}
|
||||
|
||||
func buildRouterAddress(transport string) RouterAddress {
|
||||
router_address_bytes := []byte{0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||||
str, _ := ToI2PString(transport)
|
||||
router_address_bytes = append(router_address_bytes, []byte(str)...)
|
||||
router_address_bytes = append(router_address_bytes, buildMapping()...)
|
||||
return RouterAddress(router_address_bytes)
|
||||
}
|
||||
|
||||
func buildFullRouterInfo() RouterInfo {
|
||||
router_info_data := make([]byte, 0)
|
||||
router_info_data = append(router_info_data, buildRouterIdentity()...)
|
||||
router_info_data = append(router_info_data, buildDate()...)
|
||||
router_info_data = append(router_info_data, 0x01)
|
||||
router_info_data = append(router_info_data, buildRouterAddress("foo")...)
|
||||
router_info_data = append(router_info_data, 0x00)
|
||||
router_info_data = append(router_info_data, buildMapping()...)
|
||||
router_info_data = append(router_info_data, make([]byte, 40)...)
|
||||
return RouterInfo(router_info_data)
|
||||
}
|
||||
|
||||
func TestPublishedReturnsCorrectDate(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
date, err := router_info.Published()
|
||||
assert.Nil(err)
|
||||
assert.Equal(int64(86400), date.Time().Unix(), "RouterInfo.Published() did not return correct date")
|
||||
}
|
||||
|
||||
func TestPublishedReturnsCorrectErrorWithPartialDate(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
router_info = router_info[:387+4]
|
||||
_, err := router_info.Published()
|
||||
if assert.NotNil(err) {
|
||||
assert.Equal("error parsing date: not enough data", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishedReturnsCorrectErrorWithInvalidData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
router_info = router_info[:56]
|
||||
_, err := router_info.Published()
|
||||
if assert.NotNil(err) {
|
||||
assert.Equal("error parsing KeysAndCert: data is smaller than minimum valid size", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterAddressCountReturnsCorrectCount(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
count, err := router_info.RouterAddressCount()
|
||||
assert.Nil(err)
|
||||
assert.Equal(1, count, "RouterInfo.RouterAddressCount() did not return correct count")
|
||||
}
|
||||
|
||||
func TestRouterAddressCountReturnsCorrectErrorWithInvalidData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
router_info = router_info[:387+8]
|
||||
count, err := router_info.RouterAddressCount()
|
||||
if assert.NotNil(err) {
|
||||
assert.Equal("error parsing router addresses: not enough data", err.Error())
|
||||
}
|
||||
assert.Equal(0, count)
|
||||
}
|
||||
|
||||
func TestRouterAddressesReturnsAddresses(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
router_addresses, err := router_info.RouterAddresses()
|
||||
assert.Nil(err)
|
||||
if assert.Equal(1, len(router_addresses)) {
|
||||
assert.Equal(
|
||||
0,
|
||||
bytes.Compare(
|
||||
[]byte(buildRouterAddress("foo")),
|
||||
[]byte(router_addresses[0]),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterAddressesReturnsAddressesWithMultiple(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info_data := make([]byte, 0)
|
||||
router_info_data = append(router_info_data, buildRouterIdentity()...)
|
||||
router_info_data = append(router_info_data, buildDate()...)
|
||||
router_info_data = append(router_info_data, 0x03)
|
||||
router_info_data = append(router_info_data, buildRouterAddress("foo0")...)
|
||||
router_info_data = append(router_info_data, buildRouterAddress("foo1")...)
|
||||
router_info_data = append(router_info_data, buildRouterAddress("foo2")...)
|
||||
router_info_data = append(router_info_data, 0x00)
|
||||
router_info_data = append(router_info_data, buildMapping()...)
|
||||
router_info_data = append(router_info_data, make([]byte, 40)...)
|
||||
router_info := RouterInfo(router_info_data)
|
||||
|
||||
count, err := router_info.RouterAddressCount()
|
||||
if assert.Equal(3, count) && assert.Nil(err) {
|
||||
router_addresses, err := router_info.RouterAddresses()
|
||||
if assert.Nil(err) {
|
||||
for i := 0; i < 3; i++ {
|
||||
assert.Equal(
|
||||
0,
|
||||
bytes.Compare(
|
||||
[]byte(buildRouterAddress(fmt.Sprintf("foo%d", i))),
|
||||
[]byte(router_addresses[i]),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestPeerSizeIsZero(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
size := router_info.PeerSize()
|
||||
assert.Equal(0, size, "RouterInfo.PeerSize() did not return 0")
|
||||
}
|
||||
|
||||
func TestOptionsAreCorrect(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
options := router_info.Options()
|
||||
assert.Equal(
|
||||
0,
|
||||
bytes.Compare(
|
||||
[]byte(buildMapping()),
|
||||
[]byte(options),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestSignatureIsCorrectSize(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
signature := router_info.Signature()
|
||||
assert.Equal(40, len(signature))
|
||||
}
|
||||
|
||||
func TestRouterIdentityIsCorrect(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
router_info := buildFullRouterInfo()
|
||||
router_identity, err := router_info.RouterIdentity()
|
||||
assert.Nil(err)
|
||||
assert.Equal(
|
||||
0,
|
||||
bytes.Compare(
|
||||
[]byte(buildRouterIdentity()),
|
||||
[]byte(router_identity),
|
||||
),
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user