0.2.5
This commit is contained in:
57
To-Do
57
To-Do
@@ -89,12 +89,22 @@ Basic Features
|
||||
[✓] Connection management
|
||||
[✓] Packet framing
|
||||
[✓] Transport integration
|
||||
[ ] Auto Interface support
|
||||
[ ] Interface modes (full, gateway, ap, roaming, boundary)
|
||||
[ ] Interface bandwidth control
|
||||
[ ] Interface statistics
|
||||
[ ] Interface health monitoring
|
||||
[ ] Interface reconnection logic
|
||||
[ ] Multi-interface routing
|
||||
[ ] Interface priority handling
|
||||
|
||||
[✓] Announce System
|
||||
[✓] Announce creation
|
||||
[✓] Announce propagation
|
||||
[✓] Path requests
|
||||
[✓] Announce validation
|
||||
[ ] Announce rate limiting
|
||||
[ ] Interface-specific announce rules
|
||||
|
||||
[✓] Resource Management
|
||||
[✓] Resource tracking
|
||||
@@ -109,22 +119,61 @@ Basic Features
|
||||
[✓] Message sending/receiving
|
||||
[✓] Identity management
|
||||
|
||||
Next Immediate Tasks:
|
||||
1. [✓] Fix import cycles by creating common package
|
||||
2. [✓] Complete NetworkInterface implementation
|
||||
3. [✓] Add comprehensive interface tests
|
||||
4. [✓] Implement connection retry logic
|
||||
5. [✓] Add client reconnection handling
|
||||
6. [ ] Implement Interface discovery
|
||||
- [ ] Auto interface detection
|
||||
- [ ] Interface capability detection
|
||||
- [ ] Interface mode configuration
|
||||
- [ ] Interface bandwidth detection
|
||||
|
||||
7. [ ] Test network layer integration end-to-end
|
||||
- [ ] Multi-interface testing
|
||||
- [ ] Interface failover testing
|
||||
- [ ] Mode-specific behavior testing
|
||||
|
||||
8. [ ] Add error handling for network failures
|
||||
- [ ] Interface reconnection logic
|
||||
- [ ] Packet retry mechanisms
|
||||
- [ ] Interface fallback handling
|
||||
|
||||
9. [ ] Implement interface auto-configuration
|
||||
- [ ] IPv6 link-local detection
|
||||
- [ ] Interface mode auto-selection
|
||||
- [ ] MTU discovery
|
||||
- [ ] Bandwidth detection
|
||||
|
||||
10. [ ] Add metrics collection for interfaces
|
||||
- [ ] Bandwidth usage tracking
|
||||
- [ ] Packet success/failure rates
|
||||
- [ ] Latency measurements
|
||||
- [ ] Interface health metrics
|
||||
|
||||
11. [ ] Implement client-side path caching
|
||||
12. [ ] Add support for additional transport types
|
||||
13. [ ] Implement perfect forward secrecy
|
||||
14. [ ] Add post-quantum cryptographic primitives
|
||||
14. [ ] Add post-quantum cryptographic primitives (Future)
|
||||
15. [ ] Implement secure key rotation
|
||||
16. [ ] Add support for encrypted storage of identities
|
||||
17. [ ] Implement secure memory handling
|
||||
18. [ ] Add support for hardware security modules
|
||||
18. [ ] Add support for hardware security modules (HSM)
|
||||
19. [ ] Implement interface modes
|
||||
- [ ] Full mode implementation
|
||||
- [ ] Gateway mode implementation
|
||||
- [ ] Access point mode implementation
|
||||
- [ ] Roaming mode implementation
|
||||
- [ ] Boundary mode implementation
|
||||
|
||||
20. [ ] Add interface bandwidth management
|
||||
- [ ] Rate limiting
|
||||
- [ ] QoS implementation
|
||||
- [ ] Priority queuing
|
||||
- [ ] Congestion control
|
||||
|
||||
21. [ ] Implement interface discovery system
|
||||
- [ ] Auto interface detection
|
||||
- [ ] Interface capability probing
|
||||
- [ ] Dynamic interface configuration
|
||||
- [ ] Interface health checking
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/Sudo-Ivan/reticulum-go/internal/config"
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/announce"
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/common"
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/destination"
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/identity"
|
||||
@@ -156,25 +157,26 @@ func (c *Client) handleAnnounce(data []byte) {
|
||||
func (c *Client) sendAnnounce() {
|
||||
announceData := make([]byte, 0)
|
||||
|
||||
// Packet type (1 byte)
|
||||
announceData = append(announceData, 0x04)
|
||||
// Create header
|
||||
header := announce.CreateHeader(
|
||||
announce.IFAC_NONE,
|
||||
announce.HEADER_TYPE_1,
|
||||
0x00,
|
||||
announce.PROP_TYPE_BROADCAST,
|
||||
announce.DEST_TYPE_SINGLE,
|
||||
announce.PACKET_TYPE_ANNOUNCE,
|
||||
0x00,
|
||||
)
|
||||
announceData = append(announceData, header...)
|
||||
|
||||
// Destination hash (16 bytes)
|
||||
destHash := identity.TruncatedHash(c.identity.GetPublicKey())
|
||||
announceData = append(announceData, destHash...)
|
||||
// Add destination hash (16 bytes truncated)
|
||||
identityHash := c.identity.Hash()
|
||||
announceData = append(announceData, identityHash...)
|
||||
|
||||
// Timestamp (8 bytes)
|
||||
timeBytes := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(timeBytes, uint64(time.Now().Unix()))
|
||||
announceData = append(announceData, timeBytes...)
|
||||
// Add context byte
|
||||
announceData = append(announceData, announce.ANNOUNCE_IDENTITY)
|
||||
|
||||
// Hops (1 byte)
|
||||
announceData = append(announceData, 0x00)
|
||||
|
||||
// Flags (1 byte)
|
||||
announceData = append(announceData, 0x00)
|
||||
|
||||
// Public key
|
||||
// Add public key
|
||||
announceData = append(announceData, c.identity.GetPublicKey()...)
|
||||
|
||||
// App data with length prefix
|
||||
@@ -184,21 +186,26 @@ func (c *Client) sendAnnounce() {
|
||||
announceData = append(announceData, lenBytes...)
|
||||
announceData = append(announceData, appData...)
|
||||
|
||||
// Sign the announce data
|
||||
signData := append(destHash, c.identity.GetPublicKey()...)
|
||||
// Add signature
|
||||
signData := append(identityHash, c.identity.GetPublicKey()...)
|
||||
signData = append(signData, appData...)
|
||||
signature := c.identity.Sign(signData)
|
||||
announceData = append(announceData, signature...)
|
||||
|
||||
log.Printf("Sending announce for identity: %s", c.identity.Hex())
|
||||
log.Printf("Announce packet length: %d bytes", len(announceData))
|
||||
log.Printf("Announce packet hex: %x", announceData)
|
||||
log.Printf("Sending announce:")
|
||||
log.Printf(" Identity Hash: %x", identityHash)
|
||||
log.Printf(" Packet Length: %d bytes", len(announceData))
|
||||
log.Printf(" Full Packet: %x", announceData)
|
||||
|
||||
// Send on all interfaces
|
||||
for _, iface := range c.interfaces {
|
||||
log.Printf("Sending on interface %s (%s):", iface.GetName(), iface.GetType())
|
||||
log.Printf(" MTU: %d bytes", iface.GetMTU())
|
||||
|
||||
if err := iface.Send(announceData, ""); err != nil {
|
||||
log.Printf("Failed to send announce on interface %s: %v", iface.GetName(), err)
|
||||
log.Printf(" Failed to send: %v", err)
|
||||
} else {
|
||||
log.Printf("Sent announce on interface %s", iface.GetName())
|
||||
log.Printf(" Successfully sent announce")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,46 @@ package announce
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/identity"
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/common"
|
||||
"github.com/Sudo-Ivan/reticulum-go/pkg/identity"
|
||||
)
|
||||
|
||||
const (
|
||||
// Packet Types
|
||||
PACKET_TYPE_DATA = 0x00
|
||||
PACKET_TYPE_ANNOUNCE = 0x01
|
||||
PACKET_TYPE_LINK = 0x02
|
||||
PACKET_TYPE_PROOF = 0x03
|
||||
|
||||
// Announce Types
|
||||
ANNOUNCE_NONE = 0x00
|
||||
ANNOUNCE_PATH = 0x01
|
||||
ANNOUNCE_IDENTITY = 0x02
|
||||
|
||||
// Header Types
|
||||
HEADER_TYPE_1 = 0x00 // One address field
|
||||
HEADER_TYPE_2 = 0x01 // Two address fields
|
||||
|
||||
// Propagation Types
|
||||
PROP_TYPE_BROADCAST = 0x00
|
||||
PROP_TYPE_TRANSPORT = 0x01
|
||||
|
||||
// Destination Types
|
||||
DEST_TYPE_SINGLE = 0x00
|
||||
DEST_TYPE_GROUP = 0x01
|
||||
DEST_TYPE_PLAIN = 0x02
|
||||
DEST_TYPE_LINK = 0x03
|
||||
|
||||
// IFAC Flag
|
||||
IFAC_NONE = 0x00
|
||||
IFAC_AUTH = 0x80 // Most significant bit
|
||||
|
||||
MAX_HOPS = 128
|
||||
PROPAGATION_RATE = 0.02 // 2% of interface bandwidth
|
||||
RETRY_INTERVAL = 300 // 5 minutes
|
||||
@@ -30,14 +57,14 @@ type AnnounceHandler interface {
|
||||
type Announce struct {
|
||||
mutex sync.RWMutex
|
||||
destinationHash []byte
|
||||
identity *identity.Identity
|
||||
appData []byte
|
||||
hops uint8
|
||||
timestamp int64
|
||||
signature []byte
|
||||
pathResponse bool
|
||||
retries int
|
||||
handlers []AnnounceHandler
|
||||
identity *identity.Identity
|
||||
appData []byte
|
||||
hops uint8
|
||||
timestamp int64
|
||||
signature []byte
|
||||
pathResponse bool
|
||||
retries int
|
||||
handlers []AnnounceHandler
|
||||
}
|
||||
|
||||
func New(dest *identity.Identity, appData []byte, pathResponse bool) (*Announce, error) {
|
||||
@@ -64,32 +91,24 @@ func New(dest *identity.Identity, appData []byte, pathResponse bool) (*Announce,
|
||||
}
|
||||
|
||||
func (a *Announce) Propagate(interfaces []common.NetworkInterface) error {
|
||||
a.mutex.Lock()
|
||||
defer a.mutex.Unlock()
|
||||
packet := a.CreatePacket()
|
||||
|
||||
if a.hops >= MAX_HOPS {
|
||||
return errors.New("maximum hop count reached")
|
||||
}
|
||||
log.Printf("Propagating announce:")
|
||||
log.Printf(" Destination Hash: %x", a.destinationHash)
|
||||
log.Printf(" Public Key: %x", a.identity.GetPublicKey())
|
||||
log.Printf(" App Data: %s", string(a.appData))
|
||||
log.Printf(" Packet Size: %d bytes", len(packet))
|
||||
log.Printf(" Full Packet: %x", packet)
|
||||
|
||||
// Increment hop count
|
||||
a.hops++
|
||||
|
||||
// Create announce packet
|
||||
packet := make([]byte, 0)
|
||||
packet = append(packet, a.destinationHash...)
|
||||
packet = append(packet, a.identity.GetPublicKey()...)
|
||||
packet = append(packet, byte(a.hops))
|
||||
|
||||
if a.appData != nil {
|
||||
packet = append(packet, a.appData...)
|
||||
}
|
||||
|
||||
packet = append(packet, a.signature...)
|
||||
|
||||
// Propagate to all interfaces
|
||||
// Propagate to interfaces
|
||||
for _, iface := range interfaces {
|
||||
log.Printf("Propagating on interface %s (%s):", iface.GetName(), iface.GetType())
|
||||
log.Printf(" MTU: %d bytes", iface.GetMTU())
|
||||
|
||||
if err := iface.Send(packet, ""); err != nil {
|
||||
return err
|
||||
log.Printf(" Failed to propagate: %v", err)
|
||||
} else {
|
||||
log.Printf(" Successfully propagated")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,4 +194,56 @@ func (a *Announce) RequestPath(destHash []byte, onInterface common.NetworkInterf
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// CreateHeader creates a Reticulum packet header according to spec
|
||||
func CreateHeader(ifacFlag byte, headerType byte, contextFlag byte, propType byte, destType byte, packetType byte, hops byte) []byte {
|
||||
header := make([]byte, 2)
|
||||
|
||||
// First byte: [IFAC Flag], [Header Type], [Context Flag], [Propagation Type], [Destination Type] and [Packet Type]
|
||||
header[0] = ifacFlag | (headerType << 6) | (contextFlag << 5) |
|
||||
(propType << 4) | (destType << 2) | packetType
|
||||
|
||||
// Second byte: Number of hops
|
||||
header[1] = hops
|
||||
|
||||
return header
|
||||
}
|
||||
|
||||
func (a *Announce) CreatePacket() []byte {
|
||||
packet := make([]byte, 0)
|
||||
|
||||
// Create header for announce packet
|
||||
header := CreateHeader(
|
||||
IFAC_NONE, // No interface authentication
|
||||
HEADER_TYPE_1, // One address field
|
||||
0x00, // Context flag unset
|
||||
PROP_TYPE_BROADCAST, // Broadcast propagation
|
||||
DEST_TYPE_SINGLE, // Single destination
|
||||
PACKET_TYPE_ANNOUNCE, // Announce packet type
|
||||
byte(a.hops), // Current hop count
|
||||
)
|
||||
packet = append(packet, header...)
|
||||
|
||||
// Add destination hash (16 bytes)
|
||||
packet = append(packet, a.destinationHash...)
|
||||
|
||||
// Add context byte
|
||||
packet = append(packet, ANNOUNCE_IDENTITY)
|
||||
|
||||
// Add public key
|
||||
packet = append(packet, a.identity.GetPublicKey()...)
|
||||
|
||||
// Add app data with length prefix
|
||||
if a.appData != nil {
|
||||
lenBytes := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(lenBytes, uint16(len(a.appData)))
|
||||
packet = append(packet, lenBytes...)
|
||||
packet = append(packet, a.appData...)
|
||||
}
|
||||
|
||||
// Add signature
|
||||
packet = append(packet, a.signature...)
|
||||
|
||||
return packet
|
||||
}
|
||||
|
||||
@@ -183,7 +183,8 @@ func (i *Identity) Encrypt(plaintext []byte, ratchet []byte) ([]byte, error) {
|
||||
func (i *Identity) Hash() []byte {
|
||||
h := sha256.New()
|
||||
h.Write(i.GetPublicKey())
|
||||
return h.Sum(nil)
|
||||
fullHash := h.Sum(nil)
|
||||
return fullHash[:TruncatedHashLen/8]
|
||||
}
|
||||
|
||||
func TruncatedHash(data []byte) []byte {
|
||||
@@ -200,6 +201,10 @@ func GetRandomHash() []byte {
|
||||
}
|
||||
|
||||
func Remember(packetHash, destHash []byte, publicKey []byte, appData []byte) {
|
||||
if len(destHash) > TruncatedHashLen/8 {
|
||||
destHash = destHash[:TruncatedHashLen/8]
|
||||
}
|
||||
|
||||
knownDestinations[string(destHash)] = []interface{}{
|
||||
time.Now().Unix(),
|
||||
packetHash,
|
||||
@@ -213,6 +218,10 @@ func ValidateAnnounce(packet []byte, destHash []byte, publicKey []byte, signatur
|
||||
return false
|
||||
}
|
||||
|
||||
if len(destHash) > TruncatedHashLen/8 {
|
||||
destHash = destHash[:TruncatedHashLen/8]
|
||||
}
|
||||
|
||||
announced := &Identity{}
|
||||
announced.publicKey = publicKey[:KeySize/16]
|
||||
announced.verificationKey = publicKey[KeySize/16:]
|
||||
|
||||
Reference in New Issue
Block a user