mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-22 07:30:25 +00:00
add more test cases
This commit is contained in:
parent
ff8fb80e3c
commit
9f61415832
3 changed files with 311 additions and 164 deletions
|
@ -96,50 +96,6 @@ func TestMain(m *testing.M) {
|
||||||
os.Exit(exitCode)
|
os.Exit(exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitTCPListening(address string) {
|
|
||||||
for {
|
|
||||||
conn, err := net.Dial("tcp", address)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("tcp server %v not listening: %v\n", address, err)
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Printf("tcp server %v now listening\n", address)
|
|
||||||
defer conn.Close()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTestUser() dataprovider.User {
|
|
||||||
return dataprovider.User{
|
|
||||||
Username: defaultUsername,
|
|
||||||
Password: defaultPassword,
|
|
||||||
HomeDir: filepath.Join(homeBasePath, defaultUsername),
|
|
||||||
Permissions: defaultPerms,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserAsJSON(t *testing.T, user dataprovider.User) []byte {
|
|
||||||
json, err := json.Marshal(user)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("error get user as json: %v", err)
|
|
||||||
return []byte("{}")
|
|
||||||
}
|
|
||||||
return json
|
|
||||||
}
|
|
||||||
|
|
||||||
func executeRequest(req *http.Request) *httptest.ResponseRecorder {
|
|
||||||
rr := httptest.NewRecorder()
|
|
||||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
|
||||||
return rr
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkResponseCode(t *testing.T, expected, actual int) {
|
|
||||||
if expected != actual {
|
|
||||||
t.Errorf("Expected response code %d. Got %d", expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBasicUserHandling(t *testing.T) {
|
func TestBasicUserHandling(t *testing.T) {
|
||||||
user, err := api.AddUser(getTestUser(), http.StatusOK)
|
user, err := api.AddUser(getTestUser(), http.StatusOK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -669,3 +625,47 @@ func TestMethodNotAllowedMock(t *testing.T) {
|
||||||
rr := executeRequest(req)
|
rr := executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusMethodNotAllowed, rr.Code)
|
checkResponseCode(t, http.StatusMethodNotAllowed, rr.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func waitTCPListening(address string) {
|
||||||
|
for {
|
||||||
|
conn, err := net.Dial("tcp", address)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("tcp server %v not listening: %v\n", address, err)
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("tcp server %v now listening\n", address)
|
||||||
|
defer conn.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestUser() dataprovider.User {
|
||||||
|
return dataprovider.User{
|
||||||
|
Username: defaultUsername,
|
||||||
|
Password: defaultPassword,
|
||||||
|
HomeDir: filepath.Join(homeBasePath, defaultUsername),
|
||||||
|
Permissions: defaultPerms,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserAsJSON(t *testing.T, user dataprovider.User) []byte {
|
||||||
|
json, err := json.Marshal(user)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error get user as json: %v", err)
|
||||||
|
return []byte("{}")
|
||||||
|
}
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeRequest(req *http.Request) *httptest.ResponseRecorder {
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||||
|
return rr
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkResponseCode(t *testing.T, expected, actual int) {
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("Expected response code %d. Got %d", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -185,12 +185,13 @@ func startIdleTimer(maxIdleTime time.Duration) {
|
||||||
go func() {
|
go func() {
|
||||||
for t := range idleConnectionTicker.C {
|
for t := range idleConnectionTicker.C {
|
||||||
logger.Debug(logSender, "idle connections check ticker %v", t)
|
logger.Debug(logSender, "idle connections check ticker %v", t)
|
||||||
checkIdleConnections()
|
CheckIdleConnections()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkIdleConnections() {
|
// CheckIdleConnections disconnects idle clients
|
||||||
|
func CheckIdleConnections() {
|
||||||
mutex.RLock()
|
mutex.RLock()
|
||||||
defer mutex.RUnlock()
|
defer mutex.RUnlock()
|
||||||
for _, c := range openConnections {
|
for _, c := range openConnections {
|
||||||
|
|
|
@ -135,123 +135,6 @@ func TestMain(m *testing.M) {
|
||||||
os.Exit(exitCode)
|
os.Exit(exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitTCPListening(address string) {
|
|
||||||
for {
|
|
||||||
conn, err := net.Dial("tcp", address)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("tcp server %v not listening: %v\n", address, err)
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Printf("tcp server %v now listening\n", address)
|
|
||||||
defer conn.Close()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSftpClient(user dataprovider.User, usePubKey bool) (*sftp.Client, error) {
|
|
||||||
var sftpClient *sftp.Client
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
User: defaultUsername,
|
|
||||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if usePubKey {
|
|
||||||
key, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config.Auth = []ssh.AuthMethod{ssh.PublicKeys(key)}
|
|
||||||
} else {
|
|
||||||
config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
|
|
||||||
}
|
|
||||||
conn, err := ssh.Dial("tcp", sftpServerAddr, config)
|
|
||||||
if err != nil {
|
|
||||||
return sftpClient, err
|
|
||||||
}
|
|
||||||
sftpClient, err = sftp.NewClient(conn)
|
|
||||||
return sftpClient, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTestFile(path string, size int64) error {
|
|
||||||
content := make([]byte, size)
|
|
||||||
_, err := rand.Read(content)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return ioutil.WriteFile(path, content, 0666)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTestUser(usePubKey bool) dataprovider.User {
|
|
||||||
user := dataprovider.User{
|
|
||||||
Username: defaultUsername,
|
|
||||||
Password: defaultPassword,
|
|
||||||
HomeDir: filepath.Join(homeBasePath, defaultUsername),
|
|
||||||
Permissions: allPerms,
|
|
||||||
}
|
|
||||||
if usePubKey {
|
|
||||||
user.PublicKey = testPubKey
|
|
||||||
user.Password = ""
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
|
|
||||||
func sftpUploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) error {
|
|
||||||
srcFile, err := os.Open(localSourcePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer srcFile.Close()
|
|
||||||
destFile, err := client.Create(remoteDestPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer destFile.Close()
|
|
||||||
_, err = io.Copy(destFile, srcFile)
|
|
||||||
if expectedSize > 0 {
|
|
||||||
fi, err := client.Lstat(remoteDestPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if fi.Size() != expectedSize {
|
|
||||||
return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func sftpDownloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) error {
|
|
||||||
downloadDest, err := os.Create(localDestPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer downloadDest.Close()
|
|
||||||
sftpSrcFile, err := client.Open(remoteSourcePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer sftpSrcFile.Close()
|
|
||||||
_, err = io.Copy(downloadDest, sftpSrcFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = downloadDest.Sync()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if expectedSize > 0 {
|
|
||||||
fi, err := downloadDest.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if fi.Size() != expectedSize {
|
|
||||||
return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBasicSFTPHandling(t *testing.T) {
|
func TestBasicSFTPHandling(t *testing.T) {
|
||||||
usePubKey := false
|
usePubKey := false
|
||||||
user, err := api.AddUser(getTestUser(usePubKey), http.StatusOK)
|
user, err := api.AddUser(getTestUser(usePubKey), http.StatusOK)
|
||||||
|
@ -647,7 +530,6 @@ func TestQuotaScan(t *testing.T) {
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
testFileName := "test_file.dat"
|
testFileName := "test_file.dat"
|
||||||
testFilePath := filepath.Join(homeBasePath, testFileName)
|
testFilePath := filepath.Join(homeBasePath, testFileName)
|
||||||
testFileSize := int64(65535)
|
|
||||||
err = createTestFile(testFilePath, testFileSize)
|
err = createTestFile(testFilePath, testFileSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unable to create test file: %v", err)
|
t.Errorf("unable to create test file: %v", err)
|
||||||
|
@ -697,6 +579,118 @@ func TestQuotaScan(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMultipleQuotaScans(t *testing.T) {
|
||||||
|
if !sftpd.AddQuotaScan(defaultUsername) {
|
||||||
|
t.Errorf("add quota failed")
|
||||||
|
}
|
||||||
|
if sftpd.AddQuotaScan(defaultUsername) {
|
||||||
|
t.Errorf("add quota must fail if another scan is already active")
|
||||||
|
}
|
||||||
|
sftpd.RemoveQuotaScan(defaultPassword)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQuotaSize(t *testing.T) {
|
||||||
|
usePubKey := false
|
||||||
|
testFileSize := int64(65535)
|
||||||
|
u := getTestUser(usePubKey)
|
||||||
|
u.QuotaFiles = 1
|
||||||
|
u.QuotaSize = testFileSize - 1
|
||||||
|
user, err := api.AddUser(u, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to add user: %v", err)
|
||||||
|
}
|
||||||
|
client, err := getSftpClient(user, usePubKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to create sftp client: %v", err)
|
||||||
|
} else {
|
||||||
|
defer client.Close()
|
||||||
|
testFileName := "test_file.dat"
|
||||||
|
testFilePath := filepath.Join(homeBasePath, testFileName)
|
||||||
|
err = createTestFile(testFilePath, testFileSize)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to create test file: %v", err)
|
||||||
|
}
|
||||||
|
err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("file upload error: %v", err)
|
||||||
|
}
|
||||||
|
err = sftpUploadFile(testFilePath, testFileName+".1", testFileSize, client)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("user is over quota file upload must fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = api.RemoveUser(user, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to remove user: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBandwidthAndConnections(t *testing.T) {
|
||||||
|
usePubKey := false
|
||||||
|
testFileSize := int64(131072)
|
||||||
|
u := getTestUser(usePubKey)
|
||||||
|
u.UploadBandwidth = 30
|
||||||
|
u.DownloadBandwidth = 25
|
||||||
|
wantedUploadElapsed := 1000 * (testFileSize / 1000) / u.UploadBandwidth
|
||||||
|
wantedDownloadElapsed := 1000 * (testFileSize / 1000) / u.DownloadBandwidth
|
||||||
|
// 100 ms tolerance
|
||||||
|
wantedUploadElapsed -= 100
|
||||||
|
wantedDownloadElapsed -= 100
|
||||||
|
user, err := api.AddUser(u, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to add user: %v", err)
|
||||||
|
}
|
||||||
|
client, err := getSftpClient(user, usePubKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to create sftp client: %v", err)
|
||||||
|
} else {
|
||||||
|
defer client.Close()
|
||||||
|
testFileName := "test_file.dat"
|
||||||
|
testFilePath := filepath.Join(homeBasePath, testFileName)
|
||||||
|
err = createTestFile(testFilePath, testFileSize)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to create test file: %v", err)
|
||||||
|
}
|
||||||
|
startTime := time.Now()
|
||||||
|
err = sftpUploadFile(testFilePath, testFileName, testFileSize, client)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("file upload error: %v", err)
|
||||||
|
}
|
||||||
|
elapsed := time.Since(startTime).Nanoseconds() / 1000000
|
||||||
|
if elapsed < (wantedUploadElapsed) {
|
||||||
|
t.Errorf("upload bandwidth throttling not respected, elapsed: %v, wanted: %v", elapsed, wantedUploadElapsed)
|
||||||
|
}
|
||||||
|
startTime = time.Now()
|
||||||
|
localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
|
||||||
|
c := sftpDownloadNonBlocking(testFileName, localDownloadPath, testFileSize, client)
|
||||||
|
waitForActiveTransfer()
|
||||||
|
err = <-c
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("file download error: %v", err)
|
||||||
|
}
|
||||||
|
elapsed = time.Since(startTime).Nanoseconds() / 1000000
|
||||||
|
if elapsed < (wantedDownloadElapsed) {
|
||||||
|
t.Errorf("download bandwidth throttling not respected, elapsed: %v, wanted: %v", elapsed, wantedDownloadElapsed)
|
||||||
|
}
|
||||||
|
// test disconnection
|
||||||
|
c = sftpUploadNonBlocking(testFilePath, testFileName, testFileSize, client)
|
||||||
|
waitForActiveTransfer()
|
||||||
|
sftpd.CheckIdleConnections()
|
||||||
|
stats := sftpd.GetConnectionsStats()
|
||||||
|
for _, stat := range stats {
|
||||||
|
sftpd.CloseActiveConnection(stat.ConnectionID)
|
||||||
|
}
|
||||||
|
err = <-c
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("connection closed upload must fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = api.RemoveUser(user, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to remove user: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPermList(t *testing.T) {
|
func TestPermList(t *testing.T) {
|
||||||
usePubKey := true
|
usePubKey := true
|
||||||
u := getTestUser(usePubKey)
|
u := getTestUser(usePubKey)
|
||||||
|
@ -935,3 +929,155 @@ func TestPermSymlink(t *testing.T) {
|
||||||
t.Errorf("unable to remove user: %v", err)
|
t.Errorf("unable to remove user: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func waitTCPListening(address string) {
|
||||||
|
for {
|
||||||
|
conn, err := net.Dial("tcp", address)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("tcp server %v not listening: %v\n", address, err)
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("tcp server %v now listening\n", address)
|
||||||
|
defer conn.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSftpClient(user dataprovider.User, usePubKey bool) (*sftp.Client, error) {
|
||||||
|
var sftpClient *sftp.Client
|
||||||
|
config := &ssh.ClientConfig{
|
||||||
|
User: defaultUsername,
|
||||||
|
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if usePubKey {
|
||||||
|
key, err := ssh.ParsePrivateKey([]byte(testPrivateKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.Auth = []ssh.AuthMethod{ssh.PublicKeys(key)}
|
||||||
|
} else {
|
||||||
|
config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
|
||||||
|
}
|
||||||
|
conn, err := ssh.Dial("tcp", sftpServerAddr, config)
|
||||||
|
if err != nil {
|
||||||
|
return sftpClient, err
|
||||||
|
}
|
||||||
|
sftpClient, err = sftp.NewClient(conn)
|
||||||
|
return sftpClient, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestFile(path string, size int64) error {
|
||||||
|
content := make([]byte, size)
|
||||||
|
_, err := rand.Read(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(path, content, 0666)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestUser(usePubKey bool) dataprovider.User {
|
||||||
|
user := dataprovider.User{
|
||||||
|
Username: defaultUsername,
|
||||||
|
Password: defaultPassword,
|
||||||
|
HomeDir: filepath.Join(homeBasePath, defaultUsername),
|
||||||
|
Permissions: allPerms,
|
||||||
|
}
|
||||||
|
if usePubKey {
|
||||||
|
user.PublicKey = testPubKey
|
||||||
|
user.Password = ""
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
func sftpUploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) error {
|
||||||
|
srcFile, err := os.Open(localSourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer srcFile.Close()
|
||||||
|
destFile, err := client.Create(remoteDestPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer destFile.Close()
|
||||||
|
_, err = io.Copy(destFile, srcFile)
|
||||||
|
if expectedSize > 0 {
|
||||||
|
fi, err := client.Lstat(remoteDestPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fi.Size() != expectedSize {
|
||||||
|
return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func sftpDownloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) error {
|
||||||
|
downloadDest, err := os.Create(localDestPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer downloadDest.Close()
|
||||||
|
sftpSrcFile, err := client.Open(remoteSourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sftpSrcFile.Close()
|
||||||
|
_, err = io.Copy(downloadDest, sftpSrcFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = downloadDest.Sync()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if expectedSize > 0 {
|
||||||
|
fi, err := downloadDest.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if fi.Size() != expectedSize {
|
||||||
|
return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", fi.Size(), expectedSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func sftpUploadNonBlocking(localSourcePath string, remoteDestPath string, expectedSize int64, client *sftp.Client) <-chan error {
|
||||||
|
c := make(chan error)
|
||||||
|
go func() {
|
||||||
|
c <- sftpUploadFile(localSourcePath, remoteDestPath, expectedSize, client)
|
||||||
|
}()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func sftpDownloadNonBlocking(remoteSourcePath string, localDestPath string, expectedSize int64, client *sftp.Client) <-chan error {
|
||||||
|
c := make(chan error)
|
||||||
|
go func() {
|
||||||
|
c <- sftpDownloadFile(remoteSourcePath, localDestPath, expectedSize, client)
|
||||||
|
}()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForActiveTransfer() {
|
||||||
|
stats := sftpd.GetConnectionsStats()
|
||||||
|
for len(stats) < 1 {
|
||||||
|
stats = sftpd.GetConnectionsStats()
|
||||||
|
}
|
||||||
|
activeTransferFound := false
|
||||||
|
for !activeTransferFound {
|
||||||
|
stats = sftpd.GetConnectionsStats()
|
||||||
|
if len(stats) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for _, stat := range stats {
|
||||||
|
if len(stat.Transfers) > 0 {
|
||||||
|
activeTransferFound = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue