// Package mesh implements peer-to-peer mesh networking package mesh import ( "fmt" "net" "sync" "time" "veilith/transport" ) // MeshTransport implements peer-to-peer mesh networking type MeshTransport struct { peers map[string]*Peer // address -> peer mu sync.RWMutex listener net.Listener localAddr string closed bool discoveryInterval time.Duration } // Peer represents a mesh network peer type Peer struct { Address string PublicKey string LastSeen time.Time Conn net.Conn IsRelay bool // Can this peer relay messages? } // NewMeshTransport creates a new mesh transport func NewMeshTransport() *MeshTransport { return &MeshTransport{ peers: make(map[string]*Peer), discoveryInterval: 30 * time.Second, } } // Connect connects to a mesh peer func (m *MeshTransport) Connect(address string) (net.Conn, error) { m.mu.Lock() defer m.mu.Unlock() if m.closed { return nil, fmt.Errorf("mesh transport is closed") } // Check if already connected if peer, exists := m.peers[address]; exists { if peer.Conn != nil { peer.LastSeen = time.Now() return peer.Conn, nil } } // Establish new connection conn, err := net.DialTimeout("tcp", address, 10*time.Second) if err != nil { return nil, fmt.Errorf("failed to connect to peer %s: %w", address, err) } // Add peer m.peers[address] = &Peer{ Address: address, LastSeen: time.Now(), Conn: conn, } return conn, nil } // Listen starts listening for mesh connections func (m *MeshTransport) Listen(address string) (net.Listener, error) { m.mu.Lock() defer m.mu.Unlock() if m.closed { return nil, fmt.Errorf("mesh transport is closed") } if m.listener != nil { return nil, fmt.Errorf("already listening on %s", m.localAddr) } listener, err := net.Listen("tcp", address) if err != nil { return nil, fmt.Errorf("failed to listen on %s: %w", address, err) } m.listener = listener m.localAddr = address // Start peer discovery in background go m.startPeerDiscovery() return listener, nil } // Type returns the transport type func (m *MeshTransport) Type() transport.TransportType { return transport.TransportMesh } // Close closes the mesh transport func (m *MeshTransport) Close() error { m.mu.Lock() defer m.mu.Unlock() if m.closed { return nil } m.closed = true // Close listener if m.listener != nil { if err := m.listener.Close(); err != nil { return fmt.Errorf("failed to close listener: %w", err) } m.listener = nil } // Close all peer connections for addr, peer := range m.peers { if peer.Conn != nil { peer.Conn.Close() } delete(m.peers, addr) } return nil } // AddPeer manually adds a peer to the mesh func (m *MeshTransport) AddPeer(address string) error { m.mu.Lock() defer m.mu.Unlock() if m.closed { return fmt.Errorf("mesh transport is closed") } if _, exists := m.peers[address]; exists { return fmt.Errorf("peer already exists: %s", address) } m.peers[address] = &Peer{ Address: address, LastSeen: time.Now(), } return nil } // RemovePeer removes a peer from the mesh func (m *MeshTransport) RemovePeer(address string) error { m.mu.Lock() defer m.mu.Unlock() peer, exists := m.peers[address] if !exists { return fmt.Errorf("peer not found: %s", address) } if peer.Conn != nil { peer.Conn.Close() } delete(m.peers, address) return nil } // GetPeers returns all known peers func (m *MeshTransport) GetPeers() []*Peer { m.mu.RLock() defer m.mu.RUnlock() peers := make([]*Peer, 0, len(m.peers)) for _, peer := range m.peers { peers = append(peers, peer) } return peers } // GetPeerCount returns the number of known peers func (m *MeshTransport) GetPeerCount() int { m.mu.RLock() defer m.mu.RUnlock() return len(m.peers) } // startPeerDiscovery periodically discovers new peers func (m *MeshTransport) startPeerDiscovery() { ticker := time.NewTicker(m.discoveryInterval) defer ticker.Stop() for { select { case <-ticker.C: m.mu.RLock() if m.closed { m.mu.RUnlock() return } m.mu.RUnlock() // Clean up stale peers m.cleanupStalePeers(5 * time.Minute) // In a real implementation, you would: // 1. Query known peers for their peer lists // 2. Attempt connections to new peers // 3. Exchange routing tables } } } // cleanupStalePeers removes peers that haven't been seen recently func (m *MeshTransport) cleanupStalePeers(maxAge time.Duration) { m.mu.Lock() defer m.mu.Unlock() now := time.Now() for addr, peer := range m.peers { if now.Sub(peer.LastSeen) > maxAge { if peer.Conn != nil { peer.Conn.Close() } delete(m.peers, addr) } } } // SetDiscoveryInterval sets the peer discovery interval func (m *MeshTransport) SetDiscoveryInterval(interval time.Duration) { m.mu.Lock() defer m.mu.Unlock() m.discoveryInterval = interval } // String returns a string representation func (m *MeshTransport) String() string { m.mu.RLock() defer m.mu.RUnlock() return fmt.Sprintf("MeshTransport(peers=%d, listening=%s, closed=%v)", len(m.peers), m.localAddr, m.closed) }