2016-02-01 01:56:10 -08:00
|
|
|
package common
|
|
|
|
|
2016-02-15 00:34:29 -08:00
|
|
|
/*
|
|
|
|
I2P RouterAddress
|
2016-06-16 23:17:21 -07:00
|
|
|
https://geti2p.net/spec/common-structures#routeraddress
|
2016-02-15 00:34:29 -08:00
|
|
|
Accurate for version 0.9.24
|
|
|
|
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
|cost| expiration
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
| transport_style |
|
|
|
|
+----+----+----+----+-//-+----+----+----+
|
|
|
|
| |
|
|
|
|
+ +
|
|
|
|
| options |
|
|
|
|
~ ~
|
|
|
|
~ ~
|
|
|
|
| |
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
|
|
|
|
cost :: Integer
|
|
|
|
length -> 1 byte
|
|
|
|
|
|
|
|
case 0 -> free
|
|
|
|
case 255 -> expensive
|
|
|
|
|
|
|
|
expiration :: Date (must be all zeros, see notes below)
|
|
|
|
length -> 8 bytes
|
|
|
|
|
|
|
|
case null -> never expires
|
|
|
|
|
|
|
|
transport_style :: String
|
|
|
|
length -> 1-256 bytes
|
|
|
|
|
|
|
|
options :: Mapping
|
|
|
|
*/
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
import (
|
|
|
|
"errors"
|
2016-02-15 00:34:29 -08:00
|
|
|
log "github.com/Sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2016-02-16 01:04:40 -08:00
|
|
|
ROUTER_ADDRESS_MIN_SIZE = 9
|
2016-02-07 02:54:02 -08:00
|
|
|
)
|
|
|
|
|
2016-02-01 01:56:10 -08:00
|
|
|
type RouterAddress []byte
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-15 00:34:29 -08:00
|
|
|
// Return the cost integer for this RouterAddress and any errors encountered
|
|
|
|
// parsing the RouterAddress.
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
|
|
|
func (router_address RouterAddress) Cost() (cost int, err error) {
|
2016-02-16 01:04:40 -08:00
|
|
|
err, exit := router_address.checkValid()
|
2016-02-07 02:54:02 -08:00
|
|
|
if exit {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cost = Integer([]byte{router_address[0]})
|
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-15 00:34:29 -08:00
|
|
|
// Return the Date this RouterAddress expires and any errors encountered
|
|
|
|
// parsing the RouterAddress.
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
|
|
|
func (router_address RouterAddress) Expiration() (date Date, err error) {
|
2016-02-16 01:04:40 -08:00
|
|
|
err, exit := router_address.checkValid()
|
2016-02-07 02:54:02 -08:00
|
|
|
if exit {
|
|
|
|
return
|
|
|
|
}
|
2016-02-16 01:04:40 -08:00
|
|
|
copy(date[:], router_address[1:ROUTER_ADDRESS_MIN_SIZE])
|
2016-02-01 01:56:10 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-15 00:34:29 -08:00
|
|
|
// Return the Transport type for this RouterAddress and any errors encountered
|
|
|
|
// parsing the RouterAddress.
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
|
|
|
func (router_address RouterAddress) TransportStyle() (str String, err error) {
|
2016-02-16 01:04:40 -08:00
|
|
|
err, exit := router_address.checkValid()
|
2016-02-07 02:54:02 -08:00
|
|
|
if exit {
|
|
|
|
return
|
|
|
|
}
|
2016-02-16 01:04:40 -08:00
|
|
|
str, _, err = ReadString(router_address[ROUTER_ADDRESS_MIN_SIZE:])
|
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
|
|
|
//
|
2016-02-15 00:34:29 -08:00
|
|
|
// Return the Mapping containing the options for this RouterAddress and any
|
|
|
|
// errors encountered parsing the RouterAddress.
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
|
|
|
func (router_address RouterAddress) Options() (mapping Mapping, err error) {
|
2016-02-16 01:04:40 -08:00
|
|
|
err, exit := router_address.checkValid()
|
2016-02-07 02:54:02 -08:00
|
|
|
if exit {
|
|
|
|
return
|
|
|
|
}
|
2016-02-16 01:04:40 -08:00
|
|
|
_, remainder, err := ReadString(router_address[ROUTER_ADDRESS_MIN_SIZE:])
|
2016-02-07 02:54:02 -08:00
|
|
|
if len(remainder) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
mapping = Mapping(remainder)
|
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-15 00:34:29 -08:00
|
|
|
// Check if the RouterAddress is empty or if it is too small to contain valid data.
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-12 00:21:27 -08:00
|
|
|
func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
2016-02-07 02:54:02 -08:00
|
|
|
addr_len := len(router_address)
|
|
|
|
exit = false
|
2016-02-12 00:21:27 -08:00
|
|
|
if addr_len == 0 {
|
2016-02-15 00:34:29 -08:00
|
|
|
log.WithFields(log.Fields{
|
2016-06-16 23:04:03 -07:00
|
|
|
"at": "(RouterAddress) checkValid",
|
2016-02-15 00:34:29 -08:00
|
|
|
"reason": "no data",
|
|
|
|
}).Error("invalid router address")
|
2016-02-07 02:54:02 -08:00
|
|
|
err = errors.New("error parsing RouterAddress: no data")
|
|
|
|
exit = true
|
2016-02-16 01:04:40 -08:00
|
|
|
} else if addr_len < ROUTER_ADDRESS_MIN_SIZE {
|
2016-02-15 00:34:29 -08:00
|
|
|
log.WithFields(log.Fields{
|
2016-06-16 23:04:03 -07:00
|
|
|
"at": "(RouterAddress) checkValid",
|
2016-02-16 01:04:40 -08:00
|
|
|
"reason": "data too small (len < ROUTER_ADDRESS_MIN_SIZE)",
|
2016-02-15 00:34:29 -08:00
|
|
|
}).Warn("router address format warning")
|
2016-02-07 02:54:02 -08:00
|
|
|
err = errors.New("warning parsing RouterAddress: data too small")
|
|
|
|
}
|
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
2016-02-15 00:34:29 -08:00
|
|
|
// Given a slice of bytes, read a RouterAddress, returning the remaining bytes and any
|
|
|
|
// errors encountered parsing the RouterAddress.
|
2016-02-07 02:54:02 -08:00
|
|
|
//
|
|
|
|
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
|
|
|
test_address := RouterAddress(data)
|
2016-02-12 00:21:27 -08:00
|
|
|
err, _ = test_address.checkValid()
|
2016-02-07 02:54:02 -08:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2016-02-16 01:04:40 -08:00
|
|
|
router_address = append(router_address, data[:ROUTER_ADDRESS_MIN_SIZE]...)
|
|
|
|
str, remainder, err := ReadString(data[ROUTER_ADDRESS_MIN_SIZE:])
|
2016-02-12 00:21:27 -08:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
router_address = append(router_address, str...)
|
|
|
|
map_size := 0
|
|
|
|
mapping := make([]byte, 0)
|
|
|
|
if len(remainder) >= 2 {
|
|
|
|
map_size = Integer(remainder[:2])
|
|
|
|
mapping = remainder[:map_size+2]
|
|
|
|
router_address = append(router_address, mapping...)
|
|
|
|
}
|
2016-02-16 01:04:40 -08:00
|
|
|
remainder = data[ROUTER_ADDRESS_MIN_SIZE+len(str)+len(mapping):]
|
2016-02-07 02:54:02 -08:00
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|