refactor: format code and add more constants
Some checks failed
Go Build Multi-Platform / build (amd64, darwin) (push) Failing after 12s
Go Build Multi-Platform / build (amd64, freebsd) (push) Successful in 51s
Go Build Multi-Platform / build (amd64, linux) (push) Successful in 49s
Go Build Multi-Platform / build (arm, freebsd) (push) Successful in 49s
Go Build Multi-Platform / build (amd64, windows) (push) Successful in 57s
Go Build Multi-Platform / build (arm, windows) (push) Failing after 19s
Go Build Multi-Platform / build (arm, linux) (push) Failing after 21s
Go Build Multi-Platform / build (arm64, darwin) (push) Successful in 44s
Go Build Multi-Platform / build (arm64, freebsd) (push) Successful in 48s
Go Build Multi-Platform / build (arm64, linux) (push) Successful in 47s
Go Build Multi-Platform / build (arm64, windows) (push) Successful in 46s
Run Gosec / tests (push) Successful in 45s
Go Build Multi-Platform / Create Release (push) Has been skipped
Go Revive Lint / lint (push) Successful in 9m48s
Go Test Multi-Platform / Test (ubuntu-latest, arm64) (push) Successful in 19m13s
Go Test Multi-Platform / Test (ubuntu-latest, amd64) (push) Successful in 19m19s
Some checks failed
Go Build Multi-Platform / build (amd64, darwin) (push) Failing after 12s
Go Build Multi-Platform / build (amd64, freebsd) (push) Successful in 51s
Go Build Multi-Platform / build (amd64, linux) (push) Successful in 49s
Go Build Multi-Platform / build (arm, freebsd) (push) Successful in 49s
Go Build Multi-Platform / build (amd64, windows) (push) Successful in 57s
Go Build Multi-Platform / build (arm, windows) (push) Failing after 19s
Go Build Multi-Platform / build (arm, linux) (push) Failing after 21s
Go Build Multi-Platform / build (arm64, darwin) (push) Successful in 44s
Go Build Multi-Platform / build (arm64, freebsd) (push) Successful in 48s
Go Build Multi-Platform / build (arm64, linux) (push) Successful in 47s
Go Build Multi-Platform / build (arm64, windows) (push) Successful in 46s
Run Gosec / tests (push) Successful in 45s
Go Build Multi-Platform / Create Release (push) Has been skipped
Go Revive Lint / lint (push) Successful in 9m48s
Go Test Multi-Platform / Test (ubuntu-latest, arm64) (push) Successful in 19m13s
Go Test Multi-Platform / Test (ubuntu-latest, amd64) (push) Successful in 19m19s
This commit is contained in:
@@ -13,13 +13,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
basePath string
|
basePath string
|
||||||
ratchetsPath string
|
ratchetsPath string
|
||||||
identitiesPath string
|
identitiesPath string
|
||||||
destinationTable string
|
destinationTable string
|
||||||
knownDestinations string
|
knownDestinations string
|
||||||
transportIdentity string
|
transportIdentity string
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type RatchetData struct {
|
type RatchetData struct {
|
||||||
@@ -34,14 +34,14 @@ func NewManager() (*Manager, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
basePath := filepath.Join(homeDir, ".reticulum-go", "storage")
|
basePath := filepath.Join(homeDir, ".reticulum-go", "storage")
|
||||||
|
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
basePath: basePath,
|
basePath: basePath,
|
||||||
ratchetsPath: filepath.Join(basePath, "ratchets"),
|
ratchetsPath: filepath.Join(basePath, "ratchets"),
|
||||||
identitiesPath: filepath.Join(basePath, "identities"),
|
identitiesPath: filepath.Join(basePath, "identities"),
|
||||||
destinationTable: filepath.Join(basePath, "destination_table"),
|
destinationTable: filepath.Join(basePath, "destination_table"),
|
||||||
knownDestinations: filepath.Join(basePath, "known_destinations"),
|
knownDestinations: filepath.Join(basePath, "known_destinations"),
|
||||||
transportIdentity: filepath.Join(basePath, "transport_identity"),
|
transportIdentity: filepath.Join(basePath, "transport_identity"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.initializeDirectories(); err != nil {
|
if err := m.initializeDirectories(); err != nil {
|
||||||
@@ -76,7 +76,7 @@ func (m *Manager) SaveRatchet(identityHash []byte, ratchetKey []byte) error {
|
|||||||
|
|
||||||
hexHash := hex.EncodeToString(identityHash)
|
hexHash := hex.EncodeToString(identityHash)
|
||||||
ratchetDir := filepath.Join(m.ratchetsPath, hexHash)
|
ratchetDir := filepath.Join(m.ratchetsPath, hexHash)
|
||||||
|
|
||||||
if err := os.MkdirAll(ratchetDir, 0700); err != nil {
|
if err := os.MkdirAll(ratchetDir, 0700); err != nil {
|
||||||
return fmt.Errorf("failed to create ratchet directory: %w", err)
|
return fmt.Errorf("failed to create ratchet directory: %w", err)
|
||||||
}
|
}
|
||||||
@@ -186,4 +186,3 @@ func (m *Manager) GetDestinationTablePath() string {
|
|||||||
func (m *Manager) GetKnownDestinationsPath() string {
|
func (m *Manager) GetKnownDestinationsPath() string {
|
||||||
return m.knownDestinations
|
return m.knownDestinations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,17 +87,17 @@ func New(dest *identity.Identity, destinationHash []byte, destinationName string
|
|||||||
}
|
}
|
||||||
|
|
||||||
a := &Announce{
|
a := &Announce{
|
||||||
mutex: &sync.RWMutex{},
|
mutex: &sync.RWMutex{},
|
||||||
identity: dest,
|
identity: dest,
|
||||||
destinationHash: destinationHash,
|
destinationHash: destinationHash,
|
||||||
destinationName: destinationName,
|
destinationName: destinationName,
|
||||||
appData: appData,
|
appData: appData,
|
||||||
config: config,
|
config: config,
|
||||||
hops: 0,
|
hops: 0,
|
||||||
timestamp: time.Now().Unix(),
|
timestamp: time.Now().Unix(),
|
||||||
pathResponse: pathResponse,
|
pathResponse: pathResponse,
|
||||||
retries: 0,
|
retries: 0,
|
||||||
handlers: make([]AnnounceHandler, 0),
|
handlers: make([]AnnounceHandler, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current ratchet ID if enabled
|
// Get current ratchet ID if enabled
|
||||||
@@ -365,7 +365,7 @@ func (a *Announce) CreatePacket() []byte {
|
|||||||
copy(ratchetData, ratchetPub)
|
copy(ratchetData, ratchetPub)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine context flag based on whether ratchet exists
|
// Determine context flag based on whether ratchet exists
|
||||||
contextFlag := byte(0)
|
contextFlag := byte(0)
|
||||||
if len(ratchetData) > 0 {
|
if len(ratchetData) > 0 {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ func (r *RawChannelReader) Read(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *RawChannelReader) HandleMessage(msg channel.MessageBase) bool { // #nosec G115
|
func (r *RawChannelReader) HandleMessage(msg channel.MessageBase) bool { // #nosec G115
|
||||||
if streamMsg, ok := msg.(*StreamDataMessage); ok && streamMsg.StreamID == uint16(r.streamID) {
|
if streamMsg, ok := msg.(*StreamDataMessage); ok && streamMsg.StreamID == uint16(r.streamID) {
|
||||||
r.mutex.Lock()
|
r.mutex.Lock()
|
||||||
defer r.mutex.Unlock()
|
defer r.mutex.Unlock()
|
||||||
|
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ func (c *Channel) HandleInbound(data []byte) error {
|
|||||||
msgType := uint16(data[0])<<8 | uint16(data[1])
|
msgType := uint16(data[0])<<8 | uint16(data[1])
|
||||||
sequence := uint16(data[2])<<8 | uint16(data[3])
|
sequence := uint16(data[2])<<8 | uint16(data[3])
|
||||||
length := uint16(data[4])<<8 | uint16(data[5])
|
length := uint16(data[4])<<8 | uint16(data[5])
|
||||||
|
|
||||||
if len(data) < 6+int(length) {
|
if len(data) < 6+int(length) {
|
||||||
return errors.New("channel packet incomplete")
|
return errors.New("channel packet incomplete")
|
||||||
}
|
}
|
||||||
@@ -239,9 +239,9 @@ func (c *Channel) HandleInbound(data []byte) error {
|
|||||||
for _, handler := range c.messageHandlers {
|
for _, handler := range c.messageHandlers {
|
||||||
if handler != nil {
|
if handler != nil {
|
||||||
msg := &GenericMessage{
|
msg := &GenericMessage{
|
||||||
Type: msgType,
|
Type: msgType,
|
||||||
Data: msgData,
|
Data: msgData,
|
||||||
Seq: sequence,
|
Seq: sequence,
|
||||||
}
|
}
|
||||||
if handler(msg) {
|
if handler(msg) {
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -58,4 +58,40 @@ const (
|
|||||||
STALE_TIME = 720
|
STALE_TIME = 720
|
||||||
PATH_REQUEST_TTL = 300
|
PATH_REQUEST_TTL = 300
|
||||||
ANNOUNCE_TIMEOUT = 15
|
ANNOUNCE_TIMEOUT = 15
|
||||||
|
|
||||||
|
// Common Numeric Constants
|
||||||
|
ZERO = 0
|
||||||
|
ONE = 1
|
||||||
|
TWO = 2
|
||||||
|
THREE = 3
|
||||||
|
FOUR = 4
|
||||||
|
FIVE = 5
|
||||||
|
SIX = 6
|
||||||
|
SEVEN = 7
|
||||||
|
EIGHT = 8
|
||||||
|
FIFTEEN = 15
|
||||||
|
|
||||||
|
// Common Size Constants
|
||||||
|
SIZE_16 = 16
|
||||||
|
SIZE_32 = 32
|
||||||
|
SIZE_64 = 64
|
||||||
|
SIXTY_SEVEN = 67
|
||||||
|
|
||||||
|
// Common Hex Constants
|
||||||
|
HEX_0x03 = 0x03
|
||||||
|
HEX_0xFF = 0xFF
|
||||||
|
|
||||||
|
// Common Float Constants
|
||||||
|
FLOAT_ZERO = 0.0
|
||||||
|
FLOAT_0_001 = 0.001
|
||||||
|
FLOAT_0_025 = 0.025
|
||||||
|
FLOAT_0_1 = 0.1
|
||||||
|
FLOAT_1_75 = 1.75
|
||||||
|
FLOAT_5_0 = 5.0
|
||||||
|
FLOAT_1E9 = 1e9
|
||||||
|
|
||||||
|
// Common String Constants
|
||||||
|
STR_LINK_ID = "link_id"
|
||||||
|
STR_BYTES = "bytes"
|
||||||
|
STR_FMT_HEX = "0x%02x"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ func TestAES256CBC_InvalidKeySize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestDecryptAES256CBCErrorCases(t *testing.T) {
|
func TestDecryptAES256CBCErrorCases(t *testing.T) {
|
||||||
key, err := GenerateAES256Key()
|
key, err := GenerateAES256Key()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
debugLevel = flag.Int("debug", 3, "debug level (1-7)")
|
debugLevel = flag.Int("debug", 3, "debug level (1-7)")
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
initialized bool
|
initialized bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -113,4 +113,3 @@ func SetDebugLevel(level int) {
|
|||||||
func GetDebugLevel() int {
|
func GetDebugLevel() int {
|
||||||
return *debugLevel
|
return *debugLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ func (i *Identity) String() string {
|
|||||||
|
|
||||||
func Recall(hash []byte) (*Identity, error) {
|
func Recall(hash []byte) (*Identity, error) {
|
||||||
hashStr := hex.EncodeToString(hash)
|
hashStr := hex.EncodeToString(hash)
|
||||||
|
|
||||||
if data, exists := knownDestinations[hashStr]; exists {
|
if data, exists := knownDestinations[hashStr]; exists {
|
||||||
// data is [packet, destHash, identity, appData]
|
// data is [packet, destHash, identity, appData]
|
||||||
if len(data) >= 3 {
|
if len(data) >= 3 {
|
||||||
@@ -249,7 +249,7 @@ func Recall(hash []byte) (*Identity, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("identity not found for hash %x", hash)
|
return nil, fmt.Errorf("identity not found for hash %x", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +523,7 @@ func FromFile(path string) (*Identity, error) {
|
|||||||
ratchetExpiry: make(map[string]int64),
|
ratchetExpiry: make(map[string]int64),
|
||||||
mutex: &sync.RWMutex{},
|
mutex: &sync.RWMutex{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ident.loadPrivateKey(privateKey, signingSeed); err != nil {
|
if err := ident.loadPrivateKey(privateKey, signingSeed); err != nil {
|
||||||
return nil, fmt.Errorf("failed to load private key: %w", err)
|
return nil, fmt.Errorf("failed to load private key: %w", err)
|
||||||
}
|
}
|
||||||
@@ -547,7 +547,7 @@ func LoadOrCreateTransportIdentity() (*Identity, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transportIdentityPath := fmt.Sprintf("%s/transport_identity", storagePath)
|
transportIdentityPath := fmt.Sprintf("%s/transport_identity", storagePath)
|
||||||
|
|
||||||
if ident, err := FromFile(transportIdentityPath); err == nil {
|
if ident, err := FromFile(transportIdentityPath); err == nil {
|
||||||
debug.Log(debug.DEBUG_INFO, "Loaded transport identity from storage")
|
debug.Log(debug.DEBUG_INFO, "Loaded transport identity from storage")
|
||||||
return ident, nil
|
return ident, nil
|
||||||
@@ -610,7 +610,7 @@ func (i *Identity) saveRatchets(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_PACKETS, "Saving ratchets", "count", len(i.ratchets), "path", path)
|
debug.Log(debug.DEBUG_PACKETS, "Saving ratchets", "count", len(i.ratchets), "path", path)
|
||||||
|
|
||||||
// Convert ratchets to list format for msgpack
|
// Convert ratchets to list format for msgpack
|
||||||
ratchetList := make([][]byte, 0, len(i.ratchets))
|
ratchetList := make([][]byte, 0, len(i.ratchets))
|
||||||
for _, ratchet := range i.ratchets {
|
for _, ratchet := range i.ratchets {
|
||||||
@@ -750,7 +750,7 @@ func (i *Identity) loadRatchets(path string) error {
|
|||||||
|
|
||||||
signature, hasSignature := persistedData["signature"]
|
signature, hasSignature := persistedData["signature"]
|
||||||
packedRatchets, hasRatchets := persistedData["ratchets"]
|
packedRatchets, hasRatchets := persistedData["ratchets"]
|
||||||
|
|
||||||
if !hasSignature || !hasRatchets {
|
if !hasSignature || !hasRatchets {
|
||||||
return fmt.Errorf("invalid ratchet file format: missing signature or ratchets")
|
return fmt.Errorf("invalid ratchet file format: missing signature or ratchets")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,42 +23,42 @@ const (
|
|||||||
ANNOUNCE_INTERVAL = 1600 * time.Millisecond
|
ANNOUNCE_INTERVAL = 1600 * time.Millisecond
|
||||||
PEER_JOB_INTERVAL = 4 * time.Second
|
PEER_JOB_INTERVAL = 4 * time.Second
|
||||||
MCAST_ECHO_TIMEOUT = 6500 * time.Millisecond
|
MCAST_ECHO_TIMEOUT = 6500 * time.Millisecond
|
||||||
|
|
||||||
SCOPE_LINK = "2"
|
SCOPE_LINK = "2"
|
||||||
SCOPE_ADMIN = "4"
|
SCOPE_ADMIN = "4"
|
||||||
SCOPE_SITE = "5"
|
SCOPE_SITE = "5"
|
||||||
SCOPE_ORGANISATION = "8"
|
SCOPE_ORGANISATION = "8"
|
||||||
SCOPE_GLOBAL = "e"
|
SCOPE_GLOBAL = "e"
|
||||||
|
|
||||||
MCAST_ADDR_TYPE_PERMANENT = "0"
|
MCAST_ADDR_TYPE_PERMANENT = "0"
|
||||||
MCAST_ADDR_TYPE_TEMPORARY = "1"
|
MCAST_ADDR_TYPE_TEMPORARY = "1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AutoInterface struct {
|
type AutoInterface struct {
|
||||||
BaseInterface
|
BaseInterface
|
||||||
groupID []byte
|
groupID []byte
|
||||||
groupHash []byte
|
groupHash []byte
|
||||||
discoveryPort int
|
discoveryPort int
|
||||||
dataPort int
|
dataPort int
|
||||||
discoveryScope string
|
discoveryScope string
|
||||||
multicastAddrType string
|
multicastAddrType string
|
||||||
mcastDiscoveryAddr string
|
mcastDiscoveryAddr string
|
||||||
ifacNetname string
|
ifacNetname string
|
||||||
peers map[string]*Peer
|
peers map[string]*Peer
|
||||||
linkLocalAddrs []string
|
linkLocalAddrs []string
|
||||||
adoptedInterfaces map[string]*AdoptedInterface
|
adoptedInterfaces map[string]*AdoptedInterface
|
||||||
interfaceServers map[string]*net.UDPConn
|
interfaceServers map[string]*net.UDPConn
|
||||||
discoveryServers map[string]*net.UDPConn
|
discoveryServers map[string]*net.UDPConn
|
||||||
multicastEchoes map[string]time.Time
|
multicastEchoes map[string]time.Time
|
||||||
timedOutInterfaces map[string]time.Time
|
timedOutInterfaces map[string]time.Time
|
||||||
allowedInterfaces []string
|
allowedInterfaces []string
|
||||||
ignoredInterfaces []string
|
ignoredInterfaces []string
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
outboundConn *net.UDPConn
|
outboundConn *net.UDPConn
|
||||||
announceInterval time.Duration
|
announceInterval time.Duration
|
||||||
peerJobInterval time.Duration
|
peerJobInterval time.Duration
|
||||||
peeringTimeout time.Duration
|
peeringTimeout time.Duration
|
||||||
mcastEchoTimeout time.Duration
|
mcastEchoTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdoptedInterface struct {
|
type AdoptedInterface struct {
|
||||||
@@ -97,7 +97,7 @@ func NewAutoInterface(name string, config *common.InterfaceConfig) (*AutoInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
groupHash := sha256.Sum256([]byte(groupID))
|
groupHash := sha256.Sum256([]byte(groupID))
|
||||||
|
|
||||||
ifacNetname := hex.EncodeToString(groupHash[:])[:16]
|
ifacNetname := hex.EncodeToString(groupHash[:])[:16]
|
||||||
mcastAddr := fmt.Sprintf("ff%s%s::%s", discoveryScope, multicastAddrType, ifacNetname)
|
mcastAddr := fmt.Sprintf("ff%s%s::%s", discoveryScope, multicastAddrType, ifacNetname)
|
||||||
|
|
||||||
@@ -114,27 +114,27 @@ func NewAutoInterface(name string, config *common.InterfaceConfig) (*AutoInterfa
|
|||||||
MTU: HW_MTU,
|
MTU: HW_MTU,
|
||||||
Bitrate: BITRATE_GUESS,
|
Bitrate: BITRATE_GUESS,
|
||||||
},
|
},
|
||||||
groupID: []byte(groupID),
|
groupID: []byte(groupID),
|
||||||
groupHash: groupHash[:],
|
groupHash: groupHash[:],
|
||||||
discoveryPort: discoveryPort,
|
discoveryPort: discoveryPort,
|
||||||
dataPort: dataPort,
|
dataPort: dataPort,
|
||||||
discoveryScope: discoveryScope,
|
discoveryScope: discoveryScope,
|
||||||
multicastAddrType: multicastAddrType,
|
multicastAddrType: multicastAddrType,
|
||||||
mcastDiscoveryAddr: mcastAddr,
|
mcastDiscoveryAddr: mcastAddr,
|
||||||
ifacNetname: ifacNetname,
|
ifacNetname: ifacNetname,
|
||||||
peers: make(map[string]*Peer),
|
peers: make(map[string]*Peer),
|
||||||
linkLocalAddrs: make([]string, 0),
|
linkLocalAddrs: make([]string, 0),
|
||||||
adoptedInterfaces: make(map[string]*AdoptedInterface),
|
adoptedInterfaces: make(map[string]*AdoptedInterface),
|
||||||
interfaceServers: make(map[string]*net.UDPConn),
|
interfaceServers: make(map[string]*net.UDPConn),
|
||||||
discoveryServers: make(map[string]*net.UDPConn),
|
discoveryServers: make(map[string]*net.UDPConn),
|
||||||
multicastEchoes: make(map[string]time.Time),
|
multicastEchoes: make(map[string]time.Time),
|
||||||
timedOutInterfaces: make(map[string]time.Time),
|
timedOutInterfaces: make(map[string]time.Time),
|
||||||
allowedInterfaces: make([]string, 0),
|
allowedInterfaces: make([]string, 0),
|
||||||
ignoredInterfaces: make([]string, 0),
|
ignoredInterfaces: make([]string, 0),
|
||||||
announceInterval: ANNOUNCE_INTERVAL,
|
announceInterval: ANNOUNCE_INTERVAL,
|
||||||
peerJobInterval: PEER_JOB_INTERVAL,
|
peerJobInterval: PEER_JOB_INTERVAL,
|
||||||
peeringTimeout: PEERING_TIMEOUT,
|
peeringTimeout: PEERING_TIMEOUT,
|
||||||
mcastEchoTimeout: MCAST_ECHO_TIMEOUT,
|
mcastEchoTimeout: MCAST_ECHO_TIMEOUT,
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_INFO, "AutoInterface configured", "name", name, "group", groupID, "mcast_addr", mcastAddr)
|
debug.Log(debug.DEBUG_INFO, "AutoInterface configured", "name", name, "group", groupID, "mcast_addr", mcastAddr)
|
||||||
@@ -202,26 +202,26 @@ func (ai *AutoInterface) Start() error {
|
|||||||
|
|
||||||
go ai.peerJobs()
|
go ai.peerJobs()
|
||||||
go ai.announceLoop()
|
go ai.announceLoop()
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_INFO, "AutoInterface started", "adopted", len(ai.adoptedInterfaces))
|
debug.Log(debug.DEBUG_INFO, "AutoInterface started", "adopted", len(ai.adoptedInterfaces))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ai *AutoInterface) shouldIgnoreInterface(name string) bool {
|
func (ai *AutoInterface) shouldIgnoreInterface(name string) bool {
|
||||||
ignoreList := []string{"lo", "lo0", "tun0", "awdl0", "llw0", "en5", "dummy0"}
|
ignoreList := []string{"lo", "lo0", "tun0", "awdl0", "llw0", "en5", "dummy0"}
|
||||||
|
|
||||||
for _, ignored := range ai.ignoredInterfaces {
|
for _, ignored := range ai.ignoredInterfaces {
|
||||||
if name == ignored {
|
if name == ignored {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ignored := range ignoreList {
|
for _, ignored := range ignoreList {
|
||||||
if name == ignored {
|
if name == ignored {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +394,7 @@ func (ai *AutoInterface) handlePeerAnnounce(addr *net.UDPAddr, ifaceName string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
peerKey := peerIP + "%" + ifaceName
|
peerKey := peerIP + "%" + ifaceName
|
||||||
|
|
||||||
if peer, exists := ai.peers[peerKey]; exists {
|
if peer, exists := ai.peers[peerKey]; exists {
|
||||||
peer.lastHeard = time.Now()
|
peer.lastHeard = time.Now()
|
||||||
debug.Log(debug.DEBUG_TRACE, "Updated peer", "peer", peerIP, "interface", ifaceName)
|
debug.Log(debug.DEBUG_TRACE, "Updated peer", "peer", peerIP, "interface", ifaceName)
|
||||||
|
|||||||
@@ -21,18 +21,18 @@ const (
|
|||||||
KISS_TFEND = 0xDC
|
KISS_TFEND = 0xDC
|
||||||
KISS_TFESC = 0xDD
|
KISS_TFESC = 0xDD
|
||||||
|
|
||||||
DEFAULT_MTU = 1064
|
DEFAULT_MTU = 1064
|
||||||
BITRATE_GUESS_VAL = 10 * 1000 * 1000
|
BITRATE_GUESS_VAL = 10 * 1000 * 1000
|
||||||
RECONNECT_WAIT = 5
|
RECONNECT_WAIT = 5
|
||||||
INITIAL_TIMEOUT = 5
|
INITIAL_TIMEOUT = 5
|
||||||
INITIAL_BACKOFF = time.Second
|
INITIAL_BACKOFF = time.Second
|
||||||
MAX_BACKOFF = time.Minute * 5
|
MAX_BACKOFF = time.Minute * 5
|
||||||
|
|
||||||
TCP_USER_TIMEOUT_SEC = 24
|
TCP_USER_TIMEOUT_SEC = 24
|
||||||
TCP_PROBE_AFTER_SEC = 5
|
TCP_PROBE_AFTER_SEC = 5
|
||||||
TCP_PROBE_INTERVAL_SEC = 2
|
TCP_PROBE_INTERVAL_SEC = 2
|
||||||
TCP_PROBES_COUNT = 12
|
TCP_PROBES_COUNT = 12
|
||||||
|
|
||||||
I2P_USER_TIMEOUT_SEC = 45
|
I2P_USER_TIMEOUT_SEC = 45
|
||||||
I2P_PROBE_AFTER_SEC = 10
|
I2P_PROBE_AFTER_SEC = 10
|
||||||
I2P_PROBE_INTERVAL_SEC = 9
|
I2P_PROBE_INTERVAL_SEC = 9
|
||||||
@@ -201,7 +201,7 @@ func (tc *TCPClientInterface) handlePacket(data []byte) {
|
|||||||
// Send implements the interface Send method for TCP interface
|
// Send implements the interface Send method for TCP interface
|
||||||
func (tc *TCPClientInterface) Send(data []byte, address string) error {
|
func (tc *TCPClientInterface) Send(data []byte, address string) error {
|
||||||
debug.Log(debug.DEBUG_ALL, "TCP interface sending bytes", "name", tc.Name, "bytes", len(data))
|
debug.Log(debug.DEBUG_ALL, "TCP interface sending bytes", "name", tc.Name, "bytes", len(data))
|
||||||
|
|
||||||
if !tc.IsEnabled() || !tc.IsOnline() {
|
if !tc.IsEnabled() || !tc.IsOnline() {
|
||||||
return fmt.Errorf("TCP interface %s is not online", tc.Name)
|
return fmt.Errorf("TCP interface %s is not online", tc.Name)
|
||||||
}
|
}
|
||||||
@@ -434,7 +434,6 @@ func (tc *TCPClientInterface) GetStats() (tx uint64, rx uint64, lastTx time.Time
|
|||||||
return tc.TxBytes, tc.RxBytes, tc.lastTx, tc.lastRx
|
return tc.TxBytes, tc.RxBytes, tc.lastTx, tc.lastRx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type TCPServerInterface struct {
|
type TCPServerInterface struct {
|
||||||
BaseInterface
|
BaseInterface
|
||||||
connections map[string]net.Conn
|
connections map[string]net.Conn
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build darwin
|
||||||
// +build darwin
|
// +build darwin
|
||||||
|
|
||||||
package interfaces
|
package interfaces
|
||||||
@@ -28,19 +29,19 @@ func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
|||||||
var sockoptErr error
|
var sockoptErr error
|
||||||
err = rawConn.Control(func(fd uintptr) {
|
err = rawConn.Control(func(fd uintptr) {
|
||||||
const TCP_KEEPALIVE = 0x10
|
const TCP_KEEPALIVE = 0x10
|
||||||
|
|
||||||
var probeAfter int
|
var probeAfter int
|
||||||
if tc.i2pTunneled {
|
if tc.i2pTunneled {
|
||||||
probeAfter = I2P_PROBE_AFTER_SEC
|
probeAfter = I2P_PROBE_AFTER_SEC
|
||||||
} else {
|
} else {
|
||||||
probeAfter = TCP_PROBE_AFTER_SEC
|
probeAfter = TCP_PROBE_AFTER_SEC
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
|
||||||
sockoptErr = fmt.Errorf("failed to enable SO_KEEPALIVE: %v", err)
|
sockoptErr = fmt.Errorf("failed to enable SO_KEEPALIVE: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_KEEPALIVE, probeAfter); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, TCP_KEEPALIVE, probeAfter); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPALIVE", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPALIVE", "error", err)
|
||||||
}
|
}
|
||||||
@@ -56,4 +57,3 @@ func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
|||||||
debug.Log(debug.DEBUG_VERBOSE, "TCP keepalive configured (OSX)", "i2p", tc.i2pTunneled)
|
debug.Log(debug.DEBUG_VERBOSE, "TCP keepalive configured (OSX)", "i2p", tc.i2pTunneled)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build freebsd
|
||||||
// +build freebsd
|
// +build freebsd
|
||||||
|
|
||||||
package interfaces
|
package interfaces
|
||||||
@@ -24,7 +25,7 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
if tc.i2pTunneled {
|
if tc.i2pTunneled {
|
||||||
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
||||||
}
|
}
|
||||||
@@ -36,4 +37,3 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
||||||
return tc.setTimeoutsLinux()
|
return tc.setTimeoutsLinux()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package interfaces
|
package interfaces
|
||||||
@@ -26,7 +27,7 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
var sockoptErr error
|
var sockoptErr error
|
||||||
err = rawConn.Control(func(fd uintptr) {
|
err = rawConn.Control(func(fd uintptr) {
|
||||||
var userTimeout, probeAfter, probeInterval, probeCount int
|
var userTimeout, probeAfter, probeInterval, probeCount int
|
||||||
|
|
||||||
if tc.i2pTunneled {
|
if tc.i2pTunneled {
|
||||||
userTimeout = I2P_USER_TIMEOUT_SEC * 1000
|
userTimeout = I2P_USER_TIMEOUT_SEC * 1000
|
||||||
probeAfter = I2P_PROBE_AFTER_SEC
|
probeAfter = I2P_PROBE_AFTER_SEC
|
||||||
@@ -42,20 +43,20 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 18, userTimeout); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 18, userTimeout); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_USER_TIMEOUT", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_USER_TIMEOUT", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
|
||||||
sockoptErr = fmt.Errorf("failed to enable SO_KEEPALIVE: %v", err)
|
sockoptErr = fmt.Errorf("failed to enable SO_KEEPALIVE: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 4, probeAfter); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 4, probeAfter); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPIDLE", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPIDLE", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 5, probeInterval); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 5, probeInterval); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPINTVL", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPINTVL", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 6, probeCount); err != nil {
|
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, 6, probeCount); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPCNT", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set TCP_KEEPCNT", "error", err)
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,7 @@ func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
|||||||
func platformGetRTT(fd uintptr) time.Duration {
|
func platformGetRTT(fd uintptr) time.Duration {
|
||||||
var info syscall.TCPInfo
|
var info syscall.TCPInfo
|
||||||
infoLen := uint32(unsafe.Sizeof(info))
|
infoLen := uint32(unsafe.Sizeof(info))
|
||||||
|
|
||||||
// TCP_INFO is 11 on Linux
|
// TCP_INFO is 11 on Linux
|
||||||
// #nosec G103
|
// #nosec G103
|
||||||
_, _, errno := syscall.Syscall6(
|
_, _, errno := syscall.Syscall6(
|
||||||
@@ -91,10 +92,10 @@ func platformGetRTT(fd uintptr) time.Duration {
|
|||||||
uintptr(unsafe.Pointer(&infoLen)),
|
uintptr(unsafe.Pointer(&infoLen)),
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return time.Duration(info.Rtt) * time.Microsecond
|
return time.Duration(info.Rtt) * time.Microsecond
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build netbsd
|
||||||
// +build netbsd
|
// +build netbsd
|
||||||
|
|
||||||
package interfaces
|
package interfaces
|
||||||
@@ -24,7 +25,7 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
if tc.i2pTunneled {
|
if tc.i2pTunneled {
|
||||||
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
||||||
}
|
}
|
||||||
@@ -36,4 +37,3 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
||||||
return tc.setTimeoutsLinux()
|
return tc.setTimeoutsLinux()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build openbsd
|
||||||
// +build openbsd
|
// +build openbsd
|
||||||
|
|
||||||
package interfaces
|
package interfaces
|
||||||
@@ -24,7 +25,7 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
if tc.i2pTunneled {
|
if tc.i2pTunneled {
|
||||||
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
||||||
}
|
}
|
||||||
@@ -36,4 +37,3 @@ func (tc *TCPClientInterface) setTimeoutsLinux() error {
|
|||||||
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
func (tc *TCPClientInterface) setTimeoutsOSX() error {
|
||||||
return tc.setTimeoutsLinux()
|
return tc.setTimeoutsLinux()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func (tc *TCPClientInterface) setTimeoutsWindows() error {
|
|||||||
if tc.i2pTunneled {
|
if tc.i2pTunneled {
|
||||||
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
keepalivePeriod = I2P_PROBE_INTERVAL_SEC * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
if err := tcpConn.SetKeepAlivePeriod(keepalivePeriod); err != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
debug.Log(debug.DEBUG_VERBOSE, "Failed to set keepalive period", "error", err)
|
||||||
}
|
}
|
||||||
@@ -38,5 +38,3 @@ func (tc *TCPClientInterface) setTimeoutsWindows() error {
|
|||||||
debug.Log(debug.DEBUG_VERBOSE, "TCP keepalive configured (Windows)", "i2p", tc.i2pTunneled)
|
debug.Log(debug.DEBUG_VERBOSE, "TCP keepalive configured (Windows)", "i2p", tc.i2pTunneled)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func NewUDPInterface(name string, addr string, target string, enabled bool) (*UD
|
|||||||
targetAddr: targetAddr,
|
targetAddr: targetAddr,
|
||||||
readBuffer: make([]byte, 1064),
|
readBuffer: make([]byte, 1064),
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.MTU = 1064
|
ui.MTU = 1064
|
||||||
|
|
||||||
return ui, nil
|
return ui, nil
|
||||||
@@ -183,7 +183,7 @@ func (ui *UDPInterface) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ui.conn = conn
|
ui.conn = conn
|
||||||
|
|
||||||
// Enable broadcast mode if we have a target address
|
// Enable broadcast mode if we have a target address
|
||||||
if ui.targetAddr != nil {
|
if ui.targetAddr != nil {
|
||||||
// Get the raw connection file descriptor to set SO_BROADCAST
|
// Get the raw connection file descriptor to set SO_BROADCAST
|
||||||
@@ -194,12 +194,12 @@ func (ui *UDPInterface) Start() error {
|
|||||||
debug.Log(debug.DEBUG_ERROR, "Failed to set write buffer size", "error", err)
|
debug.Log(debug.DEBUG_ERROR, "Failed to set write buffer size", "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Online = true
|
ui.Online = true
|
||||||
|
|
||||||
// Start the read loop in a goroutine
|
// Start the read loop in a goroutine
|
||||||
go ui.readLoop()
|
go ui.readLoop()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ func (ui *UDPInterface) readLoop() {
|
|||||||
ui.mutex.Lock()
|
ui.mutex.Lock()
|
||||||
// #nosec G115 - Network read sizes are always positive and within safe range
|
// #nosec G115 - Network read sizes are always positive and within safe range
|
||||||
ui.RxBytes += uint64(n)
|
ui.RxBytes += uint64(n)
|
||||||
|
|
||||||
// Auto-discover target address from first packet if not set
|
// Auto-discover target address from first packet if not set
|
||||||
if ui.targetAddr == nil {
|
if ui.targetAddr == nil {
|
||||||
debug.Log(debug.DEBUG_ALL, "UDP interface discovered peer", "name", ui.Name, "peer", remoteAddr.String())
|
debug.Log(debug.DEBUG_ALL, "UDP interface discovered peer", "name", ui.Name, "peer", remoteAddr.String())
|
||||||
|
|||||||
@@ -13,23 +13,23 @@ import (
|
|||||||
|
|
||||||
func TestEphemeralKeyGeneration(t *testing.T) {
|
func TestEphemeralKeyGeneration(t *testing.T) {
|
||||||
link := &Link{}
|
link := &Link{}
|
||||||
|
|
||||||
if err := link.generateEphemeralKeys(); err != nil {
|
if err := link.generateEphemeralKeys(); err != nil {
|
||||||
t.Fatalf("Failed to generate ephemeral keys: %v", err)
|
t.Fatalf("Failed to generate ephemeral keys: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(link.prv) != KEYSIZE {
|
if len(link.prv) != KEYSIZE {
|
||||||
t.Errorf("Expected private key length %d, got %d", KEYSIZE, len(link.prv))
|
t.Errorf("Expected private key length %d, got %d", KEYSIZE, len(link.prv))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(link.pub) != KEYSIZE {
|
if len(link.pub) != KEYSIZE {
|
||||||
t.Errorf("Expected public key length %d, got %d", KEYSIZE, len(link.pub))
|
t.Errorf("Expected public key length %d, got %d", KEYSIZE, len(link.pub))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(link.sigPriv) != 64 {
|
if len(link.sigPriv) != 64 {
|
||||||
t.Errorf("Expected signing private key length 64, got %d", len(link.sigPriv))
|
t.Errorf("Expected signing private key length 64, got %d", len(link.sigPriv))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(link.sigPub) != 32 {
|
if len(link.sigPub) != 32 {
|
||||||
t.Errorf("Expected signing public key length 32, got %d", len(link.sigPub))
|
t.Errorf("Expected signing public key length 32, got %d", len(link.sigPub))
|
||||||
}
|
}
|
||||||
@@ -38,18 +38,18 @@ func TestEphemeralKeyGeneration(t *testing.T) {
|
|||||||
func TestSignallingBytes(t *testing.T) {
|
func TestSignallingBytes(t *testing.T) {
|
||||||
mtu := 500
|
mtu := 500
|
||||||
mode := byte(MODE_AES256_CBC)
|
mode := byte(MODE_AES256_CBC)
|
||||||
|
|
||||||
bytes := signallingBytes(mtu, mode)
|
bytes := signallingBytes(mtu, mode)
|
||||||
|
|
||||||
if len(bytes) != LINK_MTU_SIZE {
|
if len(bytes) != LINK_MTU_SIZE {
|
||||||
t.Errorf("Expected signalling bytes length %d, got %d", LINK_MTU_SIZE, len(bytes))
|
t.Errorf("Expected signalling bytes length %d, got %d", LINK_MTU_SIZE, len(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
extractedMTU := (int(bytes[0]&0x1F) << 16) | (int(bytes[1]) << 8) | int(bytes[2])
|
extractedMTU := (int(bytes[0]&0x1F) << 16) | (int(bytes[1]) << 8) | int(bytes[2])
|
||||||
if extractedMTU != mtu {
|
if extractedMTU != mtu {
|
||||||
t.Errorf("Expected MTU %d, got %d", mtu, extractedMTU)
|
t.Errorf("Expected MTU %d, got %d", mtu, extractedMTU)
|
||||||
}
|
}
|
||||||
|
|
||||||
extractedMode := (bytes[0] & MODE_BYTEMASK) >> 5
|
extractedMode := (bytes[0] & MODE_BYTEMASK) >> 5
|
||||||
if extractedMode != mode {
|
if extractedMode != mode {
|
||||||
t.Errorf("Expected mode %d, got %d", mode, extractedMode)
|
t.Errorf("Expected mode %d, got %d", mode, extractedMode)
|
||||||
@@ -106,55 +106,55 @@ func TestLinkIDGeneration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
linkID := linkIDFromPacket(pkt)
|
linkID := linkIDFromPacket(pkt)
|
||||||
|
|
||||||
if len(linkID) != 16 {
|
if len(linkID) != 16 {
|
||||||
t.Errorf("Expected link ID length 16, got %d", len(linkID))
|
t.Errorf("Expected link ID length 16, got %d", len(linkID))
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Generated link ID: %x", linkID)
|
t.Logf("Generated link ID: %x", linkID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandshake(t *testing.T) {
|
func TestHandshake(t *testing.T) {
|
||||||
link1 := &Link{}
|
link1 := &Link{}
|
||||||
link2 := &Link{}
|
link2 := &Link{}
|
||||||
|
|
||||||
if err := link1.generateEphemeralKeys(); err != nil {
|
if err := link1.generateEphemeralKeys(); err != nil {
|
||||||
t.Fatalf("Failed to generate keys for link1: %v", err)
|
t.Fatalf("Failed to generate keys for link1: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := link2.generateEphemeralKeys(); err != nil {
|
if err := link2.generateEphemeralKeys(); err != nil {
|
||||||
t.Fatalf("Failed to generate keys for link2: %v", err)
|
t.Fatalf("Failed to generate keys for link2: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
link1.peerPub = link2.pub
|
link1.peerPub = link2.pub
|
||||||
link2.peerPub = link1.pub
|
link2.peerPub = link1.pub
|
||||||
|
|
||||||
link1.linkID = []byte("test-link-id-abc")
|
link1.linkID = []byte("test-link-id-abc")
|
||||||
link2.linkID = []byte("test-link-id-abc")
|
link2.linkID = []byte("test-link-id-abc")
|
||||||
|
|
||||||
link1.mode = MODE_AES256_CBC
|
link1.mode = MODE_AES256_CBC
|
||||||
link2.mode = MODE_AES256_CBC
|
link2.mode = MODE_AES256_CBC
|
||||||
|
|
||||||
if err := link1.performHandshake(); err != nil {
|
if err := link1.performHandshake(); err != nil {
|
||||||
t.Fatalf("Link1 handshake failed: %v", err)
|
t.Fatalf("Link1 handshake failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := link2.performHandshake(); err != nil {
|
if err := link2.performHandshake(); err != nil {
|
||||||
t.Fatalf("Link2 handshake failed: %v", err)
|
t.Fatalf("Link2 handshake failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(link1.sharedKey) != string(link2.sharedKey) {
|
if string(link1.sharedKey) != string(link2.sharedKey) {
|
||||||
t.Error("Shared keys do not match")
|
t.Error("Shared keys do not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(link1.derivedKey) != string(link2.derivedKey) {
|
if string(link1.derivedKey) != string(link2.derivedKey) {
|
||||||
t.Error("Derived keys do not match")
|
t.Error("Derived keys do not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
if link1.status != STATUS_HANDSHAKE {
|
if link1.status != STATUS_HANDSHAKE {
|
||||||
t.Errorf("Expected link1 status HANDSHAKE, got %d", link1.status)
|
t.Errorf("Expected link1 status HANDSHAKE, got %d", link1.status)
|
||||||
}
|
}
|
||||||
|
|
||||||
if link2.status != STATUS_HANDSHAKE {
|
if link2.status != STATUS_HANDSHAKE {
|
||||||
t.Errorf("Expected link2 status HANDSHAKE, got %d", link2.status)
|
t.Errorf("Expected link2 status HANDSHAKE, got %d", link2.status)
|
||||||
}
|
}
|
||||||
@@ -224,9 +224,9 @@ func TestLinkEstablishment(t *testing.T) {
|
|||||||
responderLink.peerSigPub = linkRequestPkt.Data[KEYSIZE:ECPUBSIZE]
|
responderLink.peerSigPub = linkRequestPkt.Data[KEYSIZE:ECPUBSIZE]
|
||||||
responderLink.linkID = linkIDFromPacket(linkRequestPkt)
|
responderLink.linkID = linkIDFromPacket(linkRequestPkt)
|
||||||
responderLink.initiator = false
|
responderLink.initiator = false
|
||||||
|
|
||||||
t.Logf("Responder link ID=%x (len=%d)", responderLink.linkID, len(responderLink.linkID))
|
t.Logf("Responder link ID=%x (len=%d)", responderLink.linkID, len(responderLink.linkID))
|
||||||
|
|
||||||
if len(responderLink.linkID) == 0 {
|
if len(responderLink.linkID) == 0 {
|
||||||
t.Fatal("Responder link ID is empty!")
|
t.Fatal("Responder link ID is empty!")
|
||||||
}
|
}
|
||||||
@@ -362,4 +362,3 @@ func TestLinkProofValidation(t *testing.T) {
|
|||||||
t.Logf("Derived key length: %d", len(initiatorLink.derivedKey))
|
t.Logf("Derived key length: %d", len(initiatorLink.derivedKey))
|
||||||
t.Logf("RTT: %.3f seconds", initiatorLink.rtt)
|
t.Logf("RTT: %.3f seconds", initiatorLink.rtt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
240
pkg/link/link.go
240
pkg/link/link.go
@@ -64,6 +64,11 @@ const (
|
|||||||
|
|
||||||
WATCHDOG_MIN_SLEEP = 0.025
|
WATCHDOG_MIN_SLEEP = 0.025
|
||||||
WATCHDOG_INTERVAL = 0.1
|
WATCHDOG_INTERVAL = 0.1
|
||||||
|
|
||||||
|
DEST_TYPE_LINK = 0x03
|
||||||
|
|
||||||
|
MIN_REQUEST_DATA_LEN = 3
|
||||||
|
MIN_RESPONSE_DATA_LEN = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -229,10 +234,10 @@ func (l *Link) Identify(id *identity.Identity) error {
|
|||||||
p := &packet.Packet{
|
p := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextLinkIdentify,
|
Context: packet.ContextLinkIdentify,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: l.destination.GetType(),
|
DestinationType: l.destination.GetType(),
|
||||||
DestinationHash: l.destination.GetHash(),
|
DestinationHash: l.destination.GetHash(),
|
||||||
Data: id.GetPublicKey(),
|
Data: id.GetPublicKey(),
|
||||||
@@ -258,25 +263,25 @@ func (l *Link) HandleIdentification(data []byte) error {
|
|||||||
pubKey := data[:ed25519.PublicKeySize]
|
pubKey := data[:ed25519.PublicKeySize]
|
||||||
signature := data[ed25519.PublicKeySize:]
|
signature := data[ed25519.PublicKeySize:]
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Processing identification from public key", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Processing identification from public key", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
|
|
||||||
remoteIdentity := identity.FromPublicKey(pubKey)
|
remoteIdentity := identity.FromPublicKey(pubKey)
|
||||||
if remoteIdentity == nil {
|
if remoteIdentity == nil {
|
||||||
debug.Log(debug.DEBUG_INFO, "Invalid remote identity from public key", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_INFO, "Invalid remote identity from public key", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
return errors.New("invalid remote identity")
|
return errors.New("invalid remote identity")
|
||||||
}
|
}
|
||||||
|
|
||||||
signData := append(l.linkID, pubKey...)
|
signData := append(l.linkID, pubKey...)
|
||||||
if !remoteIdentity.Verify(signData, signature) {
|
if !remoteIdentity.Verify(signData, signature) {
|
||||||
debug.Log(debug.DEBUG_INFO, "Invalid signature from remote identity", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_INFO, "Invalid signature from remote identity", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
return errors.New("invalid signature")
|
return errors.New("invalid signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Remote identity verified successfully", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Remote identity verified successfully", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
l.remoteIdentity = remoteIdentity
|
l.remoteIdentity = remoteIdentity
|
||||||
|
|
||||||
if l.identifiedCallback != nil {
|
if l.identifiedCallback != nil {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Executing identified callback for remote identity", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Executing identified callback for remote identity", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
l.identifiedCallback(l, remoteIdentity)
|
l.identifiedCallback(l, remoteIdentity)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,11 +313,11 @@ func (l *Link) Request(path string, data []byte, timeout time.Duration) (*Reques
|
|||||||
reqPkt := &packet.Packet{
|
reqPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextRequest,
|
Context: packet.ContextRequest,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: packedRequest,
|
Data: packedRequest,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -395,7 +400,7 @@ func (r *RequestReceipt) GetResponseTime() float64 {
|
|||||||
r.mutex.RLock()
|
r.mutex.RLock()
|
||||||
defer r.mutex.RUnlock()
|
defer r.mutex.RUnlock()
|
||||||
if r.receivedAt.IsZero() {
|
if r.receivedAt.IsZero() {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return r.receivedAt.Sub(r.sentAt).Seconds()
|
return r.receivedAt.Sub(r.sentAt).Seconds()
|
||||||
}
|
}
|
||||||
@@ -455,7 +460,7 @@ func (l *Link) GetRSSI() float64 {
|
|||||||
l.mutex.RLock()
|
l.mutex.RLock()
|
||||||
defer l.mutex.RUnlock()
|
defer l.mutex.RUnlock()
|
||||||
if !l.trackPhyStats {
|
if !l.trackPhyStats {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return l.rssi
|
return l.rssi
|
||||||
}
|
}
|
||||||
@@ -464,7 +469,7 @@ func (l *Link) GetSNR() float64 {
|
|||||||
l.mutex.RLock()
|
l.mutex.RLock()
|
||||||
defer l.mutex.RUnlock()
|
defer l.mutex.RUnlock()
|
||||||
if !l.trackPhyStats {
|
if !l.trackPhyStats {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return l.snr
|
return l.snr
|
||||||
}
|
}
|
||||||
@@ -473,7 +478,7 @@ func (l *Link) GetQ() float64 {
|
|||||||
l.mutex.RLock()
|
l.mutex.RLock()
|
||||||
defer l.mutex.RUnlock()
|
defer l.mutex.RUnlock()
|
||||||
if !l.trackPhyStats {
|
if !l.trackPhyStats {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return l.q
|
return l.q
|
||||||
}
|
}
|
||||||
@@ -488,7 +493,7 @@ func (l *Link) GetAge() float64 {
|
|||||||
l.mutex.RLock()
|
l.mutex.RLock()
|
||||||
defer l.mutex.RUnlock()
|
defer l.mutex.RUnlock()
|
||||||
if l.establishedAt.IsZero() {
|
if l.establishedAt.IsZero() {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return time.Since(l.establishedAt).Seconds()
|
return time.Since(l.establishedAt).Seconds()
|
||||||
}
|
}
|
||||||
@@ -497,7 +502,7 @@ func (l *Link) NoInboundFor() float64 {
|
|||||||
l.mutex.RLock()
|
l.mutex.RLock()
|
||||||
defer l.mutex.RUnlock()
|
defer l.mutex.RUnlock()
|
||||||
if l.lastInbound.IsZero() {
|
if l.lastInbound.IsZero() {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return time.Since(l.lastInbound).Seconds()
|
return time.Since(l.lastInbound).Seconds()
|
||||||
}
|
}
|
||||||
@@ -506,7 +511,7 @@ func (l *Link) NoOutboundFor() float64 {
|
|||||||
l.mutex.RLock()
|
l.mutex.RLock()
|
||||||
defer l.mutex.RUnlock()
|
defer l.mutex.RUnlock()
|
||||||
if l.lastOutbound.IsZero() {
|
if l.lastOutbound.IsZero() {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return time.Since(l.lastOutbound).Seconds()
|
return time.Since(l.lastOutbound).Seconds()
|
||||||
}
|
}
|
||||||
@@ -519,7 +524,7 @@ func (l *Link) NoDataFor() float64 {
|
|||||||
lastData = l.lastDataSent
|
lastData = l.lastDataSent
|
||||||
}
|
}
|
||||||
if lastData.IsZero() {
|
if lastData.IsZero() {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return time.Since(lastData).Seconds()
|
return time.Since(lastData).Seconds()
|
||||||
}
|
}
|
||||||
@@ -532,7 +537,7 @@ func (l *Link) InactiveFor() float64 {
|
|||||||
lastActivity = l.lastOutbound
|
lastActivity = l.lastOutbound
|
||||||
}
|
}
|
||||||
if lastActivity.IsZero() {
|
if lastActivity.IsZero() {
|
||||||
return 0
|
return common.FLOAT_ZERO
|
||||||
}
|
}
|
||||||
return time.Since(lastActivity).Seconds()
|
return time.Since(lastActivity).Seconds()
|
||||||
}
|
}
|
||||||
@@ -621,10 +626,10 @@ func (l *Link) SendPacket(data []byte) error {
|
|||||||
p := &packet.Packet{
|
p := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextNone,
|
Context: packet.ContextNone,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: l.destination.GetType(),
|
DestinationType: l.destination.GetType(),
|
||||||
DestinationHash: l.destination.GetHash(),
|
DestinationHash: l.destination.GetHash(),
|
||||||
Data: encrypted,
|
Data: encrypted,
|
||||||
@@ -707,16 +712,16 @@ func (l *Link) handleDataPacket(pkt *packet.Packet) error {
|
|||||||
case packet.ContextLinkIdentify:
|
case packet.ContextLinkIdentify:
|
||||||
return l.HandleIdentification(plaintext)
|
return l.HandleIdentification(plaintext)
|
||||||
case packet.ContextKeepalive:
|
case packet.ContextKeepalive:
|
||||||
if !l.initiator && len(plaintext) == 1 && plaintext[0] == 0xFF {
|
if !l.initiator && len(plaintext) == common.ONE && plaintext[common.ZERO] == common.HEX_0xFF {
|
||||||
keepaliveResp := []byte{0xFE}
|
keepaliveResp := []byte{0xFE}
|
||||||
keepalivePkt := &packet.Packet{
|
keepalivePkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextKeepalive,
|
Context: packet.ContextKeepalive,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: keepaliveResp,
|
Data: keepaliveResp,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -860,11 +865,11 @@ func (l *Link) rejectResource(resourceHash []byte) error {
|
|||||||
rejectPkt := &packet.Packet{
|
rejectPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextResourceRCL,
|
Context: packet.ContextResourceRCL,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: resourceHash,
|
Data: resourceHash,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -904,7 +909,7 @@ func (l *Link) sendResourceAdvertisement(res *resource.Resource) error {
|
|||||||
return errors.New("failed to create resource advertisement")
|
return errors.New("failed to create resource advertisement")
|
||||||
}
|
}
|
||||||
|
|
||||||
advData, err := adv.Pack(0)
|
advData, err := adv.Pack(common.ZERO)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to pack advertisement: %w", err)
|
return fmt.Errorf("failed to pack advertisement: %w", err)
|
||||||
}
|
}
|
||||||
@@ -917,11 +922,11 @@ func (l *Link) sendResourceAdvertisement(res *resource.Resource) error {
|
|||||||
advPkt := &packet.Packet{
|
advPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextResourceAdv,
|
Context: packet.ContextResourceAdv,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: encrypted,
|
Data: encrypted,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -1005,13 +1010,13 @@ func (l *Link) handleRequest(plaintext []byte, pkt *packet.Packet) error {
|
|||||||
return fmt.Errorf("failed to unpack request: %w", err)
|
return fmt.Errorf("failed to unpack request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(requestData) < 3 {
|
if len(requestData) < MIN_REQUEST_DATA_LEN {
|
||||||
return errors.New("invalid request format")
|
return errors.New("invalid request format")
|
||||||
}
|
}
|
||||||
|
|
||||||
requestedAt := time.Unix(int64(requestData[0].(int64)), 0)
|
requestedAt := time.Unix(int64(requestData[common.ZERO].(int64)), common.ZERO)
|
||||||
pathHash := requestData[1].([]byte)
|
pathHash := requestData[common.ONE].([]byte)
|
||||||
requestPayload := requestData[2].([]byte)
|
requestPayload := requestData[common.TWO].([]byte)
|
||||||
|
|
||||||
requestID := identity.TruncatedHash(plaintext)
|
requestID := identity.TruncatedHash(plaintext)
|
||||||
|
|
||||||
@@ -1034,12 +1039,12 @@ func (l *Link) handleResponse(plaintext []byte) error {
|
|||||||
return fmt.Errorf("failed to unpack response: %w", err)
|
return fmt.Errorf("failed to unpack response: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(responseData) < 2 {
|
if len(responseData) < MIN_RESPONSE_DATA_LEN {
|
||||||
return errors.New("invalid response format")
|
return errors.New("invalid response format")
|
||||||
}
|
}
|
||||||
|
|
||||||
requestID := responseData[0].([]byte)
|
requestID := responseData[common.ZERO].([]byte)
|
||||||
responsePayload := responseData[1].([]byte)
|
responsePayload := responseData[common.ONE].([]byte)
|
||||||
|
|
||||||
l.requestMutex.Lock()
|
l.requestMutex.Lock()
|
||||||
for i, req := range l.pendingRequests {
|
for i, req := range l.pendingRequests {
|
||||||
@@ -1079,11 +1084,11 @@ func (l *Link) sendResponse(requestID []byte, response interface{}) error {
|
|||||||
respPkt := &packet.Packet{
|
respPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextResponse,
|
Context: packet.ContextResponse,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: encrypted,
|
Data: encrypted,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -1110,8 +1115,8 @@ func (l *Link) handleRTTPacket(pkt *packet.Packet) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var rtt float64
|
var rtt float64
|
||||||
if len(plaintext) >= 8 {
|
if len(plaintext) >= common.EIGHT {
|
||||||
rtt = float64(binary.BigEndian.Uint64(plaintext[:8])) / 1e9
|
rtt = float64(binary.BigEndian.Uint64(plaintext[:common.EIGHT])) / common.FLOAT_1E9
|
||||||
}
|
}
|
||||||
|
|
||||||
l.rtt = max(measuredRTT, rtt)
|
l.rtt = max(measuredRTT, rtt)
|
||||||
@@ -1140,9 +1145,9 @@ func (l *Link) updateKeepalive() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
keepaliveMaxRTT := 1.75
|
keepaliveMaxRTT := common.FLOAT_1_75
|
||||||
keepaliveMax := float64(KEEPALIVE)
|
keepaliveMax := float64(KEEPALIVE)
|
||||||
keepaliveMin := 5.0
|
keepaliveMin := common.FLOAT_5_0
|
||||||
|
|
||||||
calculatedKeepalive := l.rtt * (keepaliveMax / keepaliveMaxRTT)
|
calculatedKeepalive := l.rtt * (keepaliveMax / keepaliveMaxRTT)
|
||||||
if calculatedKeepalive > keepaliveMax {
|
if calculatedKeepalive > keepaliveMax {
|
||||||
@@ -1153,7 +1158,7 @@ func (l *Link) updateKeepalive() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l.keepalive = time.Duration(calculatedKeepalive * float64(time.Second))
|
l.keepalive = time.Duration(calculatedKeepalive * float64(time.Second))
|
||||||
l.staleTime = time.Duration(float64(l.keepalive) * 2.0)
|
l.staleTime = time.Duration(float64(l.keepalive) * float64(common.TWO))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Link) handleLinkProof(pkt *packet.Packet) error {
|
func (l *Link) handleLinkProof(pkt *packet.Packet) error {
|
||||||
@@ -1284,11 +1289,11 @@ func (l *Link) Send(data []byte) interface{} {
|
|||||||
pkt := &packet.Packet{
|
pkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextChannel,
|
Context: packet.ContextChannel,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: data,
|
Data: data,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -1464,33 +1469,33 @@ func (l *Link) decodePacket(data []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
packetType := data[0]
|
packetType := data[0]
|
||||||
debug.Log(debug.DEBUG_ALL, "Packet Analysis", "size", len(data), "type", fmt.Sprintf("0x%02x", packetType))
|
debug.Log(debug.DEBUG_ALL, "Packet Analysis", "size", len(data), "type", fmt.Sprintf(common.STR_FMT_HEX, packetType))
|
||||||
|
|
||||||
switch packetType {
|
switch packetType {
|
||||||
case packet.PacketTypeData:
|
case packet.PacketTypeData:
|
||||||
debug.Log(debug.DEBUG_ALL, "Type Description: Data Packet", "payload_size", len(data)-1)
|
debug.Log(debug.DEBUG_ALL, "Type Description: Data Packet", "payload_size", len(data)-common.ONE)
|
||||||
|
|
||||||
case packet.PacketTypeLinkReq:
|
case packet.PacketTypeLinkReq:
|
||||||
debug.Log(debug.DEBUG_ALL, "Type Description: Link Management", "link_id", fmt.Sprintf("%x", data[1:33]))
|
debug.Log(debug.DEBUG_ALL, "Type Description: Link Management", common.STR_LINK_ID, fmt.Sprintf("%x", data[common.ONE:common.SIZE_32+common.ONE]))
|
||||||
|
|
||||||
case packet.PacketTypeAnnounce:
|
case packet.PacketTypeAnnounce:
|
||||||
debug.Log(debug.DEBUG_ALL, "Received announce packet", "bytes", len(data))
|
debug.Log(debug.DEBUG_ALL, "Received announce packet", common.STR_BYTES, len(data))
|
||||||
if len(data) < packet.MinAnnounceSize {
|
if len(data) < packet.MinAnnounceSize {
|
||||||
debug.Log(debug.DEBUG_INFO, "Announce packet too short", "bytes", len(data))
|
debug.Log(debug.DEBUG_INFO, "Announce packet too short", "bytes", len(data))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
destHash := data[2:18]
|
destHash := data[common.TWO : common.SIZE_16+common.TWO]
|
||||||
encKey := data[18:50]
|
encKey := data[common.SIZE_16+common.TWO : common.SIZE_32+common.SIZE_16+common.TWO]
|
||||||
signKey := data[50:82]
|
signKey := data[common.SIZE_32+common.SIZE_16+common.TWO : common.SIZE_32*common.TWO+common.SIZE_16+common.TWO]
|
||||||
nameHash := data[82:92]
|
nameHash := data[common.SIZE_32*common.TWO+common.SIZE_16+common.TWO : common.SIZE_32*common.TWO+common.SIZE_16+common.TWO+common.EIGHT+common.TWO]
|
||||||
randomHash := data[92:102]
|
randomHash := data[common.SIZE_32*common.TWO+common.SIZE_16+common.TWO+common.EIGHT+common.TWO : common.SIZE_32*common.TWO+common.SIZE_16+common.TWO+common.EIGHT*common.TWO+common.TWO]
|
||||||
signature := data[102:166]
|
signature := data[common.SIZE_32*common.TWO+common.SIZE_16+common.TWO+common.EIGHT*common.TWO+common.TWO : common.SIZE_64+common.SIZE_32*common.TWO+common.SIZE_16+common.TWO+common.EIGHT*common.TWO+common.TWO]
|
||||||
appData := data[166:]
|
appData := data[common.SIZE_64+common.SIZE_32*common.TWO+common.SIZE_16+common.TWO+common.EIGHT*common.TWO+common.TWO:]
|
||||||
|
|
||||||
pubKey := append(encKey, signKey...)
|
pubKey := append(encKey, signKey...)
|
||||||
|
|
||||||
validationData := make([]byte, 0, 164)
|
validationData := make([]byte, common.ZERO, common.SIZE_32*common.FIVE+common.FOUR)
|
||||||
validationData = append(validationData, destHash...)
|
validationData = append(validationData, destHash...)
|
||||||
validationData = append(validationData, encKey...)
|
validationData = append(validationData, encKey...)
|
||||||
validationData = append(validationData, signKey...)
|
validationData = append(validationData, signKey...)
|
||||||
@@ -1498,18 +1503,18 @@ func (l *Link) decodePacket(data []byte) {
|
|||||||
validationData = append(validationData, randomHash...)
|
validationData = append(validationData, randomHash...)
|
||||||
|
|
||||||
if identity.ValidateAnnounce(validationData, destHash, pubKey, signature, appData) {
|
if identity.ValidateAnnounce(validationData, destHash, pubKey, signature, appData) {
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Valid announce from", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Valid announce from", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
if err := l.transport.HandleAnnounce(destHash, l.networkInterface); err != nil {
|
if err := l.transport.HandleAnnounce(destHash, l.networkInterface); err != nil {
|
||||||
debug.Log(debug.DEBUG_INFO, "Failed to handle announce", "error", err)
|
debug.Log(debug.DEBUG_INFO, "Failed to handle announce", "error", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug.Log(debug.DEBUG_INFO, "Invalid announce signature from", "public_key", fmt.Sprintf("%x", pubKey[:8]))
|
debug.Log(debug.DEBUG_INFO, "Invalid announce signature from", "public_key", fmt.Sprintf("%x", pubKey[:common.EIGHT]))
|
||||||
}
|
}
|
||||||
|
|
||||||
case packet.PacketTypeProof:
|
case packet.PacketTypeProof:
|
||||||
debug.Log(debug.DEBUG_ALL, "Type Description: RNS Discovery")
|
debug.Log(debug.DEBUG_ALL, "Type Description: RNS Discovery")
|
||||||
if len(data) > 17 {
|
if len(data) > common.SIZE_16+common.ONE {
|
||||||
searchHash := data[1:17]
|
searchHash := data[common.ONE : common.SIZE_16+common.ONE]
|
||||||
debug.Log(debug.DEBUG_ALL, "Searching for Hash", "search_hash", fmt.Sprintf("%x", searchHash))
|
debug.Log(debug.DEBUG_ALL, "Searching for Hash", "search_hash", fmt.Sprintf("%x", searchHash))
|
||||||
|
|
||||||
if id, err := resolver.ResolveIdentity(hex.EncodeToString(searchHash)); err == nil {
|
if id, err := resolver.ResolveIdentity(hex.EncodeToString(searchHash)); err == nil {
|
||||||
@@ -1535,12 +1540,12 @@ func (l *Link) watchdog() {
|
|||||||
for l.status != STATUS_CLOSED {
|
for l.status != STATUS_CLOSED {
|
||||||
l.mutex.Lock()
|
l.mutex.Lock()
|
||||||
if l.watchdogLock {
|
if l.watchdogLock {
|
||||||
rttWait := 0.025
|
rttWait := common.FLOAT_0_025
|
||||||
if l.rtt > 0 {
|
if l.rtt > common.FLOAT_ZERO {
|
||||||
rttWait = l.rtt
|
rttWait = l.rtt
|
||||||
}
|
}
|
||||||
if rttWait < 0.025 {
|
if rttWait < common.FLOAT_0_025 {
|
||||||
rttWait = 0.025
|
rttWait = common.FLOAT_0_025
|
||||||
}
|
}
|
||||||
l.mutex.Unlock()
|
l.mutex.Unlock()
|
||||||
time.Sleep(time.Duration(rttWait * float64(time.Second)))
|
time.Sleep(time.Duration(rttWait * float64(time.Second)))
|
||||||
@@ -1559,7 +1564,7 @@ func (l *Link) watchdog() {
|
|||||||
if l.closedCallback != nil {
|
if l.closedCallback != nil {
|
||||||
l.closedCallback(l)
|
l.closedCallback(l)
|
||||||
}
|
}
|
||||||
sleepTime = 0.001
|
sleepTime = common.FLOAT_0_001
|
||||||
}
|
}
|
||||||
} else if l.status == STATUS_HANDSHAKE {
|
} else if l.status == STATUS_HANDSHAKE {
|
||||||
nextCheck := l.requestTime.Add(l.establishmentTimeout)
|
nextCheck := l.requestTime.Add(l.establishmentTimeout)
|
||||||
@@ -1607,20 +1612,21 @@ func (l *Link) watchdog() {
|
|||||||
sleepTime = time.Until(nextKeepalive).Seconds()
|
sleepTime = time.Until(nextKeepalive).Seconds()
|
||||||
}
|
}
|
||||||
} else if l.status == STATUS_STALE {
|
} else if l.status == STATUS_STALE {
|
||||||
sleepTime = 0.001
|
sleepTime = common.FLOAT_0_001
|
||||||
_ = l.sendTeardownPacket() // #nosec G104 - best effort teardown
|
_ = l.sendTeardownPacket() // #nosec G104 - best effort teardown
|
||||||
l.status = STATUS_CLOSED
|
l.status = STATUS_CLOSED
|
||||||
l.teardownReason = STATUS_FAILED
|
l.teardownReason = STATUS_FAILED
|
||||||
if l.closedCallback != nil {
|
if l.closedCallback != nil {
|
||||||
l.closedCallback(l)
|
l.closedCallback(l)
|
||||||
}
|
}
|
||||||
|
sleepTime = common.FLOAT_0_001
|
||||||
}
|
}
|
||||||
|
|
||||||
if sleepTime <= 0 {
|
if sleepTime <= common.FLOAT_ZERO {
|
||||||
sleepTime = 0.1
|
sleepTime = common.FLOAT_0_1
|
||||||
}
|
}
|
||||||
if sleepTime > 5.0 {
|
if sleepTime > common.FLOAT_5_0 {
|
||||||
sleepTime = 5.0
|
sleepTime = common.FLOAT_5_0
|
||||||
}
|
}
|
||||||
|
|
||||||
l.mutex.Unlock()
|
l.mutex.Unlock()
|
||||||
@@ -1634,11 +1640,11 @@ func (l *Link) sendKeepalive() error {
|
|||||||
keepalivePkt := &packet.Packet{
|
keepalivePkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextKeepalive,
|
Context: packet.ContextKeepalive,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: keepaliveData,
|
Data: keepaliveData,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -1659,11 +1665,11 @@ func (l *Link) sendTeardownPacket() error {
|
|||||||
teardownPkt := &packet.Packet{
|
teardownPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextLinkClose,
|
Context: packet.ContextLinkClose,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: l.linkID,
|
Data: l.linkID,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -1711,10 +1717,10 @@ func (l *Link) generateEphemeralKeys() error {
|
|||||||
|
|
||||||
func signallingBytes(mtu int, mode byte) []byte {
|
func signallingBytes(mtu int, mode byte) []byte {
|
||||||
bytes := make([]byte, LINK_MTU_SIZE)
|
bytes := make([]byte, LINK_MTU_SIZE)
|
||||||
bytes[0] = byte((mtu >> 16) & 0xFF)
|
bytes[common.ZERO] = byte((mtu >> common.SIZE_16) & common.HEX_0xFF)
|
||||||
bytes[1] = byte((mtu >> 8) & 0xFF)
|
bytes[common.ONE] = byte((mtu >> common.EIGHT) & common.HEX_0xFF)
|
||||||
bytes[2] = byte(mtu & 0xFF)
|
bytes[common.TWO] = byte(mtu & common.HEX_0xFF)
|
||||||
bytes[0] |= (mode << 5)
|
bytes[common.ZERO] |= (mode << common.FIVE)
|
||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1724,7 +1730,7 @@ func (l *Link) SendLinkRequest() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l.mode = MODE_DEFAULT
|
l.mode = MODE_DEFAULT
|
||||||
l.mtu = 500
|
l.mtu = common.DEFAULT_MTU / common.THREE
|
||||||
l.updateMDU()
|
l.updateMDU()
|
||||||
|
|
||||||
signalling := signallingBytes(l.mtu, l.mode)
|
signalling := signallingBytes(l.mtu, l.mode)
|
||||||
@@ -1736,10 +1742,10 @@ func (l *Link) SendLinkRequest() error {
|
|||||||
pkt := &packet.Packet{
|
pkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeLinkReq,
|
PacketType: packet.PacketTypeLinkReq,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextNone,
|
Context: packet.ContextNone,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: l.destination.GetType(),
|
DestinationType: l.destination.GetType(),
|
||||||
DestinationHash: l.destination.GetHash(),
|
DestinationHash: l.destination.GetHash(),
|
||||||
Data: requestData,
|
Data: requestData,
|
||||||
@@ -1764,18 +1770,18 @@ func (l *Link) SendLinkRequest() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func linkIDFromPacket(pkt *packet.Packet) []byte {
|
func linkIDFromPacket(pkt *packet.Packet) []byte {
|
||||||
hashablePart := make([]byte, 0, 1+16+1+ECPUBSIZE)
|
hashablePart := make([]byte, common.ZERO, common.ONE+common.SIZE_16+common.ONE+ECPUBSIZE)
|
||||||
hashablePart = append(hashablePart, pkt.Raw[0])
|
hashablePart = append(hashablePart, pkt.Raw[common.ZERO])
|
||||||
|
|
||||||
if pkt.HeaderType == packet.HeaderType2 {
|
if pkt.HeaderType == packet.HeaderType2 {
|
||||||
startIndex := 18
|
startIndex := common.SIZE_16 + common.TWO
|
||||||
endIndex := startIndex + 16 + 1 + ECPUBSIZE
|
endIndex := startIndex + common.SIZE_16 + common.ONE + ECPUBSIZE
|
||||||
if len(pkt.Raw) >= endIndex {
|
if len(pkt.Raw) >= endIndex {
|
||||||
hashablePart = append(hashablePart, pkt.Raw[startIndex:endIndex]...)
|
hashablePart = append(hashablePart, pkt.Raw[startIndex:endIndex]...)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
startIndex := 2
|
startIndex := common.TWO
|
||||||
endIndex := startIndex + 16 + 1 + ECPUBSIZE
|
endIndex := startIndex + common.SIZE_16 + common.ONE + ECPUBSIZE
|
||||||
if len(pkt.Raw) >= endIndex {
|
if len(pkt.Raw) >= endIndex {
|
||||||
hashablePart = append(hashablePart, pkt.Raw[startIndex:endIndex]...)
|
hashablePart = append(hashablePart, pkt.Raw[startIndex:endIndex]...)
|
||||||
}
|
}
|
||||||
@@ -1788,7 +1794,7 @@ func (l *Link) HandleLinkRequest(pkt *packet.Packet, ownerIdentity *identity.Ide
|
|||||||
return errors.New("link request data too short")
|
return errors.New("link request data too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
peerPub := pkt.Data[0:KEYSIZE]
|
peerPub := pkt.Data[common.ZERO:KEYSIZE]
|
||||||
peerSigPub := pkt.Data[KEYSIZE:ECPUBSIZE]
|
peerSigPub := pkt.Data[KEYSIZE:ECPUBSIZE]
|
||||||
|
|
||||||
l.peerPub = peerPub
|
l.peerPub = peerPub
|
||||||
@@ -1802,7 +1808,7 @@ func (l *Link) HandleLinkRequest(pkt *packet.Packet, ownerIdentity *identity.Ide
|
|||||||
l.mode = (mtuBytes[0] & MODE_BYTEMASK) >> 5
|
l.mode = (mtuBytes[0] & MODE_BYTEMASK) >> 5
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Link request includes MTU", "mtu", l.mtu, "mode", l.mode)
|
debug.Log(debug.DEBUG_VERBOSE, "Link request includes MTU", "mtu", l.mtu, "mode", l.mode)
|
||||||
} else {
|
} else {
|
||||||
l.mtu = 500
|
l.mtu = common.DEFAULT_MTU / common.THREE
|
||||||
l.mode = MODE_DEFAULT
|
l.mode = MODE_DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1834,14 +1840,14 @@ func (l *Link) HandleLinkRequest(pkt *packet.Packet, ownerIdentity *identity.Ide
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Link) updateMDU() {
|
func (l *Link) updateMDU() {
|
||||||
headerMaxSize := 64
|
headerMaxSize := common.SIZE_64
|
||||||
ifacMinSize := 4
|
ifacMinSize := common.FOUR
|
||||||
tokenOverhead := 16
|
tokenOverhead := common.SIZE_16
|
||||||
aesBlockSize := 16
|
aesBlockSize := common.SIZE_16
|
||||||
|
|
||||||
l.mdu = int(float64(l.mtu-headerMaxSize-ifacMinSize-tokenOverhead)/float64(aesBlockSize))*aesBlockSize - 1
|
l.mdu = int(float64(l.mtu-headerMaxSize-ifacMinSize-tokenOverhead)/float64(aesBlockSize))*aesBlockSize - common.ONE
|
||||||
if l.mdu < 0 {
|
if l.mdu < common.ZERO {
|
||||||
l.mdu = 100
|
l.mdu = common.DEFAULT_MTU / common.FIFTEEN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1891,7 +1897,7 @@ func (l *Link) sendLinkProof(ownerIdentity *identity.Identity) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_ERROR, "Link proof packet created", "dest_hash", fmt.Sprintf("%x", proofPkt.DestinationHash), "packet_type", fmt.Sprintf("0x%02x", proofPkt.PacketType))
|
debug.Log(debug.DEBUG_ERROR, "Link proof packet created", "dest_hash", fmt.Sprintf("%x", proofPkt.DestinationHash), "packet_type", fmt.Sprintf(common.STR_FMT_HEX, proofPkt.PacketType))
|
||||||
|
|
||||||
// For responder links (not initiator), send proof directly through the receiving interface
|
// For responder links (not initiator), send proof directly through the receiving interface
|
||||||
if !l.initiator && l.networkInterface != nil {
|
if !l.initiator && l.networkInterface != nil {
|
||||||
@@ -1940,11 +1946,11 @@ func (l *Link) GenerateLinkProof(ownerIdentity *identity.Identity) (*packet.Pack
|
|||||||
proofPkt := &packet.Packet{
|
proofPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeProof,
|
PacketType: packet.PacketTypeProof,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextLRProof,
|
Context: packet.ContextLRProof,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: proofData,
|
Data: proofData,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
@@ -1967,14 +1973,14 @@ func (l *Link) ValidateLinkProof(pkt *packet.Packet) error {
|
|||||||
return errors.New("link proof data too short")
|
return errors.New("link proof data too short")
|
||||||
}
|
}
|
||||||
|
|
||||||
signature := pkt.Data[0 : identity.SIGLENGTH/8]
|
signature := pkt.Data[common.ZERO : identity.SIGLENGTH/common.EIGHT]
|
||||||
peerPub := pkt.Data[identity.SIGLENGTH/8 : identity.SIGLENGTH/8+KEYSIZE]
|
peerPub := pkt.Data[identity.SIGLENGTH/common.EIGHT : identity.SIGLENGTH/common.EIGHT+KEYSIZE]
|
||||||
|
|
||||||
signalling := []byte{0, 0, 0}
|
signalling := []byte{common.ZERO, common.ZERO, common.ZERO}
|
||||||
if len(pkt.Data) >= identity.SIGLENGTH/8+KEYSIZE+LINK_MTU_SIZE {
|
if len(pkt.Data) >= identity.SIGLENGTH/8+KEYSIZE+LINK_MTU_SIZE {
|
||||||
signalling = pkt.Data[identity.SIGLENGTH/8+KEYSIZE : identity.SIGLENGTH/8+KEYSIZE+LINK_MTU_SIZE]
|
signalling = pkt.Data[identity.SIGLENGTH/8+KEYSIZE : identity.SIGLENGTH/8+KEYSIZE+LINK_MTU_SIZE]
|
||||||
mtu := (int(signalling[0]&0x1F) << 16) | (int(signalling[1]) << 8) | int(signalling[2])
|
mtu := (int(signalling[common.ZERO]&0x1F) << common.SIZE_16) | (int(signalling[common.ONE]) << common.EIGHT) | int(signalling[common.TWO])
|
||||||
mode := (signalling[0] & MODE_BYTEMASK) >> 5
|
mode := (signalling[common.ZERO] & MODE_BYTEMASK) >> common.FIVE
|
||||||
l.mtu = mtu
|
l.mtu = mtu
|
||||||
l.mode = mode
|
l.mode = mode
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Link proof includes MTU", "mtu", mtu, "mode", mode)
|
debug.Log(debug.DEBUG_VERBOSE, "Link proof includes MTU", "mtu", mtu, "mode", mode)
|
||||||
@@ -2018,15 +2024,15 @@ func (l *Link) ValidateLinkProof(pkt *packet.Packet) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rttData := make([]byte, 8)
|
rttData := make([]byte, 8)
|
||||||
binary.BigEndian.PutUint64(rttData, uint64(l.rtt*1e9))
|
binary.BigEndian.PutUint64(rttData, uint64(l.rtt*common.FLOAT_1E9))
|
||||||
rttPkt := &packet.Packet{
|
rttPkt := &packet.Packet{
|
||||||
HeaderType: packet.HeaderType1,
|
HeaderType: packet.HeaderType1,
|
||||||
PacketType: packet.PacketTypeData,
|
PacketType: packet.PacketTypeData,
|
||||||
TransportType: 0,
|
TransportType: common.ZERO,
|
||||||
Context: packet.ContextLRRTT,
|
Context: packet.ContextLRRTT,
|
||||||
ContextFlag: packet.FlagUnset,
|
ContextFlag: packet.FlagUnset,
|
||||||
Hops: 0,
|
Hops: common.ZERO,
|
||||||
DestinationType: 0x03,
|
DestinationType: DEST_TYPE_LINK,
|
||||||
DestinationHash: l.linkID,
|
DestinationHash: l.linkID,
|
||||||
Data: rttData,
|
Data: rttData,
|
||||||
CreateReceipt: false,
|
CreateReceipt: false,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ type Packet struct {
|
|||||||
|
|
||||||
Addresses []byte
|
Addresses []byte
|
||||||
Link interface{}
|
Link interface{}
|
||||||
|
|
||||||
receipt *PacketReceipt
|
receipt *PacketReceipt
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ func (p *Packet) Pack() error {
|
|||||||
debug.Log(debug.DEBUG_TRACE, "Created packet header", "flags", fmt.Sprintf("%08b", flags), "hops", p.Hops)
|
debug.Log(debug.DEBUG_TRACE, "Created packet header", "flags", fmt.Sprintf("%08b", flags), "hops", p.Hops)
|
||||||
|
|
||||||
header = append(header, p.DestinationHash...)
|
header = append(header, p.DestinationHash...)
|
||||||
|
|
||||||
if p.HeaderType == HeaderType2 {
|
if p.HeaderType == HeaderType2 {
|
||||||
if p.TransportID == nil {
|
if p.TransportID == nil {
|
||||||
return errors.New("transport ID required for header type 2")
|
return errors.New("transport ID required for header type 2")
|
||||||
@@ -189,8 +189,8 @@ func (p *Packet) Unpack() error {
|
|||||||
if len(p.Raw) < 2*dstLen+3 {
|
if len(p.Raw) < 2*dstLen+3 {
|
||||||
return errors.New("packet too short for header type 2")
|
return errors.New("packet too short for header type 2")
|
||||||
}
|
}
|
||||||
p.DestinationHash = p.Raw[2 : dstLen+2] // Destination hash first
|
p.DestinationHash = p.Raw[2 : dstLen+2] // Destination hash first
|
||||||
p.TransportID = p.Raw[dstLen+2 : 2*dstLen+2] // Transport ID second
|
p.TransportID = p.Raw[dstLen+2 : 2*dstLen+2] // Transport ID second
|
||||||
p.Context = p.Raw[2*dstLen+2]
|
p.Context = p.Raw[2*dstLen+2]
|
||||||
p.Data = p.Raw[2*dstLen+3:]
|
p.Data = p.Raw[2*dstLen+3:]
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -32,14 +32,14 @@ type PacketReceipt struct {
|
|||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
concludedAt time.Time
|
concludedAt time.Time
|
||||||
proofPacket *Packet
|
proofPacket *Packet
|
||||||
|
|
||||||
deliveryCallback func(*PacketReceipt)
|
deliveryCallback func(*PacketReceipt)
|
||||||
timeoutCallback func(*PacketReceipt)
|
timeoutCallback func(*PacketReceipt)
|
||||||
|
|
||||||
link interface{}
|
link interface{}
|
||||||
destinationHash []byte
|
destinationHash []byte
|
||||||
destinationIdent *identity.Identity
|
destinationIdent *identity.Identity
|
||||||
timeoutCheckDone chan bool
|
timeoutCheckDone chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPacketReceipt(pkt *Packet) *PacketReceipt {
|
func NewPacketReceipt(pkt *Packet) *PacketReceipt {
|
||||||
@@ -57,18 +57,18 @@ func NewPacketReceipt(pkt *Packet) *PacketReceipt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go receipt.timeoutWatchdog()
|
go receipt.timeoutWatchdog()
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_PACKETS, "Created packet receipt", "hash", fmt.Sprintf("%x", receipt.truncatedHash))
|
debug.Log(debug.DEBUG_PACKETS, "Created packet receipt", "hash", fmt.Sprintf("%x", receipt.truncatedHash))
|
||||||
return receipt
|
return receipt
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateTimeout(pkt *Packet) time.Duration {
|
func calculateTimeout(pkt *Packet) time.Duration {
|
||||||
baseTimeout := 15 * time.Second
|
baseTimeout := 15 * time.Second
|
||||||
|
|
||||||
if pkt.Hops > 0 {
|
if pkt.Hops > 0 {
|
||||||
baseTimeout += time.Duration(pkt.Hops) * (3 * time.Second)
|
baseTimeout += time.Duration(pkt.Hops) * (3 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
return baseTimeout
|
return baseTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,11 +107,11 @@ func (pr *PacketReceipt) ValidateLinkProof(proof []byte, link interface{}, proof
|
|||||||
if len(proof) == EXPL_LENGTH {
|
if len(proof) == EXPL_LENGTH {
|
||||||
proofHash := proof[:identity.HASHLENGTH/8]
|
proofHash := proof[:identity.HASHLENGTH/8]
|
||||||
signature := proof[identity.HASHLENGTH/8 : identity.HASHLENGTH/8+identity.SIGLENGTH/8]
|
signature := proof[identity.HASHLENGTH/8 : identity.HASHLENGTH/8+identity.SIGLENGTH/8]
|
||||||
|
|
||||||
pr.mutex.RLock()
|
pr.mutex.RLock()
|
||||||
hashMatch := string(proofHash) == string(pr.hash)
|
hashMatch := string(proofHash) == string(pr.hash)
|
||||||
pr.mutex.RUnlock()
|
pr.mutex.RUnlock()
|
||||||
|
|
||||||
if !hashMatch {
|
if !hashMatch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ func (pr *PacketReceipt) ValidateLinkProof(proof []byte, link interface{}, proof
|
|||||||
} else if len(proof) == IMPL_LENGTH {
|
} else if len(proof) == IMPL_LENGTH {
|
||||||
debug.Log(debug.DEBUG_TRACE, "Implicit link proof not yet implemented")
|
debug.Log(debug.DEBUG_TRACE, "Implicit link proof not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,14 +144,14 @@ func (pr *PacketReceipt) ValidateProof(proof []byte, proofPacket *Packet) bool {
|
|||||||
if len(proof) == EXPL_LENGTH {
|
if len(proof) == EXPL_LENGTH {
|
||||||
proofHash := proof[:identity.HASHLENGTH/8]
|
proofHash := proof[:identity.HASHLENGTH/8]
|
||||||
signature := proof[identity.HASHLENGTH/8 : identity.HASHLENGTH/8+identity.SIGLENGTH/8]
|
signature := proof[identity.HASHLENGTH/8 : identity.HASHLENGTH/8+identity.SIGLENGTH/8]
|
||||||
|
|
||||||
pr.mutex.RLock()
|
pr.mutex.RLock()
|
||||||
hashMatch := string(proofHash) == string(pr.hash)
|
hashMatch := string(proofHash) == string(pr.hash)
|
||||||
ident := pr.destinationIdent
|
ident := pr.destinationIdent
|
||||||
pr.mutex.RUnlock()
|
pr.mutex.RUnlock()
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_PACKETS, "Explicit proof validation", "len", len(proof), "hashMatch", hashMatch, "hasIdent", ident != nil)
|
debug.Log(debug.DEBUG_PACKETS, "Explicit proof validation", "len", len(proof), "hashMatch", hashMatch, "hasIdent", ident != nil)
|
||||||
|
|
||||||
if !hashMatch {
|
if !hashMatch {
|
||||||
debug.Log(debug.DEBUG_PACKETS, "Proof hash mismatch")
|
debug.Log(debug.DEBUG_PACKETS, "Proof hash mismatch")
|
||||||
return false
|
return false
|
||||||
@@ -182,7 +182,7 @@ func (pr *PacketReceipt) ValidateProof(proof []byte, proofPacket *Packet) bool {
|
|||||||
}
|
}
|
||||||
} else if len(proof) == IMPL_LENGTH {
|
} else if len(proof) == IMPL_LENGTH {
|
||||||
signature := proof[:identity.SIGLENGTH/8]
|
signature := proof[:identity.SIGLENGTH/8]
|
||||||
|
|
||||||
pr.mutex.RLock()
|
pr.mutex.RLock()
|
||||||
ident := pr.destinationIdent
|
ident := pr.destinationIdent
|
||||||
pr.mutex.RUnlock()
|
pr.mutex.RUnlock()
|
||||||
@@ -209,7 +209,7 @@ func (pr *PacketReceipt) ValidateProof(proof []byte, proofPacket *Packet) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,11 +217,11 @@ func (pr *PacketReceipt) validateLinkSignature(signature []byte, link interface{
|
|||||||
type linkValidator interface {
|
type linkValidator interface {
|
||||||
Validate(signature, message []byte) bool
|
Validate(signature, message []byte) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
if validator, ok := link.(linkValidator); ok {
|
if validator, ok := link.(linkValidator); ok {
|
||||||
return validator.Validate(signature, pr.hash)
|
return validator.Validate(signature, pr.hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_TRACE, "Link does not implement Validate method")
|
debug.Log(debug.DEBUG_TRACE, "Link does not implement Validate method")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -229,46 +229,46 @@ func (pr *PacketReceipt) validateLinkSignature(signature []byte, link interface{
|
|||||||
func (pr *PacketReceipt) GetRTT() time.Duration {
|
func (pr *PacketReceipt) GetRTT() time.Duration {
|
||||||
pr.mutex.RLock()
|
pr.mutex.RLock()
|
||||||
defer pr.mutex.RUnlock()
|
defer pr.mutex.RUnlock()
|
||||||
|
|
||||||
if pr.concludedAt.IsZero() {
|
if pr.concludedAt.IsZero() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return pr.concludedAt.Sub(pr.sentAt)
|
return pr.concludedAt.Sub(pr.sentAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pr *PacketReceipt) IsTimedOut() bool {
|
func (pr *PacketReceipt) IsTimedOut() bool {
|
||||||
pr.mutex.RLock()
|
pr.mutex.RLock()
|
||||||
defer pr.mutex.RUnlock()
|
defer pr.mutex.RUnlock()
|
||||||
|
|
||||||
return time.Since(pr.sentAt) > pr.timeout
|
return time.Since(pr.sentAt) > pr.timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pr *PacketReceipt) checkTimeout() {
|
func (pr *PacketReceipt) checkTimeout() {
|
||||||
pr.mutex.Lock()
|
pr.mutex.Lock()
|
||||||
|
|
||||||
if pr.status != RECEIPT_SENT {
|
if pr.status != RECEIPT_SENT {
|
||||||
pr.mutex.Unlock()
|
pr.mutex.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pr.IsTimedOut() {
|
if !pr.IsTimedOut() {
|
||||||
pr.mutex.Unlock()
|
pr.mutex.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if pr.timeout < 0 {
|
if pr.timeout < 0 {
|
||||||
pr.status = RECEIPT_CULLED
|
pr.status = RECEIPT_CULLED
|
||||||
} else {
|
} else {
|
||||||
pr.status = RECEIPT_FAILED
|
pr.status = RECEIPT_FAILED
|
||||||
}
|
}
|
||||||
|
|
||||||
pr.concludedAt = time.Now()
|
pr.concludedAt = time.Now()
|
||||||
callback := pr.timeoutCallback
|
callback := pr.timeoutCallback
|
||||||
pr.mutex.Unlock()
|
pr.mutex.Unlock()
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Packet receipt timed out", "hash", fmt.Sprintf("%x", pr.truncatedHash))
|
debug.Log(debug.DEBUG_VERBOSE, "Packet receipt timed out", "hash", fmt.Sprintf("%x", pr.truncatedHash))
|
||||||
|
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
go callback(pr)
|
go callback(pr)
|
||||||
}
|
}
|
||||||
@@ -282,11 +282,11 @@ func (pr *PacketReceipt) timeoutWatchdog() {
|
|||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
pr.checkTimeout()
|
pr.checkTimeout()
|
||||||
|
|
||||||
pr.mutex.RLock()
|
pr.mutex.RLock()
|
||||||
status := pr.status
|
status := pr.status
|
||||||
pr.mutex.RUnlock()
|
pr.mutex.RUnlock()
|
||||||
|
|
||||||
if status != RECEIPT_SENT {
|
if status != RECEIPT_SENT {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -329,15 +329,14 @@ func (pr *PacketReceipt) SetLink(link interface{}) {
|
|||||||
func (pr *PacketReceipt) Cancel() {
|
func (pr *PacketReceipt) Cancel() {
|
||||||
pr.mutex.Lock()
|
pr.mutex.Lock()
|
||||||
defer pr.mutex.Unlock()
|
defer pr.mutex.Unlock()
|
||||||
|
|
||||||
if pr.status == RECEIPT_SENT {
|
if pr.status == RECEIPT_SENT {
|
||||||
pr.status = RECEIPT_CULLED
|
pr.status = RECEIPT_CULLED
|
||||||
pr.concludedAt = time.Now()
|
pr.concludedAt = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case pr.timeoutCheckDone <- true:
|
case pr.timeoutCheckDone <- true:
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,13 +115,13 @@ func TestPacketReceiptProofValidation(t *testing.T) {
|
|||||||
|
|
||||||
packetHash := pkt.GetHash()
|
packetHash := pkt.GetHash()
|
||||||
t.Logf("Packet hash: %x", packetHash)
|
t.Logf("Packet hash: %x", packetHash)
|
||||||
|
|
||||||
signature := testIdent.Sign(packetHash)
|
signature := testIdent.Sign(packetHash)
|
||||||
|
|
||||||
t.Logf("PacketHash length: %d", len(packetHash))
|
t.Logf("PacketHash length: %d", len(packetHash))
|
||||||
t.Logf("Signature length: %d", len(signature))
|
t.Logf("Signature length: %d", len(signature))
|
||||||
t.Logf("EXPL_LENGTH constant: %d", EXPL_LENGTH)
|
t.Logf("EXPL_LENGTH constant: %d", EXPL_LENGTH)
|
||||||
|
|
||||||
if testIdent.Verify(packetHash, signature) {
|
if testIdent.Verify(packetHash, signature) {
|
||||||
t.Log("Direct verification succeeded")
|
t.Log("Direct verification succeeded")
|
||||||
} else {
|
} else {
|
||||||
@@ -207,4 +207,3 @@ func TestPacketReceiptCallbacks(t *testing.T) {
|
|||||||
t.Error("Delivery callback was not called")
|
t.Error("Delivery callback was not called")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,13 +162,13 @@ func NewTransport(cfg *common.ReticulumConfig) *Transport {
|
|||||||
interfaces: make(map[string]common.NetworkInterface),
|
interfaces: make(map[string]common.NetworkInterface),
|
||||||
paths: make(map[string]*common.Path),
|
paths: make(map[string]*common.Path),
|
||||||
seenAnnounces: make(map[string]bool),
|
seenAnnounces: make(map[string]bool),
|
||||||
announceRate: rate.NewLimiter(PROPAGATION_RATE, 1),
|
announceRate: rate.NewLimiter(PROPAGATION_RATE, common.ONE),
|
||||||
mutex: sync.RWMutex{},
|
mutex: sync.RWMutex{},
|
||||||
config: cfg,
|
config: cfg,
|
||||||
links: make(map[string]LinkInterface),
|
links: make(map[string]LinkInterface),
|
||||||
destinations: make(map[string]interface{}),
|
destinations: make(map[string]interface{}),
|
||||||
pathfinder: pathfinder.NewPathFinder(),
|
pathfinder: pathfinder.NewPathFinder(),
|
||||||
receipts: make([]*packet.PacketReceipt, 0),
|
receipts: make([]*packet.PacketReceipt, common.ZERO),
|
||||||
receiptsMutex: sync.RWMutex{},
|
receiptsMutex: sync.RWMutex{},
|
||||||
pathRequests: make(map[string]time.Time),
|
pathRequests: make(map[string]time.Time),
|
||||||
pathStates: make(map[string]byte),
|
pathStates: make(map[string]byte),
|
||||||
@@ -189,7 +189,7 @@ func NewTransport(cfg *common.ReticulumConfig) *Transport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) startMaintenanceJobs() {
|
func (t *Transport) startMaintenanceJobs() {
|
||||||
ticker := time.NewTicker(5 * time.Second)
|
ticker := time.NewTicker(common.FIVE * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
@@ -211,7 +211,7 @@ func (t *Transport) cleanupExpiredPaths() {
|
|||||||
if now.Sub(path.LastUpdated) > pathExpiry {
|
if now.Sub(path.LastUpdated) > pathExpiry {
|
||||||
delete(t.paths, destHash)
|
delete(t.paths, destHash)
|
||||||
delete(t.pathStates, destHash)
|
delete(t.pathStates, destHash)
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Expired path", "dest_hash", fmt.Sprintf("%x", destHash[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Expired path", "dest_hash", fmt.Sprintf("%x", destHash[:common.EIGHT]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ func (t *Transport) cleanupExpiredDiscoveryRequests() {
|
|||||||
for destHash, req := range t.discoveryPathRequests {
|
for destHash, req := range t.discoveryPathRequests {
|
||||||
if now.After(req.Timeout) {
|
if now.After(req.Timeout) {
|
||||||
delete(t.discoveryPathRequests, destHash)
|
delete(t.discoveryPathRequests, destHash)
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Expired discovery path request", "dest_hash", fmt.Sprintf("%x", destHash[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Expired discovery path request", "dest_hash", fmt.Sprintf("%x", destHash[:common.EIGHT]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ func (t *Transport) cleanupExpiredAnnounces() {
|
|||||||
for destHash, entry := range t.announceTable {
|
for destHash, entry := range t.announceTable {
|
||||||
if entry != nil && time.Since(entry.CreatedAt) > announceExpiry {
|
if entry != nil && time.Since(entry.CreatedAt) > announceExpiry {
|
||||||
delete(t.announceTable, destHash)
|
delete(t.announceTable, destHash)
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Expired announce entry", "dest_hash", fmt.Sprintf("%x", destHash[:8]))
|
debug.Log(debug.DEBUG_VERBOSE, "Expired announce entry", "dest_hash", fmt.Sprintf("%x", destHash[:common.EIGHT]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ func (t *Transport) cleanupExpiredReceipts() {
|
|||||||
t.receiptsMutex.Lock()
|
t.receiptsMutex.Lock()
|
||||||
defer t.receiptsMutex.Unlock()
|
defer t.receiptsMutex.Unlock()
|
||||||
|
|
||||||
validReceipts := make([]*packet.PacketReceipt, 0)
|
validReceipts := make([]*packet.PacketReceipt, common.ZERO)
|
||||||
for _, receipt := range t.receipts {
|
for _, receipt := range t.receipts {
|
||||||
if receipt != nil && !receipt.IsTimedOut() {
|
if receipt != nil && !receipt.IsTimedOut() {
|
||||||
status := receipt.GetStatus()
|
status := receipt.GetStatus()
|
||||||
@@ -452,7 +452,7 @@ func (l *Link) Send(data []byte) interface{} {
|
|||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.rtt == 0 {
|
if l.rtt == common.FLOAT_ZERO {
|
||||||
l.rtt = l.InactiveFor()
|
l.rtt = l.InactiveFor()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,9 +594,9 @@ func (t *Transport) HandleAnnounce(data []byte, sourceIface common.NetworkInterf
|
|||||||
debug.Log(debug.DEBUG_ALL, "Transport handling announce", "bytes", len(data), "source", sourceIface.GetName())
|
debug.Log(debug.DEBUG_ALL, "Transport handling announce", "bytes", len(data), "source", sourceIface.GetName())
|
||||||
|
|
||||||
// Parse announce fields according to RNS spec
|
// Parse announce fields according to RNS spec
|
||||||
destHash := data[1:33]
|
destHash := data[common.ONE:common.SIZE_32+common.ONE]
|
||||||
identity := data[33:49]
|
identity := data[common.SIZE_32+common.ONE:common.SIZE_16+common.SIZE_32+common.ONE]
|
||||||
appData := data[49:]
|
appData := data[common.SIZE_16+common.SIZE_32+common.ONE:]
|
||||||
|
|
||||||
// Generate announce hash to check for duplicates
|
// Generate announce hash to check for duplicates
|
||||||
announceHash := sha256.Sum256(data)
|
announceHash := sha256.Sum256(data)
|
||||||
@@ -605,15 +605,15 @@ func (t *Transport) HandleAnnounce(data []byte, sourceIface common.NetworkInterf
|
|||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
if _, seen := t.seenAnnounces[hashStr]; seen {
|
if _, seen := t.seenAnnounces[hashStr]; seen {
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
debug.Log(debug.DEBUG_ALL, "Ignoring duplicate announce", "hash", fmt.Sprintf("%x", announceHash[:8]))
|
debug.Log(debug.DEBUG_ALL, "Ignoring duplicate announce", "hash", fmt.Sprintf("%x", announceHash[:common.EIGHT]))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
t.seenAnnounces[hashStr] = true
|
t.seenAnnounces[hashStr] = true
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
|
||||||
// Don't forward if max hops reached
|
// Don't forward if max hops reached
|
||||||
if data[0] >= MAX_HOPS {
|
if data[common.ZERO] >= MAX_HOPS {
|
||||||
debug.Log(debug.DEBUG_ALL, "Announce exceeded max hops", "hops", data[0])
|
debug.Log(debug.DEBUG_ALL, "Announce exceeded max hops", "hops", data[common.ZERO])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,23 +798,23 @@ func SendAnnounce(packet []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) HandlePacket(data []byte, iface common.NetworkInterface) {
|
func (t *Transport) HandlePacket(data []byte, iface common.NetworkInterface) {
|
||||||
if len(data) < 2 {
|
if len(data) < common.TWO {
|
||||||
debug.Log(debug.DEBUG_INFO, "Dropping packet: insufficient length", "bytes", len(data))
|
debug.Log(debug.DEBUG_INFO, "Dropping packet: insufficient length", common.STR_BYTES, len(data))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
headerByte := data[0]
|
headerByte := data[common.ZERO]
|
||||||
packetType := headerByte & 0x03
|
packetType := headerByte & common.HEX_0x03
|
||||||
headerType := (headerByte & 0x40) >> 6
|
headerType := (headerByte & 0x40) >> common.SIX
|
||||||
contextFlag := (headerByte & 0x20) >> 5
|
contextFlag := (headerByte & 0x20) >> common.FIVE
|
||||||
propType := (headerByte & 0x10) >> 4
|
propType := (headerByte & 0x10) >> common.FOUR
|
||||||
destType := (headerByte & 0x0C) >> 2
|
destType := (headerByte & 0x0C) >> common.TWO
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_INFO, "TRANSPORT: Packet received", "type", fmt.Sprintf("0x%02x", packetType), "header", headerType, "context", contextFlag, "propType", propType, "destType", destType, "size", len(data))
|
debug.Log(debug.DEBUG_INFO, "TRANSPORT: Packet received", "type", fmt.Sprintf(common.STR_FMT_HEX, packetType), "header", headerType, "context", contextFlag, "propType", propType, "destType", destType, "size", len(data))
|
||||||
debug.Log(debug.DEBUG_TRACE, "Interface and raw header", "name", iface.GetName(), "header", fmt.Sprintf("0x%02x", headerByte))
|
debug.Log(debug.DEBUG_TRACE, "Interface and raw header", "name", iface.GetName(), "header", fmt.Sprintf(common.STR_FMT_HEX, headerByte))
|
||||||
|
|
||||||
if len(data) == 67 {
|
if len(data) == common.SIXTY_SEVEN {
|
||||||
debug.Log(debug.DEBUG_ERROR, "67-byte packet detected", "header", fmt.Sprintf("0x%02x", headerByte), "packet_type_bits", fmt.Sprintf("0x%02x", packetType), "first_32_bytes", fmt.Sprintf("%x", data[:32]))
|
debug.Log(debug.DEBUG_ERROR, "67-byte packet detected", "header", fmt.Sprintf(common.STR_FMT_HEX, headerByte), "packet_type_bits", fmt.Sprintf(common.STR_FMT_HEX, packetType), "first_32_bytes", fmt.Sprintf("%x", data[:common.SIZE_32]))
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcpIface, ok := iface.(*interfaces.TCPClientInterface); ok {
|
if tcpIface, ok := iface.(*interfaces.TCPClientInterface); ok {
|
||||||
@@ -830,66 +830,66 @@ func (t *Transport) HandlePacket(data []byte, iface common.NetworkInterface) {
|
|||||||
}
|
}
|
||||||
case PACKET_TYPE_LINK:
|
case PACKET_TYPE_LINK:
|
||||||
debug.Log(debug.DEBUG_ERROR, "Processing link packet (type=0x02)", "packet_size", len(data))
|
debug.Log(debug.DEBUG_ERROR, "Processing link packet (type=0x02)", "packet_size", len(data))
|
||||||
t.handleLinkPacket(data[1:], iface, PACKET_TYPE_LINK)
|
t.handleLinkPacket(data[common.ONE:], iface, PACKET_TYPE_LINK)
|
||||||
case packet.PacketTypeProof:
|
case packet.PacketTypeProof:
|
||||||
debug.Log(debug.DEBUG_VERBOSE, "Processing proof packet")
|
debug.Log(debug.DEBUG_VERBOSE, "Processing proof packet")
|
||||||
fullData := append([]byte{packet.PacketTypeProof}, data[1:]...)
|
fullData := append([]byte{packet.PacketTypeProof}, data[common.ONE:]...)
|
||||||
pkt := &packet.Packet{Raw: fullData}
|
pkt := &packet.Packet{Raw: fullData}
|
||||||
if err := pkt.Unpack(); err != nil {
|
if err := pkt.Unpack(); err != nil {
|
||||||
debug.Log(debug.DEBUG_INFO, "Failed to unpack proof packet", "error", err)
|
debug.Log(debug.DEBUG_INFO, "Failed to unpack proof packet", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.handleProofPacket(pkt, iface)
|
t.handleProofPacket(pkt, iface)
|
||||||
case 0x00:
|
case common.ZERO:
|
||||||
// Data packets addressed to link destinations carry link traffic
|
// Data packets addressed to link destinations carry link traffic
|
||||||
if destType == DEST_TYPE_LINK {
|
if destType == DEST_TYPE_LINK {
|
||||||
debug.Log(debug.DEBUG_ERROR, "Processing link data packet (dest_type=3)", "packet_size", len(data))
|
debug.Log(debug.DEBUG_ERROR, "Processing link data packet (dest_type=3)", "packet_size", len(data))
|
||||||
t.handleLinkPacket(data[1:], iface, 0x00)
|
t.handleLinkPacket(data[common.ONE:], iface, common.ZERO)
|
||||||
} else {
|
} else {
|
||||||
debug.Log(debug.DEBUG_ERROR, "Processing data packet (type 0x00)", "packet_size", len(data), "dest_type", destType, "header_type", headerType)
|
debug.Log(debug.DEBUG_ERROR, "Processing data packet (type 0x00)", "packet_size", len(data), "dest_type", destType, "header_type", headerType)
|
||||||
t.handleTransportPacket(data[1:], iface)
|
t.handleTransportPacket(data[common.ONE:], iface)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
debug.Log(debug.DEBUG_INFO, "Unknown packet type", "type", fmt.Sprintf("0x%02x", packetType), "source", iface.GetName())
|
debug.Log(debug.DEBUG_INFO, "Unknown packet type", "type", fmt.Sprintf(common.STR_FMT_HEX, packetType), "source", iface.GetName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) handleAnnouncePacket(data []byte, iface common.NetworkInterface) error {
|
func (t *Transport) handleAnnouncePacket(data []byte, iface common.NetworkInterface) error {
|
||||||
debug.Log(debug.DEBUG_INFO, "Processing announce packet", "length", len(data))
|
debug.Log(debug.DEBUG_INFO, "Processing announce packet", "length", len(data))
|
||||||
if len(data) < 2 {
|
if len(data) < common.TWO {
|
||||||
return fmt.Errorf("packet too small for header")
|
return fmt.Errorf("packet too small for header")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse header bytes according to RNS spec
|
// Parse header bytes according to RNS spec
|
||||||
headerByte1 := data[0]
|
headerByte1 := data[common.ZERO]
|
||||||
hopCount := data[1]
|
hopCount := data[common.ONE]
|
||||||
|
|
||||||
// Extract header fields
|
// Extract header fields
|
||||||
ifacFlag := (headerByte1 & 0x80) >> 7 // IFAC flag in highest bit
|
ifacFlag := (headerByte1 & 0x80) >> common.SEVEN // IFAC flag in highest bit
|
||||||
headerType := (headerByte1 & 0x40) >> 6 // Header type in next bit
|
headerType := (headerByte1 & 0x40) >> common.SIX // Header type in next bit
|
||||||
contextFlag := (headerByte1 & 0x20) >> 5 // Context flag
|
contextFlag := (headerByte1 & 0x20) >> common.FIVE // Context flag
|
||||||
propType := (headerByte1 & 0x10) >> 4 // Propagation type
|
propType := (headerByte1 & 0x10) >> common.FOUR // Propagation type
|
||||||
destType := (headerByte1 & 0x0C) >> 2 // Destination type in next 2 bits
|
destType := (headerByte1 & 0x0C) >> common.TWO // Destination type in next 2 bits
|
||||||
packetType := headerByte1 & 0x03 // Packet type in lowest 2 bits
|
packetType := headerByte1 & common.HEX_0x03 // Packet type in lowest 2 bits
|
||||||
|
|
||||||
debug.Log(debug.DEBUG_TRACE, "Announce header", "ifac", ifacFlag, "headerType", headerType, "context", contextFlag, "propType", propType, "destType", destType, "packetType", packetType)
|
debug.Log(debug.DEBUG_TRACE, "Announce header", "ifac", ifacFlag, "headerType", headerType, "context", contextFlag, "propType", propType, "destType", destType, "packetType", packetType)
|
||||||
|
|
||||||
// Skip IFAC code if present
|
// Skip IFAC code if present
|
||||||
startIdx := 2
|
startIdx := common.TWO
|
||||||
if ifacFlag == 1 {
|
if ifacFlag == common.ONE {
|
||||||
startIdx++ // For now assume 1 byte IFAC code
|
startIdx++ // For now assume 1 byte IFAC code
|
||||||
}
|
}
|
||||||
|
|
||||||
// Announce packets use HEADER_TYPE_1 (single address field)
|
// Announce packets use HEADER_TYPE_1 (single address field)
|
||||||
// Calculate address field size
|
// Calculate address field size
|
||||||
addrSize := 16 // Always 16 bytes for HEADER_TYPE_1
|
addrSize := common.SIZE_16 // Always 16 bytes for HEADER_TYPE_1
|
||||||
if headerType == 1 {
|
if headerType == common.ONE {
|
||||||
// HEADER_TYPE_2 has two address fields
|
// HEADER_TYPE_2 has two address fields
|
||||||
addrSize = 32
|
addrSize = common.SIZE_32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate minimum packet size
|
// Validate minimum packet size
|
||||||
minSize := startIdx + addrSize + 1 // Header + address(es) + context
|
minSize := startIdx + addrSize + common.ONE // Header + address(es) + context
|
||||||
if len(data) < minSize {
|
if len(data) < minSize {
|
||||||
return fmt.Errorf("packet too small: %d bytes", len(data))
|
return fmt.Errorf("packet too small: %d bytes", len(data))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user