feat: per-network share directories + isolation test
Each network now carries its own share dir, set at join_network time via optional share_dir field or updated live with set_share_dir. The global -share-dir daemon flag becomes a fallback default. - proto: add ShareDir/DownloadDir to NetworkInfo and IpcMessage - netmgr: Join accepts shareDir override; SetShareDir updates live - ipc: wire join_network share_dir and set_share_dir command - daemon: remove -share-dir from auto-join path (pass "" for default) - test-network.sh: per-network join with share_dir; isolation verification section confirms alice/friends and alice/work share dirs are independent - test-tui.sh: join_network with share_dir; peer IDs resolved after join All tests pass: YAW/2.1 FS, share isolation, file transfer, persistence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ type Config struct {
|
||||
MasterIdentity *crypto.Identity
|
||||
StoreDir string // base directory for per-network SQLite files
|
||||
AnchorURL string // WebSocket anchor URL used for all networks
|
||||
ShareDir string // shared file directory (global for now; per-network in future)
|
||||
ShareDir string // default share directory; overridden per network via Join or SetShareDir
|
||||
}
|
||||
|
||||
// Network is a single joined network context.
|
||||
@@ -41,6 +41,9 @@ type Network struct {
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// ShareDir returns the share directory for this network (from the mesh).
|
||||
func (n *Network) ShareDir() string { return n.Mesh.ShareDir }
|
||||
|
||||
// Manager owns all joined networks and fans out their events to IPC subscribers.
|
||||
type Manager struct {
|
||||
cfg Config
|
||||
@@ -63,7 +66,8 @@ func New(cfg Config) *Manager {
|
||||
|
||||
// Join creates or rejoins a named network. Returns the network ID.
|
||||
// If the network is already joined the existing ID is returned immediately.
|
||||
func (mgr *Manager) Join(name string) (string, error) {
|
||||
// shareDir overrides the global default for this network; pass "" to use the default.
|
||||
func (mgr *Manager) Join(name, shareDir string) (string, error) {
|
||||
netHash := hashNetName(name)
|
||||
netID := netHash[:8]
|
||||
|
||||
@@ -89,7 +93,10 @@ func (mgr *Manager) Join(name string) (string, error) {
|
||||
}
|
||||
|
||||
m := mesh.New(derived, st)
|
||||
if mgr.cfg.ShareDir != "" {
|
||||
// Per-network share dir takes precedence over the global default.
|
||||
if shareDir != "" {
|
||||
m.ShareDir = shareDir
|
||||
} else if mgr.cfg.ShareDir != "" {
|
||||
m.ShareDir = mgr.cfg.ShareDir
|
||||
}
|
||||
m.DownloadDir = filepath.Join(mgr.cfg.StoreDir, "downloads-"+netID_full)
|
||||
@@ -130,10 +137,11 @@ func (mgr *Manager) Join(name string) (string, error) {
|
||||
}
|
||||
|
||||
mgr.emit(proto.IpcMessage{
|
||||
Type: proto.EvtNetworkJoined,
|
||||
NetworkID: netID,
|
||||
Type: proto.EvtNetworkJoined,
|
||||
NetworkID: netID,
|
||||
NetworkName: name,
|
||||
LocalPeer: peerPtr(derived.PeerInfo()),
|
||||
LocalPeer: peerPtr(derived.PeerInfo()),
|
||||
ShareDir: m.ShareDir,
|
||||
})
|
||||
|
||||
return netID, nil
|
||||
@@ -159,6 +167,20 @@ func (mgr *Manager) Leave(netID string) {
|
||||
mgr.emit(proto.IpcMessage{Type: proto.EvtNetworkLeft, NetworkID: netID})
|
||||
}
|
||||
|
||||
// SetShareDir updates the share directory for an already-joined network.
|
||||
// Changes take effect immediately for subsequent file-list requests and offers.
|
||||
func (mgr *Manager) SetShareDir(netID, path string) bool {
|
||||
mgr.mu.RLock()
|
||||
net, ok := mgr.networks[netID]
|
||||
mgr.mu.RUnlock()
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
net.Mesh.ShareDir = path
|
||||
log.Printf("netmgr: share dir for %q set to %q", net.Name, path)
|
||||
return true
|
||||
}
|
||||
|
||||
// LeaveAll leaves every joined network.
|
||||
func (mgr *Manager) LeaveAll() {
|
||||
mgr.mu.RLock()
|
||||
|
||||
Reference in New Issue
Block a user