move every struct into it's own directory in order to run tests individually.

This commit is contained in:
idk
2022-05-22 19:59:20 -04:00
parent 13b996d0da
commit 171f09bba6
33 changed files with 63 additions and 22 deletions

View 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
}

View 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),
),
)
}