2016-02-01 01:56:10 -08:00
|
|
|
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"
|
2021-04-19 20:43:37 -04:00
|
|
|
log "github.com/sirupsen/logrus"
|
2016-02-07 02:54:02 -08:00
|
|
|
)
|
|
|
|
|
2016-02-01 01:56:10 -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-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
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")
|
2016-02-13 21:00:29 -08:00
|
|
|
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])
|
2016-02-01 01:56:10 -08:00
|
|
|
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")
|
2016-02-13 21:00:29 -08:00
|
|
|
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-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
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")
|
2016-02-13 21:00:29 -08:00
|
|
|
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-01 01:56:10 -08:00
|
|
|
}
|
2016-02-07 02:54:02 -08:00
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
|
|
|
// Return the PeerSize value, currently unused and always zero.
|
|
|
|
//
|
2016-02-01 01:56:10 -08:00
|
|
|
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
|
2016-02-01 01:56:10 -08:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-13 21:00:29 -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) {
|
2016-02-01 01:56:10 -08:00
|
|
|
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-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
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) {
|
2016-02-13 21:00:29 -08:00
|
|
|
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-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
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:]
|
2016-02-01 01:56:10 -08:00
|
|
|
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-02-01 01:56:10 -08:00
|
|
|
}
|
2016-07-02 17:22:14 -07:00
|
|
|
location += 1
|
2016-02-15 01:13:44 -08:00
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
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) {
|
2016-02-01 01:56:10 -08:00
|
|
|
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
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|