tesses.backup/Tesses.Backup.Client/BackupSession.cs

148 lines
6.1 KiB
C#

/*
A simple Backup Client / Server
Copyright (C) 2023 Mike Nolan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Tesses.Backup.Models;
using Tesses.VirtualFilesystem;
namespace Tesses.Backup
{
public class BackupSession
{
public BackupSession(LoginResponse response,BackupClient client)
{
this.clt = client;
this.LoginResponse = response;
}
BackupClient clt;
public LoginResponse LoginResponse {get;set;}
public long DeviceId {get;set;}=-1;
public async Task<LogoutResponse> LogoutAsync()
{
LogoutRequest request = new LogoutRequest();
request.Key = LoginResponse.Key;
return await clt.MakeJsonPostRequestAsync<LogoutResponse>("/api/v1/Logout",request);
}
public async Task<EnumerateBackupsResponse> EnumerateBackupsAsync()
{
EnumerateBackupsRequest request=new EnumerateBackupsRequest();
request.DeviceId = DeviceId;
request.Key = LoginResponse.Key;
return await clt.MakeJsonPostRequestAsync<EnumerateBackupsResponse>("/api/v1/Backups",request);
}
public async Task<EnumerateBackupResponse> EnumerateBackupDataAsync(long backupId)
{
EnumerateBackupRequest request=new EnumerateBackupRequest();
request.BackupId= backupId;
request.Key = LoginResponse.Key;
return await clt.MakeJsonPostRequestAsync<EnumerateBackupResponse>("/api/v1/Backup",request);
}
public async Task<EnumerateDeviceResponse> GetDevicesAsync()
{
EnumerateDeviceRequest request = new EnumerateDeviceRequest();
request.Key = LoginResponse.Key;
return await clt.MakeJsonPostRequestAsync<EnumerateDeviceResponse>("/api/v1/Devices",request);
}
public async Task<GetDeviceResponse> SetDeviceAsync(string deviceName)
{
GetDeviceRequest request=new GetDeviceRequest();
request.Key = LoginResponse.Key;
request.Name = deviceName;
var resp= await clt.MakeJsonPostRequestAsync<GetDeviceResponse>("/api/v1/Device",request);
DeviceId=resp.DeviceId;
return resp;
}
public async Task RestoreFileAsync(string hash,long myDeviceId,Stream strm)
{
var fstrm=await clt.Client.GetStreamAsync($"/api/v1/File?key={LoginResponse.Key}&device={myDeviceId}&hash={hash}");
await fstrm.CopyToAsync(strm);
}
public async Task RestoreFileAsync(string hash,Stream strm)
{
await RestoreFileAsync(hash,DeviceId,strm);
}
public async Task<BackupContext> PrepareBackupAsync(IVirtualFilesystem fs)
{
Func<List<BackupFileEntry>,UnixPath,Task> enumerateFiles=null;
enumerateFiles=async(ent,p)=>{
foreach(var dir in fs.EnumerateDirectories(p))
{
BackupFileEntry entry=new BackupFileEntry();
entry.IsFile=false;
entry.Created = await fs.GetCreationTimeAsync(dir);
entry.Modified = await fs.GetLastWriteTimeAsync(dir);
entry.Length = 0;
entry.Hash ="";
entry.Name = dir.Name;
await enumerateFiles(entry.SubEntries,dir);
ent.Add(entry);
}
foreach(var file in fs.EnumerateFiles(p))
{
BackupFileEntry entry=new BackupFileEntry();
entry.IsFile=true;
entry.Created = await fs.GetCreationTimeAsync(file);
entry.Modified = await fs.GetLastWriteTimeAsync(file);
using(var f = await fs.OpenAsync(file,System.IO.FileMode.Open,System.IO.FileAccess.Read,System.IO.FileShare.Read))
{
entry.Length = f.Length;
using (var bufferedStream = new BufferedStream(f, 1024 * 32))
{
using(var sha = new SHA256Managed())
{
byte[] hashBytes=sha.ComputeHash(bufferedStream);
entry.Hash = BitConverter.ToString(hashBytes).Replace("-","");
}
}
}
entry.Name = file.Name;
ent.Add(entry);
}
};
CreateBackupRequest request = new CreateBackupRequest();
await enumerateFiles(request.BackupData,Special.Root);
request.DeviceId = DeviceId;
request.Key = LoginResponse.Key;
var response=await clt.MakeJsonPostRequestAsync<CreateBackupResponse>("/api/v1/CreateBackup",request);
return await Task.Run<BackupContext>(()=>{
return new BackupContext(LoginResponse.Key,clt.Client,fs,response,request.DeviceId);
});
}
public async Task<BackupContext> PrepareBackupAsync(IVirtualFilesystem fs,UnixPath path)
{
return await PrepareBackupAsync(fs.GetSubdirFilesystem(path));
}
}
}