Files
go-i2p/lib/common/router_info.go

269 lines
7.4 KiB
Go
Raw Normal View History

package common
2016-02-15 01:13:44 -08:00
/*
I2P RouterInfo
2016-06-16 23:17:21 -07:00
https://geti2p.net/spec/common-structures#routerinfo
2016-02-15 01:13:44 -08:00
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
*/
2016-02-07 02:54:02 -08:00
import (
"errors"
log "github.com/sirupsen/logrus"
2016-02-07 02:54:02 -08:00
)
type RouterInfo []byte
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
// Read a RouterIdentity from the RouterInfo, returning the RouterIdentity and any errors
// encountered parsing the RouterIdentity.
2016-02-07 02:54:02 -08:00
//
func (router_info RouterInfo) RouterIdentity() (router_identity RouterIdentity, err error) {
router_identity, _, err = ReadRouterIdentity(router_info)
return
}
2016-08-17 09:19:56 -04:00
//
// Calculate this RouterInfo's Identity Hash (the sha256 of the RouterIdentity)
// returns error if the RouterIdentity is malformed
//
func (router_info RouterInfo) IdentHash() (h Hash, err error) {
var ri RouterIdentity
ri, err = router_info.RouterIdentity()
if err == nil {
h = HashData(ri)
}
return
}
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
// Return the Date the RouterInfo was published and any errors encountered parsing the RouterInfo.
2016-02-07 02:54:02 -08:00
//
func (router_info RouterInfo) Published() (date Date, err error) {
2016-06-20 22:49:21 -07:00
_, remainder, err := ReadRouterIdentity(router_info)
if err != nil {
return
}
2016-02-15 01:13:44 -08:00
remainder_len := len(remainder)
if remainder_len < 8 {
log.WithFields(log.Fields{
2016-06-16 23:04:03 -07:00
"at": "(RouterInfo) Published",
2016-02-15 01:13:44 -08:00
"data_len": remainder_len,
"required_len": 8,
"reason": "not enough data",
}).Error("error parsing router info")
err = errors.New("error parsing date: not enough data")
2016-02-07 02:54:02 -08:00
return
}
2016-06-19 14:26:03 -07:00
copy(date[:], remainder[:8])
return
}
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
// Return the Integer representing the number of RouterAddresses that are contained in this RouterInfo.
2016-02-07 02:54:02 -08:00
//
func (router_info RouterInfo) RouterAddressCount() (count int, err error) {
2016-06-20 22:49:21 -07:00
_, remainder, err := ReadRouterIdentity(router_info)
if err != nil {
return
}
2016-02-15 01:13:44 -08:00
remainder_len := len(remainder)
if remainder_len < 9 {
log.WithFields(log.Fields{
2016-06-16 23:04:03 -07:00
"at": "(RouterInfo) RouterAddressCount",
2016-02-15 01:13:44 -08:00
"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")
2016-02-07 02:54:02 -08:00
return
}
count = Integer([]byte{remainder[8]})
return
}
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
// Read the RouterAddresses inside this RouterInfo and return them in a slice, returning
// a partial list if data is missing.
2016-02-07 02:54:02 -08:00
//
func (router_info RouterInfo) RouterAddresses() (router_addresses []RouterAddress, err error) {
2016-06-20 22:49:21 -07:00
_, remainder, err := ReadRouterIdentity(router_info)
if err != nil {
return
}
2016-02-15 01:13:44 -08:00
remainder_len := len(remainder)
if remainder_len < 9 {
log.WithFields(log.Fields{
2016-06-16 23:04:03 -07:00
"at": "(RouterInfo) RouterAddresses",
2016-02-15 01:13:44 -08:00
"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")
2016-02-07 02:54:02 -08:00
return
}
2016-06-22 21:06:03 -07:00
remaining := remainder[9:]
2016-02-07 02:54:02 -08:00
var router_address 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)
2016-02-01 08:06:24 -05:00
if err == nil {
2016-02-07 02:54:02 -08:00
router_addresses = append(router_addresses, router_address)
2016-02-01 08:06:24 -05:00
}
}
2016-02-07 02:54:02 -08:00
return
}
2016-02-07 02:54:02 -08:00
//
// Return the PeerSize value, currently unused and always zero.
//
func (router_info RouterInfo) PeerSize() int {
2016-02-07 02:54:02 -08:00
// Peer size is unused:
2016-06-16 23:17:21 -07:00
// https://geti2p.net/spec/common-structures#routeraddress
return 0
}
2016-02-07 02:54:02 -08:00
//
// Return the Options Mapping inside this RouterInfo.
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
func (router_info RouterInfo) Options() (mapping Mapping) {
head := router_info.optionsLocation()
size := head + router_info.optionsSize()
2016-02-15 01:13:44 -08:00
mapping = Mapping(router_info[head:size])
return
}
2016-02-07 02:54:02 -08:00
//
2017-04-06 10:20:19 -04:00
// Return the signature of this router info
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
func (router_info RouterInfo) Signature() (signature Signature) {
head := router_info.optionsLocation()
size := head + router_info.optionsSize()
2017-04-06 10:20:19 -04:00
ident, _ := router_info.RouterIdentity()
keyCert := KeyCertificate(ident)
sigSize := keyCert.SignatureSize()
signature = Signature(router_info[size : size+sigSize])
2016-02-15 01:13:44 -08:00
return
}
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
// Used during parsing to determine where in the RouterInfo the Mapping data begins.
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
func (router_info RouterInfo) optionsLocation() (location int) {
2016-07-02 17:22:14 -07:00
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
2016-07-02 17:22:14 -07:00
var router_addresses []RouterAddress
addr_count, cerr := router_info.RouterAddressCount()
if cerr != nil {
err = cerr
return
}
2016-02-07 02:54:02 -08:00
for i := 0; i < addr_count; i++ {
2016-07-02 17:22:14 -07:00
router_address, remaining, err = ReadRouterAddress(remaining)
if err == nil {
location += len(router_address)
router_addresses = append(router_addresses, router_address)
}
}
2016-07-02 17:22:14 -07:00
location += 1
2016-02-15 01:13:44 -08:00
return
}
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
// Used during parsing to determine the size of the options in the RouterInfo.
2016-02-07 02:54:02 -08:00
//
2016-02-15 01:13:44 -08:00
func (router_info RouterInfo) optionsSize() (size int) {
head := router_info.optionsLocation()
2016-07-02 17:22:14 -07:00
size = Integer(router_info[head:head+2]) + 2
2016-02-15 01:13:44 -08:00
return
}