Add DatabaseLookup and test it

This commit is contained in:
satk0
2025-02-26 21:21:09 +01:00
parent 17a789bed7
commit 89e51820f1
3 changed files with 720 additions and 14 deletions

View File

@ -1,5 +1,5 @@
test-i2np-header-all: test-i2np-type test-i2np-message test-i2np-expiration test-i2np-ntcp-components test-i2np-data test-i2np-regression test-i2np-build-request-record test-i2np-build-response-record test-i2np-header-all: test-i2np-type test-i2np-message test-i2np-expiration test-i2np-ntcp-components test-i2np-data test-i2np-regression test-i2np-build-request-record test-i2np-build-response-record test-i2np-database-lookup
test-i2np-type: test-i2np-type:
$(GO) test -v ./lib/i2np -run TestReadI2NPTypeWith $(GO) test -v ./lib/i2np -run TestReadI2NPTypeWith
@ -37,6 +37,31 @@ test-i2np-build-response-record:
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordTooLittleData $(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordTooLittleData
$(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordValidData $(GO) test -v ./lib/i2np -run TestReadBuildResponseRecordValidData
test-i2np-database-lookup:
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupKeyTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupKeyValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFromTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFromValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFlagsTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupFlagsValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTunnelIDTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTunnelIDNotIncluded
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTunnelIDValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupSizeTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupSizeValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupExcludedPeersTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupExcludedPeersZeroSize
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupExcludedPeersValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyKeyTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyKeyValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupTagsTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupTagsValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTagsTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTagsZeroTags
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupReplyTagsValidData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupTooLittleData
$(GO) test -v ./lib/i2np -run TestReadDatabaseLookupValidData
.PHONY: test-i2np-header-all \ .PHONY: test-i2np-header-all \
test-i2np-type \ test-i2np-type \
test-i2np-message \ test-i2np-message \
@ -45,4 +70,5 @@ test-i2np-build-response-record:
test-i2np-data \ test-i2np-data \
test-i2np-regression \ test-i2np-regression \
test-i2np-build-request-record \ test-i2np-build-request-record \
test-i2np-build-response-record test-i2np-build-response-record \
test-i2np-database-lookup

View File

@ -1,6 +1,10 @@
package i2np package i2np
import ( import (
"errors"
"github.com/sirupsen/logrus"
common "github.com/go-i2p/go-i2p/lib/common/data" common "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/session_key" "github.com/go-i2p/go-i2p/lib/common/session_key"
"github.com/go-i2p/go-i2p/lib/common/session_tag" "github.com/go-i2p/go-i2p/lib/common/session_tag"
@ -8,8 +12,8 @@ import (
/* /*
I2P I2NP DatabaseLookup I2P I2NP DatabaseLookup
https://geti2p.net/spec/i2np https://geti2p.net/spec/i2np#databaselookup
Accurate for version 0.9.28 Accurate for version 0.9.65
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
| SHA256 hash as the key to look up | | SHA256 hash as the key to look up |
@ -21,7 +25,7 @@ Accurate for version 0.9.28
| | | |
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
| SHA256 hash of the routerInfo | | SHA256 hash of the routerInfo |
+ who is asking, or the gateway to + + who is asking or the gateway to +
| send the reply to | | send the reply to |
+ + + +
| | | |
@ -30,7 +34,7 @@ Accurate for version 0.9.28
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
|flag| reply_tunnelId | size | | |flag| reply_tunnelId | size | |
+----+----+----+----+----+----+----+ + +----+----+----+----+----+----+----+ +
| SHA256 of $key1 to exclude | | SHA256 of key1 to exclude |
+ + + +
| | | |
+ + + +
@ -38,7 +42,7 @@ Accurate for version 0.9.28
+ +----+ + +----+
| | | | | |
+----+----+----+----+----+----+----+ + +----+----+----+----+----+----+----+ +
| SHA256 of $key2 to exclude | | SHA256 of key2 to exclude |
+ + + +
~ ~ ~ ~
+ +----+ + +----+
@ -95,12 +99,20 @@ flags ::
with version 0.9.16 or higher. with version 0.9.16 or higher.
01 => LS lookup, return LeaseSet or 01 => LS lookup, return LeaseSet or
DatabaseSearchReplyMessage DatabaseSearchReplyMessage
As of release 0.9.38, may also return a
LeaseSet2, MetaLeaseSet, or EncryptedLeaseSet.
10 => RI lookup, return RouterInfo or 10 => RI lookup, return RouterInfo or
DatabaseSearchReplyMessage DatabaseSearchReplyMessage
11 => exploration lookup, return DatabaseSearchReplyMessage 11 => exploration lookup, return DatabaseSearchReplyMessage
containing non-floodfill routers only (replaces an containing non-floodfill routers only (replaces an
excludedPeer of all zeroes) excludedPeer of all zeroes)
bits 7-4: bit 4: ECIESFlag
before release 0.9.46 ignored
as of release 0.9.46:
0 => send unencrypted or ElGamal reply
1 => send ChaCha/Poly encrypted reply using enclosed key
(whether tag is enclosed depends on bit 1)
bits 7-5:
through release 0.9.5, must be set to 0 through release 0.9.5, must be set to 0
as of release 0.9.6, ignored, set to 0 for compatibility with as of release 0.9.6, ignored, set to 0 for compatibility with
future uses and with older routers future uses and with older routers
@ -108,7 +120,7 @@ flags ::
reply_tunnelId :: reply_tunnelId ::
4 byte TunnelID 4 byte TunnelID
only included if deliveryFlag == 1 only included if deliveryFlag == 1
tunnelId of the tunnel to send the reply to tunnelId of the tunnel to send the reply to, nonzero
size :: size ::
2 byte Integer 2 byte Integer
@ -124,18 +136,53 @@ excludedPeers ::
to list non-floodfill routers only. to list non-floodfill routers only.
reply_key :: reply_key ::
32 byte SessionKey 32 byte key
only included if encryptionFlag == 1, only as of release 0.9.7 see below
tags :: tags ::
1 byte Integer 1 byte Integer
valid range: 1-32 (typically 1) valid range: 1-32 (typically 1)
the number of reply tags that follow the number of reply tags that follow
only included if encryptionFlag == 1, only as of release 0.9.7 see below
reply_tags ::
one or more 8 or 32 byte session tags (typically one)
see below
ElG to ElG
reply_key ::
32 byte SessionKey big-endian
only included if encryptionFlag == 1 AND ECIESFlag == 0, only as of release 0.9.7
tags ::
1 byte Integer
valid range: 1-32 (typically 1)
the number of reply tags that follow
only included if encryptionFlag == 1 AND ECIESFlag == 0, only as of release 0.9.7
reply_tags :: reply_tags ::
one or more 32 byte SessionTags (typically one) one or more 32 byte SessionTags (typically one)
only included if encryptionFlag == 1, only as of release 0.9.7 only included if encryptionFlag == 1 AND ECIESFlag == 0, only as of release 0.9.7
ECIES to ElG
reply_key ::
32 byte ECIES SessionKey big-endian
only included if encryptionFlag == 0 AND ECIESFlag == 1, only as of release 0.9.46
tags ::
1 byte Integer
required value: 1
the number of reply tags that follow
only included if encryptionFlag == 0 AND ECIESFlag == 1, only as of release 0.9.46
reply_tags ::
an 8 byte ECIES SessionTag
only included if encryptionFlag == 0 AND ECIESFlag == 1, only as of release 0.9.46
*/ */
type DatabaseLookup struct { type DatabaseLookup struct {
@ -146,6 +193,209 @@ type DatabaseLookup struct {
Size int Size int
ExcludedPeers []common.Hash ExcludedPeers []common.Hash
ReplyKey session_key.SessionKey ReplyKey session_key.SessionKey
tags int Tags int
ReplyTags []session_tag.SessionTag ReplyTags []session_tag.SessionTag
} }
var ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA = errors.New("not enough i2np database lookup data")
func ReadDatabaseLookup(data []byte) (DatabaseLookup, error) {
log.Debug("Reading DatabaseLookup")
databaseLookup := DatabaseLookup{}
length, key, err := readDatabaseLookupKey(data)
if err != nil {
log.WithError(err).Error("Failed to read Key")
return databaseLookup, err
}
databaseLookup.Key = key
length, from, err := readDatabaseLookupFrom(length, data)
if err != nil {
log.WithError(err).Error("Failed to read From")
return databaseLookup, err
}
databaseLookup.From = from
length, flags, err := readDatabaseLookupFlags(length, data)
if err != nil {
log.WithError(err).Error("Failed to read Flags")
return databaseLookup, err
}
databaseLookup.Flags = flags
length, replyTunnelID, err := readDatabaseLookupReplyTunnelID(flags, length, data)
if err != nil {
log.WithError(err).Error("Failed to read ReplyTunnelID")
return databaseLookup, err
}
databaseLookup.ReplyTunnelID = replyTunnelID
length, size, err := readDatabaseLookupSize(length, data)
if err != nil {
log.WithError(err).Error("Failed to read Size")
return databaseLookup, err
}
databaseLookup.Size = size
length, excludedPeers, err := readDatabaseLookupExcludedPeers(length, data, size)
if err != nil {
log.WithError(err).Error("Failed to read ExcludedPeers")
return databaseLookup, err
}
databaseLookup.ExcludedPeers = excludedPeers
length, reply_key, err := readDatabaseLookupReplyKey(length, data)
if err != nil {
log.WithError(err).Error("Failed to read ReplyKey")
return databaseLookup, err
}
databaseLookup.ReplyKey = reply_key
length, tags, err := readDatabaseLookupTags(length, data)
if err != nil {
log.WithError(err).Error("Failed to read Tags")
return databaseLookup, err
}
databaseLookup.Tags = tags
length, reply_tags, err := readDatabaseLookupReplyTags(length, data, tags)
if err != nil {
log.WithError(err).Error("Failed to read ReplyTags")
return databaseLookup, err
}
databaseLookup.ReplyTags = reply_tags
log.Debug("DatabaseLookup read successfully")
return databaseLookup, nil
}
func readDatabaseLookupKey(data []byte) (int, common.Hash, error) {
if len(data) < 32 {
return 0, common.Hash{}, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
key := common.Hash(data[:32])
log.WithFields(logrus.Fields{
"at": "i2np.readDatabaseLookupKey",
"key": key,
}).Debug("parsed_database_lookup_key")
return 32, key, nil
}
func readDatabaseLookupFrom(length int, data []byte) (int, common.Hash, error) {
if len(data) < length + 32 {
return length, common.Hash{}, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
from := common.Hash(data[length:length + 32])
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupFrom",
"from": from,
}).Debug("parsed_database_lookup_from")
return length + 32, from, nil
}
func readDatabaseLookupFlags(length int, data []byte) (int, byte, error) {
if len(data) < length + 1 {
return length, byte(0), ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
flags := data[length]
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupFlags",
"flags": flags,
}).Debug("parsed_database_lookup_flags")
return length + 1, flags, nil
}
func readDatabaseLookupReplyTunnelID(flags byte, length int, data []byte) (int, [4]byte, error) {
if flags & 1 != 1 {
return length, [4]byte{}, nil
}
if len(data) < length + 4 {
return length, [4]byte{}, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
replyTunnelID := [4]byte(data[length:length + 4])
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupReplyTunnelID",
"reply_tunnel_id": replyTunnelID,
}).Debug("parsed_database_lookup_reply_tunnel_id")
return length + 4, replyTunnelID, nil
}
func readDatabaseLookupSize(length int, data []byte) (int, int, error) {
if len(data) < length + 2 {
return length, 0, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
size := common.Integer(data[length:length + 2]).Int()
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupSize",
"size": size,
}).Debug("parsed_database_lookup_size")
return length + 2, size, nil
}
func readDatabaseLookupExcludedPeers(length int, data []byte, size int) (int, []common.Hash, error) {
if len(data) < length + size * 32 {
return length, []common.Hash{}, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
var excludedPeers []common.Hash
for i := 0; i < size; i++ {
offset := length + i * 32
peer := common.Hash(data[offset:offset + 32])
excludedPeers = append(excludedPeers, peer)
}
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupExcludedPeers",
"excluded_peers": excludedPeers,
}).Debug("parsed_database_lookup_excluded_peers")
return length + size * 32, excludedPeers, nil
}
func readDatabaseLookupReplyKey(length int, data []byte) (int, session_key.SessionKey, error) {
if len(data) < length + 32 {
return length, session_key.SessionKey{}, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
replyKey := session_key.SessionKey(data[length:length + 32])
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupReplyKey",
"reply_key": replyKey,
}).Debug("parsed_database_lookup_reply_key")
return length + 32, replyKey, nil
}
func readDatabaseLookupTags(length int, data []byte) (int, int, error) {
if len(data) < length + 1 {
return length, 0, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
tags := int(data[length])
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupTags",
"tags": tags,
}).Debug("parsed_database_lookup_tags")
return length + 1, tags, nil
}
func readDatabaseLookupReplyTags(length int, data []byte, tags int) (int, []session_tag.SessionTag, error) {
if len(data) < length + tags * 32 {
return length, []session_tag.SessionTag{}, ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA
}
var reply_tags []session_tag.SessionTag
for i := 0; i < tags; i++ {
offset := length + i * 32
tag := session_tag.SessionTag(data[offset:offset + 32])
reply_tags = append(reply_tags, tag)
}
log.WithFields(logrus.Fields{
"at": "i2np.database_lookup.readDatabaseLookupReplyTags",
"reply_tags": reply_tags,
}).Debug("parsed_database_lookup_reply_tags")
return length + tags * 32, reply_tags, nil
}

View File

@ -0,0 +1,430 @@
package i2np
import (
"testing"
common "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/common/session_key"
"github.com/go-i2p/go-i2p/lib/common/session_tag"
"github.com/stretchr/testify/assert"
)
func TestReadDatabaseLookupKeyTooLittleData(t *testing.T) {
assert := assert.New(t)
length, key, err := readDatabaseLookupKey([]byte{0x01})
assert.Equal(0, length)
assert.Equal(common.Hash{}, key)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupKeyValidData(t *testing.T) {
assert := assert.New(t)
data := make([]byte, 32)
for i := range 31 {
data[i] = 0x31
}
length, key, err := readDatabaseLookupKey(data)
expected := common.Hash(data)
assert.Equal(32, length)
assert.Equal(expected, key)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupFromTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 32
prev := make([]byte, length)
data := append(prev, 0x01)
length, key, err := readDatabaseLookupFrom(length, data)
assert.Equal(32, length)
assert.Equal(common.Hash{}, key)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupFromValidData(t *testing.T) {
assert := assert.New(t)
length := 32
prev := make([]byte, length)
expectedFrom := make([]byte, 32)
expectedFrom[23] = 0x21
expectedFrom[29] = 0x37
data := append(prev, expectedFrom...)
length, from, err := readDatabaseLookupFrom(length, data)
expected := common.Hash(expectedFrom)
assert.Equal(64, length)
assert.Equal(from, expected)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupFlagsTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 64
prev := make([]byte, length)
data := prev
length, flags, err := readDatabaseLookupFlags(length, data)
assert.Equal(64, length)
assert.Equal(byte(0), flags)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupFlagsValidData(t *testing.T) {
assert := assert.New(t)
length := 64
prev := make([]byte, length)
expected := byte(0x1)
data := append(prev, expected)
length, flags, err := readDatabaseLookupFlags(length, data)
assert.Equal(65, length)
assert.Equal(flags, expected)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupReplyTunnelIDTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 64
prev := make([]byte, length)
flag := byte(0x1)
data := append(prev, flag)
excessData := make([]byte, 2)
excessData[1] = 0x32
data = append(data, excessData...)
length, flags, err := readDatabaseLookupFlags(length, data)
length, replyTunnelID, err := readDatabaseLookupReplyTunnelID(flags, length, data)
assert.Equal(65, length)
assert.Equal([4]byte{}, replyTunnelID)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupReplyTunnelIDNotIncluded(t *testing.T) {
assert := assert.New(t)
length := 65
data := make([]byte, length)
length, flags, err := readDatabaseLookupFlags(length, data)
length, tunnelID, err := readDatabaseLookupReplyTunnelID(flags, length, data)
assert.Equal(65, length)
assert.Equal([4]byte{}, tunnelID)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupReplyTunnelIDValidData(t *testing.T) {
assert := assert.New(t)
length := 64
prev := make([]byte, length)
flag := byte(0x1)
data := append(prev, flag)
expected := make([]byte, 4)
expected[1] = 0x32
expected[3] = 0x34
data = append(data, expected...)
length, flags, err := readDatabaseLookupFlags(length, data)
length, replyTunnelID, err := readDatabaseLookupReplyTunnelID(flags, length, data)
assert.Equal(69, length)
assert.Equal([4]byte(expected), replyTunnelID)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupSizeTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 65
data := make([]byte, length)
data = append(data, 0x2)
length, size, err := readDatabaseLookupSize(length, data)
assert.Equal(65, length)
assert.Equal(0, size)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupSizeValidData(t *testing.T) {
assert := assert.New(t)
length := 65
data := make([]byte, length)
expectedSizeData := []byte{0x16,0x9}
data = append(data, expectedSizeData...)
length, size, err := readDatabaseLookupSize(length, data)
assert.Equal(67, length)
assert.Equal(common.Integer(expectedSizeData).Int(), size)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupExcludedPeersTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 65
data := make([]byte, length)
sizeData := []byte{0x0,0x3}
data = append(data, sizeData...)
data = append(data, 0x23)
length, size, err := readDatabaseLookupSize(length, data)
length, excludedPeers, err := readDatabaseLookupExcludedPeers(length, data, size)
assert.Equal([]common.Hash{}, excludedPeers)
assert.Equal(67, length)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupExcludedPeersZeroSize(t *testing.T) {
assert := assert.New(t)
length := 65
data := make([]byte, length)
sizeData := []byte{0x0,0x0}
data = append(data, sizeData...)
data = append(data, 0x23)
length, size, err := readDatabaseLookupSize(length, data)
var expectedExcludedPeers []common.Hash
length, excludedPeers, err := readDatabaseLookupExcludedPeers(length, data, size)
assert.Equal(expectedExcludedPeers, excludedPeers)
assert.Equal(67, length)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupExcludedPeersValidData(t *testing.T) {
assert := assert.New(t)
length := 65
data := make([]byte, length)
sizeData := []byte{0x0,0x3}
data = append(data, sizeData...)
length, size, err := readDatabaseLookupSize(length, data)
var expectedExcludedPeers []common.Hash
for i := range size {
peer := make([]byte, 32)
// random data:
peer[i + 1] = 0x43
peer[i + 23] = 0x89
expectedExcludedPeers = append(expectedExcludedPeers, common.Hash(peer))
data = append(data, peer...)
}
length, excludedPeers, err := readDatabaseLookupExcludedPeers(length, data, size)
assert.Equal(expectedExcludedPeers, excludedPeers)
assert.Equal(67 + 32 * size, length)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupReplyKeyTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 67
data := make([]byte, length)
data = append(data, 0x2)
length, replyKey, err := readDatabaseLookupReplyKey(length, data)
assert.Equal(67, length)
assert.Equal(session_key.SessionKey{}, replyKey)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupReplyKeyValidData(t *testing.T) {
assert := assert.New(t)
length := 67
data := make([]byte, length)
expectedReplyKeyData := make([]byte, 32)
expectedReplyKeyData[3] = 0x31
expectedReplyKey := session_key.SessionKey(expectedReplyKeyData)
data = append(data, expectedReplyKeyData...)
length, replyKey, err := readDatabaseLookupReplyKey(length, data)
assert.Equal(67 + 32, length)
assert.Equal(expectedReplyKey, replyKey)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupTagsTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 99
data := make([]byte, length)
length, tags, err := readDatabaseLookupTags(length, data)
assert.Equal(99, length)
assert.Equal(0, tags)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupTagsValidData(t *testing.T) {
assert := assert.New(t)
length := 99
data := make([]byte, length)
expected := 121
data = append(data, byte(expected))
length, tags, err := readDatabaseLookupTags(length, data)
assert.Equal(100, length)
assert.Equal(expected, tags)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupReplyTagsTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 99
data := make([]byte, length)
tags := 10
data = append(data, byte(tags))
data = append(data, 0x34)
length, tags, err := readDatabaseLookupTags(length, data)
length, replyTags, err := readDatabaseLookupReplyTags(length, data, tags)
assert.Equal(100, length)
assert.Equal([]session_tag.SessionTag{}, replyTags)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupReplyTagsZeroTags(t *testing.T) {
assert := assert.New(t)
length := 99
data := make([]byte, length)
tags := 0
data = append(data, byte(tags))
data = append(data, 0x23)
length, tags, err := readDatabaseLookupTags(length, data)
var expectedReplyTags []session_tag.SessionTag
length, replyTags, err := readDatabaseLookupReplyTags(length, data, tags)
assert.Equal(expectedReplyTags, replyTags)
assert.Equal(100, length)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupReplyTagsValidData(t *testing.T) {
assert := assert.New(t)
length := 99
data := make([]byte, length)
tags := 10
data = append(data, byte(tags))
length, tags, err := readDatabaseLookupTags(length, data)
var expectedReplyTags []session_tag.SessionTag
for i := range tags {
tag := make([]byte, 32)
// random data:
tag[i + 1] = 0x43
tag[i + 5] = 0x89
expectedReplyTags = append(expectedReplyTags, session_tag.SessionTag(tag))
data = append(data, tag...)
}
length, replyTags, err := readDatabaseLookupReplyTags(length, data, tags)
assert.Equal(expectedReplyTags, replyTags)
assert.Equal(100 + 32 * tags, length)
assert.Equal(nil, err)
}
func TestReadDatabaseLookupTooLittleData(t *testing.T) {
assert := assert.New(t)
length := 67
data := make([]byte, length)
expectedReplyKeyData := make([]byte, 32)
expectedReplyKeyData[3] = 0x31
expectedReplyKey := session_key.SessionKey(expectedReplyKeyData)
data = append(data, expectedReplyKeyData...)
databaseLookup, err := ReadDatabaseLookup(data)
assert.Equal(expectedReplyKey, databaseLookup.ReplyKey)
assert.Equal(ERR_DATABASE_LOOKUP_NOT_ENOUGH_DATA, err)
}
func TestReadDatabaseLookupValidData(t *testing.T) {
assert := assert.New(t)
data := make([]byte, 32)
for i := range 31 {
data[i] = 0x31
}
expectedKey := common.Hash(data)
from := make([]byte, 32)
from[14] = 0x69
from[27] = 0x15
data = append(data, from...)
expectedFrom := common.Hash(from)
expectedFlags := byte(0x1)
data = append(data, expectedFlags)
tunnelIDData := make([]byte, 4)
tunnelIDData[0] = 0xff
tunnelIDData[2] = 0xf2
data = append(data, tunnelIDData...)
expectedTunnelID := [4]byte(tunnelIDData)
sizeData := []byte{0x0,0xf}
data = append(data, sizeData...)
expectedSize := common.Integer(sizeData).Int()
var expectedExcludedPeers []common.Hash
for i := range expectedSize {
peer := make([]byte, 32)
// random data:
peer[i + 5] = 0xdd
peer[i + 13] = 0x35
expectedExcludedPeers = append(expectedExcludedPeers, common.Hash(peer))
data = append(data, peer...)
}
replyKeyData := make([]byte, 32)
replyKeyData[6] = 0x11
replyKeyData[14] = 0x13
data = append(data, replyKeyData...)
expectedReplyKey := session_key.SessionKey(replyKeyData)
expectedTags := 15
data = append(data, byte(expectedTags))
var expectedReplyTags []session_tag.SessionTag
for i := range expectedTags {
tag := make([]byte, 32)
// random data:
tag[i + 3] = 0x22
tag[i + 13] = 0x11
expectedReplyTags = append(expectedReplyTags, session_tag.SessionTag(tag))
data = append(data, tag...)
}
databaseLookup, err := ReadDatabaseLookup(data)
assert.Equal(expectedKey, databaseLookup.Key)
assert.Equal(expectedFrom, databaseLookup.From)
assert.Equal(expectedFlags, databaseLookup.Flags)
assert.Equal(expectedTunnelID, databaseLookup.ReplyTunnelID)
assert.Equal(expectedSize, databaseLookup.Size)
assert.Equal(expectedExcludedPeers, databaseLookup.ExcludedPeers)
assert.Equal(expectedReplyKey, databaseLookup.ReplyKey)
assert.Equal(expectedTags, databaseLookup.Tags)
assert.Equal(expectedReplyTags, databaseLookup.ReplyTags)
assert.Equal(err, nil)
}