2022-09-12 08:31:02 +00:00
|
|
|
// Package router_address implements the I2P RouterAddress common data structure
|
2022-07-11 23:41:58 -04:00
|
|
|
package router_address
|
2016-02-01 01:56:10 -08:00
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
import (
|
2024-11-09 00:53:17 -05:00
|
|
|
"encoding/binary"
|
2024-10-03 21:31:54 -04:00
|
|
|
"net"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2024-11-09 00:53:17 -05:00
|
|
|
"time"
|
2022-09-12 08:31:02 +00:00
|
|
|
|
2024-11-21 17:16:48 -05:00
|
|
|
"github.com/go-i2p/logger"
|
2025-02-26 19:22:48 -05:00
|
|
|
"github.com/samber/oops"
|
2024-10-18 13:22:36 -04:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
. "github.com/go-i2p/go-i2p/lib/common/data"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Minimum number of bytes in a valid RouterAddress
|
|
|
|
const (
|
|
|
|
ROUTER_ADDRESS_MIN_SIZE = 9
|
|
|
|
)
|
|
|
|
|
2024-10-23 00:06:06 -04:00
|
|
|
var log = logger.GetGoI2PLogger()
|
2024-10-18 13:22:36 -04:00
|
|
|
|
2016-02-15 00:34:29 -08:00
|
|
|
/*
|
2022-09-12 08:31:02 +00:00
|
|
|
[RouterAddress]
|
|
|
|
Accurate for version 0.9.49
|
|
|
|
|
|
|
|
Description
|
|
|
|
This structure defines the means to contact a router through a transport protocol.
|
|
|
|
|
|
|
|
Contents
|
|
|
|
1 byte Integer defining the relative cost of using the address, where 0 is free and 255 is
|
|
|
|
expensive, followed by the expiration Date after which the address should not be used,
|
|
|
|
of if null, the address never expires. After that comes a String defining the transport
|
|
|
|
protocol this router address uses. Finally there is a Mapping containing all of the
|
|
|
|
transport specific options necessary to establish the connection, such as IP address,
|
|
|
|
port number, email address, URL, etc.
|
|
|
|
|
2016-02-15 00:34:29 -08:00
|
|
|
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
|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
|
|
|
|
*/
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// RouterAddress is the represenation of an I2P RouterAddress.
|
|
|
|
//
|
|
|
|
// https://geti2p.net/spec/common-structures#routeraddress
|
2022-05-09 20:43:24 -04:00
|
|
|
type RouterAddress struct {
|
2024-10-03 21:31:54 -04:00
|
|
|
TransportCost *Integer
|
|
|
|
ExpirationDate *Date
|
|
|
|
TransportType I2PString
|
|
|
|
TransportOptions *Mapping
|
2022-05-09 20:43:24 -04:00
|
|
|
}
|
|
|
|
|
2024-10-03 21:31:54 -04:00
|
|
|
// Network implements net.Addr. It returns the transport type plus 4 or 6
|
|
|
|
func (router_address *RouterAddress) Network() string {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("Getting network for RouterAddress")
|
2024-10-03 21:31:54 -04:00
|
|
|
if router_address.TransportType == nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Warn("TransportType is nil in RouterAddress")
|
2024-10-03 21:31:54 -04:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
str, err := router_address.TransportType.Data()
|
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithError(err).Error("Failed to get TransportType data")
|
2024-10-03 21:31:54 -04:00
|
|
|
return ""
|
|
|
|
}
|
2024-10-18 13:22:36 -04:00
|
|
|
network := string(str) + router_address.IPVersion()
|
|
|
|
log.WithField("network", network).Debug("Retrieved network for RouterAddress")
|
|
|
|
return network
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// IPVersion returns a string "4" for IPv4 or 6 for IPv6
|
|
|
|
func (router_address *RouterAddress) IPVersion() string {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("Getting IP version for RouterAddress")
|
2024-10-03 21:31:54 -04:00
|
|
|
str, err := router_address.CapsString().Data()
|
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithError(err).Error("Failed to get CapsString data")
|
2024-10-03 21:31:54 -04:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
if strings.HasSuffix(str, "6") {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("IP version is IPv6")
|
2024-10-03 21:31:54 -04:00
|
|
|
return "6"
|
|
|
|
}
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("IP version is IPv4")
|
2024-10-03 21:31:54 -04:00
|
|
|
return "4"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address *RouterAddress) UDP() bool {
|
2024-10-18 13:22:36 -04:00
|
|
|
// return strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu")
|
|
|
|
log.Debug("Checking if RouterAddress is UDP")
|
|
|
|
isUDP := strings.HasPrefix(strings.ToLower(router_address.Network()), "ssu")
|
|
|
|
log.WithField("is_udp", isUDP).Debug("Checked if RouterAddress is UDP")
|
|
|
|
return isUDP
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// String implements net.Addr. It returns the IP address, followed by the options
|
|
|
|
func (router_address *RouterAddress) String() string {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("Converting RouterAddress to string")
|
2024-10-03 21:31:54 -04:00
|
|
|
var rv []string
|
|
|
|
rv = append(rv, string(router_address.TransportStyle()))
|
|
|
|
rv = append(rv, string(router_address.HostString()))
|
|
|
|
rv = append(rv, string(router_address.PortString()))
|
|
|
|
rv = append(rv, string(router_address.StaticKeyString()))
|
|
|
|
rv = append(rv, string(router_address.InitializationVectorString()))
|
|
|
|
rv = append(rv, string(router_address.ProtocolVersionString()))
|
|
|
|
if router_address.UDP() {
|
|
|
|
rv = append(rv, string(router_address.IntroducerHashString(0)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerExpirationString(0)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerTagString(0)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerHashString(1)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerExpirationString(1)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerTagString(1)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerHashString(2)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerExpirationString(2)))
|
|
|
|
rv = append(rv, string(router_address.IntroducerTagString(2)))
|
|
|
|
}
|
2024-10-18 13:22:36 -04:00
|
|
|
str := strings.TrimSpace(strings.Join(rv, " "))
|
|
|
|
log.WithField("router_address_string", str).Debug("Converted RouterAddress to string")
|
|
|
|
return str
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var ex_addr net.Addr = &RouterAddress{}
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// Bytes returns the router address as a []byte.
|
2022-08-06 14:16:42 -04:00
|
|
|
func (router_address RouterAddress) Bytes() []byte {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("Converting RouterAddress to bytes")
|
2022-08-06 14:16:42 -04:00
|
|
|
bytes := make([]byte, 0)
|
2024-10-03 21:31:54 -04:00
|
|
|
bytes = append(bytes, router_address.TransportCost.Bytes()...)
|
|
|
|
bytes = append(bytes, router_address.ExpirationDate.Bytes()...)
|
2024-11-15 11:30:11 -05:00
|
|
|
bytes = append(bytes, router_address.TransportType...)
|
2024-10-03 21:31:54 -04:00
|
|
|
bytes = append(bytes, router_address.TransportOptions.Data()...)
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithField("bytes_length", len(bytes)).Debug("Converted RouterAddress to bytes")
|
2022-08-06 14:16:42 -04:00
|
|
|
return bytes
|
|
|
|
}
|
2016-02-01 01:56:10 -08:00
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// Cost returns the cost for this RouterAddress as a Go integer.
|
2022-05-09 20:43:24 -04:00
|
|
|
func (router_address RouterAddress) Cost() int {
|
2024-10-03 21:31:54 -04:00
|
|
|
return router_address.TransportCost.Int()
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// Expiration returns the expiration for this RouterAddress as an I2P Date.
|
2022-05-09 20:43:24 -04:00
|
|
|
func (router_address RouterAddress) Expiration() Date {
|
2024-10-03 21:31:54 -04:00
|
|
|
return *router_address.ExpirationDate
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// TransportStyle returns the transport style for this RouterAddress as an I2PString.
|
2022-05-09 20:43:24 -04:00
|
|
|
func (router_address RouterAddress) TransportStyle() I2PString {
|
2024-10-03 21:31:54 -04:00
|
|
|
return router_address.TransportType
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetOption returns the value of the option specified by the key
|
|
|
|
func (router_address RouterAddress) GetOption(key I2PString) I2PString {
|
|
|
|
return router_address.Options().Values().Get(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) HostString() I2PString {
|
|
|
|
host, _ := ToI2PString("host")
|
|
|
|
return router_address.GetOption(host)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) PortString() I2PString {
|
|
|
|
port, _ := ToI2PString("port")
|
|
|
|
return router_address.GetOption(port)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) CapsString() I2PString {
|
|
|
|
caps, _ := ToI2PString("caps")
|
|
|
|
return router_address.GetOption(caps)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) StaticKeyString() I2PString {
|
|
|
|
sk, _ := ToI2PString("s")
|
|
|
|
return router_address.GetOption(sk)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) InitializationVectorString() I2PString {
|
|
|
|
iv, _ := ToI2PString("i")
|
|
|
|
return router_address.GetOption(iv)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) ProtocolVersionString() I2PString {
|
|
|
|
v, _ := ToI2PString("v")
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) IntroducerHashString(num int) I2PString {
|
|
|
|
if num >= 0 && num <= 2 {
|
|
|
|
val := strconv.Itoa(num)
|
|
|
|
v, _ := ToI2PString("ih" + val)
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
v, _ := ToI2PString("ih0")
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) IntroducerExpirationString(num int) I2PString {
|
|
|
|
if num >= 0 && num <= 2 {
|
|
|
|
val := strconv.Itoa(num)
|
|
|
|
v, _ := ToI2PString("iexp" + val)
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
v, _ := ToI2PString("iexp0")
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) IntroducerTagString(num int) I2PString {
|
|
|
|
if num >= 0 && num <= 2 {
|
|
|
|
val := strconv.Itoa(num)
|
|
|
|
v, _ := ToI2PString("itag" + val)
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
v, _ := ToI2PString("itag0")
|
|
|
|
return router_address.GetOption(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) Host() (net.Addr, error) {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("Getting host from RouterAddress")
|
2024-10-03 21:31:54 -04:00
|
|
|
host := router_address.HostString()
|
|
|
|
hostBytes, err := host.Data()
|
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithError(err).Error("Failed to get host data")
|
2024-10-03 21:31:54 -04:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ip := net.ParseIP(hostBytes)
|
|
|
|
if ip == nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Error("Failed to parse IP address")
|
2025-02-26 19:22:48 -05:00
|
|
|
return nil, oops.Errorf("null host error")
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
2024-10-18 13:22:36 -04:00
|
|
|
// return net.ResolveIPAddr("", ip.String())
|
|
|
|
addr, err := net.ResolveIPAddr("", ip.String())
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to resolve IP address")
|
|
|
|
} else {
|
|
|
|
log.WithField("addr", addr).Debug("Retrieved host from RouterAddress")
|
|
|
|
}
|
|
|
|
return addr, err
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) Port() (string, error) {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.Debug("Getting port from RouterAddress")
|
2024-10-03 21:31:54 -04:00
|
|
|
port := router_address.PortString()
|
|
|
|
portBytes, err := port.Data()
|
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithError(err).Error("Failed to get port data")
|
2024-10-03 21:31:54 -04:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
val, err := strconv.Atoi(portBytes)
|
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithError(err).Error("Failed to convert port to integer")
|
2024-10-03 21:31:54 -04:00
|
|
|
return "", err
|
|
|
|
}
|
2024-10-18 13:22:36 -04:00
|
|
|
// return strconv.Itoa(val), nil
|
|
|
|
portStr := strconv.Itoa(val)
|
|
|
|
log.WithField("port", portStr).Debug("Retrieved port from RouterAddress")
|
|
|
|
return portStr, nil
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) StaticKey() ([32]byte, error) {
|
|
|
|
sk := router_address.StaticKeyString()
|
|
|
|
if len([]byte(sk)) != 32 {
|
2025-02-26 19:22:48 -05:00
|
|
|
return [32]byte{}, oops.Errorf("error: invalid static key")
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
return [32]byte(sk), nil
|
|
|
|
}
|
|
|
|
|
2024-11-20 16:02:14 -05:00
|
|
|
func (router_address RouterAddress) InitializationVector() ([16]byte, error) {
|
2024-10-03 21:31:54 -04:00
|
|
|
iv := router_address.InitializationVectorString()
|
2024-11-20 16:02:14 -05:00
|
|
|
if len([]byte(iv)) != 16 {
|
2025-02-26 19:22:48 -05:00
|
|
|
return [16]byte{}, oops.Errorf("error: invalid IV")
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
2024-11-20 16:02:14 -05:00
|
|
|
return [16]byte(iv), nil
|
2024-10-03 21:31:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (router_address RouterAddress) ProtocolVersion() (string, error) {
|
|
|
|
return router_address.ProtocolVersionString().Data()
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// Options returns the options for this RouterAddress as an I2P Mapping.
|
2022-05-09 20:43:24 -04:00
|
|
|
func (router_address RouterAddress) Options() Mapping {
|
2024-10-03 21:31:54 -04:00
|
|
|
return *router_address.TransportOptions
|
2016-02-01 01:56:10 -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-12 00:21:27 -08:00
|
|
|
func (router_address RouterAddress) checkValid() (err error, exit bool) {
|
2016-02-07 02:54:02 -08:00
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// ReadRouterAddress returns RouterAddress from a []byte.
|
|
|
|
// The remaining bytes after the specified length are also returned.
|
|
|
|
// Returns a list of errors that occurred during parsing.
|
2016-02-07 02:54:02 -08:00
|
|
|
func ReadRouterAddress(data []byte) (router_address RouterAddress, remainder []byte, err error) {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithField("data_length", len(data)).Debug("Reading RouterAddress from data")
|
2024-10-03 21:31:54 -04:00
|
|
|
if len(data) == 0 {
|
|
|
|
log.WithField("at", "(RouterAddress) ReadRouterAddress").Error("error parsing RouterAddress: no data")
|
2025-02-26 19:22:48 -05:00
|
|
|
err = oops.Errorf("error parsing RouterAddress: no data")
|
2022-07-11 10:33:33 -04:00
|
|
|
return
|
|
|
|
}
|
2024-10-03 21:31:54 -04:00
|
|
|
router_address.TransportCost, remainder, err = NewInteger(data, 1)
|
2016-02-07 02:54:02 -08:00
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithFields(logrus.Fields{
|
2022-05-09 20:43:24 -04:00
|
|
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
|
|
|
"reason": "error parsing cost",
|
|
|
|
}).Warn("error parsing RouterAddress")
|
2016-02-07 02:54:02 -08:00
|
|
|
}
|
2024-10-03 21:31:54 -04:00
|
|
|
router_address.ExpirationDate, remainder, err = NewDate(remainder)
|
2016-02-12 00:21:27 -08:00
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithFields(logrus.Fields{
|
2022-05-09 20:43:24 -04:00
|
|
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
|
|
|
"reason": "error parsing expiration",
|
|
|
|
}).Error("error parsing RouterAddress")
|
2016-02-12 00:21:27 -08:00
|
|
|
}
|
2024-10-03 21:31:54 -04:00
|
|
|
router_address.TransportType, remainder, err = ReadI2PString(remainder)
|
2022-05-09 20:43:24 -04:00
|
|
|
if err != nil {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithFields(logrus.Fields{
|
2022-05-09 20:43:24 -04:00
|
|
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
2024-10-03 21:31:54 -04:00
|
|
|
"reason": "error parsing transport_style",
|
2022-05-09 20:43:24 -04:00
|
|
|
}).Error("error parsing RouterAddress")
|
2016-02-12 00:21:27 -08:00
|
|
|
}
|
2024-10-03 21:31:54 -04:00
|
|
|
var errs []error
|
|
|
|
router_address.TransportOptions, remainder, errs = NewMapping(remainder)
|
2022-07-11 23:41:58 -04:00
|
|
|
for _, err := range errs {
|
2024-10-18 13:22:36 -04:00
|
|
|
log.WithFields(logrus.Fields{
|
2022-07-11 23:41:58 -04:00
|
|
|
"at": "(RouterAddress) ReadNewRouterAddress",
|
|
|
|
"reason": "error parsing options",
|
2024-10-03 21:31:54 -04:00
|
|
|
"error": err,
|
|
|
|
}).Error("error parsing RozuterAddress")
|
2022-05-09 20:43:24 -04:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2024-11-09 00:53:17 -05:00
|
|
|
|
|
|
|
// NewRouterAddress creates a new RouterAddress with the provided parameters.
|
|
|
|
// Returns a pointer to RouterAddress.
|
|
|
|
func NewRouterAddress(cost uint8, expiration time.Time, transportType string, options map[string]string) (*RouterAddress, error) {
|
|
|
|
log.Debug("Creating new RouterAddress")
|
|
|
|
|
|
|
|
// Create TransportCost as an Integer (1 byte)
|
|
|
|
transportCost, err := NewIntegerFromInt(int(cost), 1)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to create TransportCost Integer")
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create ExpirationDate as a Date
|
|
|
|
millis := expiration.UnixNano() / int64(time.Millisecond)
|
|
|
|
dateBytes := make([]byte, DATE_SIZE)
|
|
|
|
binary.BigEndian.PutUint64(dateBytes, uint64(millis))
|
|
|
|
expirationDate, _, err := NewDate(dateBytes)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to create ExpirationDate")
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create TransportType as an I2PString
|
|
|
|
transportTypeStr, err := ToI2PString(transportType)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to create TransportType I2PString")
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create TransportOptions as a Mapping
|
|
|
|
transportOptions, err := GoMapToMapping(options)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to create TransportOptions Mapping")
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create RouterAddress
|
|
|
|
ra := &RouterAddress{
|
|
|
|
TransportCost: transportCost,
|
|
|
|
ExpirationDate: expirationDate,
|
|
|
|
TransportType: transportTypeStr,
|
|
|
|
TransportOptions: transportOptions,
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"cost": cost,
|
|
|
|
"expiration": expiration,
|
|
|
|
"transportType": transportType,
|
|
|
|
"options": options,
|
|
|
|
}).Debug("Successfully created new RouterAddress")
|
|
|
|
|
|
|
|
return ra, nil
|
|
|
|
}
|