urbackup_backend/urbackupcommon/fileclient/FileClient.h
2019-05-13 22:34:20 +02:00

311 lines
7.0 KiB
C++

#ifndef CFILECLIENT_H
#define CFILECLIENT_H
#include <deque>
#include <string.h>
#include "packet_ids.h"
#include "../../urbackupcommon/fileclient/tcpstack.h"
#include "socket_header.h"
#include "../../Interface/Pipe.h"
#include "../../Interface/File.h"
#include "../../Interface/Mutex.h"
#include "../os_functions.h"
#define TCP_PORT 35621
#define UDP_PORT 35622
#define UDP_SOURCE_PORT 35623
#define BUFFERSIZE 32768
#define NBUFFERS 32
#define NUM_FILECLIENTS 5
#define FILECLIENT_VERSION 36
#define WINDOW_SIZE 512*1024
#define BUFFERSIZE_UDP 4096
//#define DISABLE_WINDOW_SIZE
typedef unsigned int _u32;
typedef int _i32;
typedef unsigned short _u16;
typedef __int64 _u64;
#define SERVER_TIMEOUT_BACKUPPED 120000
#define SERVER_TIMEOUT 120000
#define LOG
class CRData;
class FileClient
{
public:
class ReconnectionCallback
{
public:
virtual IPipe * new_fileclient_connection(void)=0;
};
class NoFreeSpaceCallback
{
public:
virtual bool handle_not_enough_space(const std::string &path)=0;
};
enum MetadataQueue
{
MetadataQueue_Data,
MetadataQueue_Metadata,
MetadataQueue_MetadataAndHash
};
class QueueCallback
{
public:
virtual std::string getQueuedFileFull(MetadataQueue& metadata, size_t& folder_items, bool& finish_script, int64& file_id) = 0;
virtual void unqueueFileFull(const std::string& fn, bool finish_script) = 0;
virtual void resetQueueFull() = 0;
};
class ProgressLogCallback
{
public:
virtual void log_progress(const std::string& fn, int64 total, int64 downloaded, int64 speed_bps) = 0;
};
FileClient(bool enable_find_servers, std::string identity, int protocol_version=0, bool internet_connection=false,
FileClient::ReconnectionCallback *reconnection_callback=NULL,
FileClient::NoFreeSpaceCallback *nofreespace_callback=NULL);
~FileClient(void);
struct SAddrHint
{
SAddrHint()
{}
SAddrHint(const SLookupResult& lookup_res)
: is_ipv6(lookup_res.is_ipv6)
{
if (lookup_res.is_ipv6)
{
memcpy(addr_ipv6, lookup_res.addr_v6, sizeof(addr_ipv6));
}
else
{
addr_ipv4 = lookup_res.addr_v4;
}
}
union
{
unsigned int addr_ipv4;
char addr_ipv6[16];
};
bool is_ipv6;
bool same(const SAddrHint& other) const
{
if (is_ipv6 != other.is_ipv6)
return false;
if (is_ipv6)
return memcmp(addr_ipv6, other.addr_ipv6, sizeof(addr_ipv6)) == 0;
else
return addr_ipv4 == other.addr_ipv4;
}
std::string toString() const;
};
_u32 GetServers(bool start, const std::vector<SAddrHint> &addr_hints);
std::vector<SAddrHint> getServers(void);
std::vector<SAddrHint> getWrongVersionServers(void);
std::vector<std::string> getServerNames(void);
_u32 getLocalIP(void);
void setServerName(std::string pName);
std::string getServerName(void);
int getMaxVersion(void);
bool isConnected(void);
bool ListDownloaded(void);
_u32 Connect(const SAddrHint& addr);
_u32 Connect(IPipe *cp);
void Shutdown();
//---needs Connection
_u32 GetFile(std::string remotefn, IFsFile *file, bool hashed, bool metadata_only, size_t folder_items, bool is_script, size_t file_id);
//_u32 GetFileHashAndMetadata(std::string remotefn, std::string& hash, std::string& permissions, int64& filesize, int64& created, int64& modified);
_u32 InformMetadataStreamEnd(const std::string& server_token, int tries);
_u32 StopPhashLoad(const std::string& server_token, const std::string& phash_fn, int tries);
_u32 FinishScript(std::string remotefn);
void addThrottler(IPipeThrottler *throttler);
_i64 getTransferredBytes(void);
_i64 getRealTransferredBytes();
_i64 getReceivedDataBytes(bool with_sparse);
void resetReceivedDataBytes(bool with_sparse);
static std::string getErrorString(_u32 ec);
void setReconnectionTimeout(unsigned int t);
void setQueueCallback(FileClient::QueueCallback* cb);
void setProgressLogCallback(FileClient::ProgressLogCallback* cb);
FileClient::ProgressLogCallback* getProgressLogCallback();
void setNoFreeSpaceCallback(FileClient::NoFreeSpaceCallback* cb);
_u32 Flush();
bool Reconnect(void);
bool isDownloading();
IFile* releaseSparseExtendsFile();
void resetSparseExtentsFile();
static IFile* temporaryFileRetry();
static bool writeFileRetry(IFile* f, const char* buf, _u32 bsize);
void setReconnectTries(int tries);
private:
int getReconnectTriesDecr();
void bindToNewInterfaces();
void fillQueue();
void logProgress(const std::string& remotefn, _u64 filesize, _u64 received);
bool alreadyHasAddrv4(sockaddr_in addr);
bool alreadyHasAddrv6(sockaddr_in6 addr);
struct SSocket
{
SOCKET udpsock;
bool is_ipv6;
union
{
sockaddr_in addr_ipv4;
sockaddr_in6 addr_ipv6;
};
sockaddr_in broadcast_addr;
};
std::string ipToString(SSocket& s);
std::vector<SSocket> udpsocks;
IPipe *tcpsock;
int64 starttime;
int64 connect_starttime;
bool socket_open;
bool connected;
char buffer[BUFFERSIZE_UDP];
std::vector<SAddrHint> servers;
std::vector<SAddrHint> wvservers;
std::vector<std::string> servernames;
std::vector<std::string> games;
CTCPStack stack;
_u32 local_ip;
std::string mServerName;
int max_version;
SAddrHint server_addr;
int connection_id;
int protocol_version;
bool internet_connection;
_i64 real_transferred_bytes;
_i64 transferred_bytes;
std::vector<IPipeThrottler*> throttlers;
FileClient::ReconnectionCallback *reconnection_callback;
FileClient::NoFreeSpaceCallback *nofreespace_callback;
FileClient::QueueCallback* queue_callback;
unsigned int reconnection_timeout;
bool retryBindToNewInterfaces;
std::string identity;
_i64 received_data_bytes;
IMutex* mutex;
struct SQueueItem
{
SQueueItem(std::string fn, bool finish_script)
: fn(fn), finish_script(finish_script)
{
}
std::string fn;
bool finish_script;
};
std::deque<SQueueItem> queued;
char dl_buf[BUFFERSIZE];
size_t dl_off;
int64 last_transferred_bytes;
int64 last_progress_log;
FileClient::ProgressLogCallback* progress_log_callback;
bool needs_flush;
bool is_downloading;
IFile* sparse_extends_f;
_i64 sparse_bytes;
int reconnect_tries;
};
const _u32 ERR_CONTINUE=0;
const _u32 ERR_SUCCESS=1;
const _u32 ERR_TIMEOUT=2;
const _u32 ERR_CANNOT_OPEN_FILE=3;
const _u32 ERR_SOCKET_ERROR=4;
const _u32 ERR_CONNECTED=5;
const _u32 ERR_ERROR=6;
const _u32 ERR_BASE_DIR_LOST=7;
const _u32 ERR_HASH=8;
const _u32 ERR_INT_ERROR=9;
const _u32 ERR_CONN_LOST=10;
const _u32 ERR_ERRORCODES=11;
const _u32 ERR_READ_ERROR = 12;
const _u32 sleeptime=50;
#endif