@ -52,7 +52,8 @@ type FileSystemForRemote struct {
// mu guards the below values. Acquire a write lock before updating any of
// mu guards the below values. Acquire a write lock before updating any of
// them, acquire a read lock before reading any of them.
// them, acquire a read lock before reading any of them.
mu sync . RWMutex
mu sync . RWMutex
fileServerAddr string
// fileServerTokenAndAddr is the secretToken|fileserverAddress
fileServerTokenAndAddr string
shares [ ] * drive . Share
shares [ ] * drive . Share
children map [ string ] * compositedav . Child
children map [ string ] * compositedav . Child
userServers map [ string ] * userServer
userServers map [ string ] * userServer
@ -61,7 +62,7 @@ type FileSystemForRemote struct {
// SetFileServerAddr implements drive.FileSystemForRemote.
// SetFileServerAddr implements drive.FileSystemForRemote.
func ( s * FileSystemForRemote ) SetFileServerAddr ( addr string ) {
func ( s * FileSystemForRemote ) SetFileServerAddr ( addr string ) {
s . mu . Lock ( )
s . mu . Lock ( )
s . fileServer Addr = addr
s . fileServer TokenAnd Addr = addr
s . mu . Unlock ( )
s . mu . Unlock ( )
}
}
@ -113,25 +114,7 @@ func (s *FileSystemForRemote) SetShares(shares []*drive.Share) {
}
}
func ( s * FileSystemForRemote ) buildChild ( share * drive . Share ) * compositedav . Child {
func ( s * FileSystemForRemote ) buildChild ( share * drive . Share ) * compositedav . Child {
return & compositedav . Child {
getTokenAndAddr := func ( shareName string ) ( string , string , error ) {
Child : & dirfs . Child {
Name : share . Name ,
} ,
BaseURL : fmt . Sprintf ( "http://%v/%v" , hex . EncodeToString ( [ ] byte ( share . Name ) ) , url . PathEscape ( share . Name ) ) ,
Transport : & http . Transport {
Dial : func ( _ , shareAddr string ) ( net . Conn , error ) {
shareNameHex , _ , err := net . SplitHostPort ( shareAddr )
if err != nil {
return nil , fmt . Errorf ( "unable to parse share address %v: %w" , shareAddr , err )
}
// We had to encode the share name in hex to make sure it's a valid hostname
shareNameBytes , err := hex . DecodeString ( shareNameHex )
if err != nil {
return nil , fmt . Errorf ( "unable to decode share name from host %v: %v" , shareNameHex , err )
}
shareName := string ( shareNameBytes )
s . mu . RLock ( )
s . mu . RLock ( )
var share * drive . Share
var share * drive . Share
i , shareFound := slices . BinarySearchFunc ( s . shares , shareName , func ( s * drive . Share , name string ) int {
i , shareFound := slices . BinarySearchFunc ( s . shares , shareName , func ( s * drive . Share , name string ) int {
@ -141,27 +124,65 @@ func (s *FileSystemForRemote) buildChild(share *drive.Share) *compositedav.Child
share = s . shares [ i ]
share = s . shares [ i ]
}
}
userServers := s . userServers
userServers := s . userServers
fileServer Addr := s . fileServer Addr
fileServer TokenAnd Addr := s . fileServer TokenAnd Addr
s . mu . RUnlock ( )
s . mu . RUnlock ( )
if ! shareFound {
if ! shareFound {
return nil , fmt . Errorf ( "unknown share %v" , shareName )
return "" , "" , fmt . Errorf ( "unknown share %v" , shareName )
}
}
var a ddr string
var tokenAndA ddr string
if ! drive . AllowShareAs ( ) {
if ! drive . AllowShareAs ( ) {
addr = fileServer Addr
tokenAndAddr = fileServerTokenAnd Addr
} else {
} else {
userServer , found := userServers [ share . As ]
userServer , found := userServers [ share . As ]
if found {
if found {
userServer . mu . RLock ( )
userServer . mu . RLock ( )
addr = userServer . a ddr
tokenAndAddr = userServer . tokenAndA ddr
userServer . mu . RUnlock ( )
userServer . mu . RUnlock ( )
}
}
}
}
if addr == "" {
if tokenAndAddr == "" {
return nil , fmt . Errorf ( "unable to determine address for share %v" , shareName )
return "" , "" , fmt . Errorf ( "unable to determine address for share %v" , shareName )
}
parts := strings . Split ( tokenAndAddr , "|" )
if len ( parts ) != 2 {
return "" , "" , fmt . Errorf ( "invalid address for share %v" , shareName )
}
return parts [ 0 ] , parts [ 1 ] , nil
}
return & compositedav . Child {
Child : & dirfs . Child {
Name : share . Name ,
} ,
BaseURL : func ( ) ( string , error ) {
secretToken , _ , err := getTokenAndAddr ( share . Name )
if err != nil {
return "" , err
}
return fmt . Sprintf ( "http://%s/%s/%s" , hex . EncodeToString ( [ ] byte ( share . Name ) ) , secretToken , url . PathEscape ( share . Name ) ) , nil
} ,
Transport : & http . Transport {
Dial : func ( _ , shareAddr string ) ( net . Conn , error ) {
shareNameHex , _ , err := net . SplitHostPort ( shareAddr )
if err != nil {
return nil , fmt . Errorf ( "unable to parse share address %v: %w" , shareAddr , err )
}
// We had to encode the share name in hex to make sure it's a valid hostname
shareNameBytes , err := hex . DecodeString ( shareNameHex )
if err != nil {
return nil , fmt . Errorf ( "unable to decode share name from host %v: %v" , shareNameHex , err )
}
shareName := string ( shareNameBytes )
_ , addr , err := getTokenAndAddr ( shareName )
if err != nil {
return nil , err
}
}
_ , err = netip . ParseAddrPort ( addr )
_ , err = netip . ParseAddrPort ( addr )
@ -255,7 +276,7 @@ type userServer struct {
// them, acquire a read lock before reading any of them.
// them, acquire a read lock before reading any of them.
mu sync . RWMutex
mu sync . RWMutex
cmd * exec . Cmd
cmd * exec . Cmd
addr string
tokenAndAddr string
closed bool
closed bool
}
}
@ -366,7 +387,7 @@ func (s *userServer) run() error {
}
}
} ( )
} ( )
s . mu . Lock ( )
s . mu . Lock ( )
s . a ddr = strings . TrimSpace ( addr )
s . tokenAndA ddr = strings . TrimSpace ( addr )
s . mu . Unlock ( )
s . mu . Unlock ( )
return cmd . Wait ( )
return cmd . Wait ( )
}
}