-
Notifications
You must be signed in to change notification settings - Fork 388
/
WdtTransferRequest.h
272 lines (222 loc) · 8.68 KB
/
WdtTransferRequest.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <folly/Optional.h>
#include <wdt/ErrorCodes.h>
#include <wdt/Protocol.h>
#include <wdt/WdtOptions.h>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace facebook {
namespace wdt {
/**
* Users of wdt apis can provide a list of info
* for files. A info represents a file name with
* information such as size, and flags
* to read the file with
*/
struct WdtFileInfo {
/**
* Name of the file to be read, generally as relative path
*/
std::string fileName;
/// Size of the file to be read, default is -1
int64_t fileSize;
/// File descriptor. If this is not -1, then wdt uses this to read
int fd{-1};
/// Whether read should be done using o_direct. If fd is set, this flag will
/// be set automatically to match the fd open mode
bool directReads{false};
/// Constructor for file info with name, size and odirect request
WdtFileInfo(const std::string& name, int64_t size, bool directReads);
/**
* Constructor with name, size and fd
* If this constructor is used, then whether to do direct reads is decided
* by fd flags.
* Attempt to disambiguate the 2 constructors by having the fd first
* and string last in this one.
*/
WdtFileInfo(int fd, int64_t size, const std::string& name);
/// Verify that we can align for reading in O_DIRECT and
/// the flags make sense
void verifyAndFixFlags();
};
/**
* Basic Uri class to parse and get information from wdt url
* This class can be used in two ways :
* 1. Construct the class with a url and get fields like
* hostname, and different get parameters
* 2. Construct an empty object and set the fields, and
* generate a url
*
* Example of a url :
* wdt://localhost?dir=/tmp/wdt&ports=22356,22357
*/
class WdtUri {
public:
/// Empty Uri object
WdtUri() = default;
/// Construct the uri object using a string url
explicit WdtUri(const std::string& url);
/// Get the host name of the url
std::string getHostName() const;
/// Get the port number
int32_t getPort() const;
/// Get the query param by key
std::string getQueryParam(const std::string& key) const;
/// Get all the query params
const std::map<std::string, std::string>& getQueryParams() const;
/// Sets hostname to generate a url
void setHostName(const std::string& hostName);
/// Set the port for the uri
void setPort(int32_t port);
/// Sets a query param in the query params map
void setQueryParam(const std::string& key, const std::string& value);
/// Generate url by serializing the members of this struct
std::string generateUrl() const;
/// Url escape a value (which can be binary)
static std::string escape(const std::string& binaryStr);
/// Url unescape a value (escaped by escape()) - returns true if successful,
/// false if there is a malformed % sequence in the string
static bool unescape(std::string& result, folly::StringPiece escapedValue);
/// 0-16 -> '0'-'f'
static char toHex(unsigned char v);
/// '0'-'f' -> 0-16
static int fromHex(char c);
/// Assignment operator to convert string to wdt uri object
WdtUri& operator=(const std::string& url);
/// Clears the field of the uri
void clear();
/// Get the error code if any during parsing
ErrorCode getErrorCode() const;
private:
/**
* Returns whether the url could be processed successfully. Populates
* the values on a best effort basis.
*/
ErrorCode process(const std::string& url);
// TODO: use a vector instead, we don't really need to search...
/**
* Map of get parameters of the url. Key and value
* of the map are the name and value of get parameter respectively
*/
std::map<std::string, std::string> queryParams_;
/// Prefix of the wdt url
const std::string WDT_URL_PREFIX{"wdt://"};
/// Hostname/ip address in the uri
std::string hostName_{""};
/// Port of the uri
int32_t port_{-1};
/// Error code that reflects that status of parsing url
ErrorCode errorCode_{OK};
};
/**
* Basic request for creating wdt objects
* This request can be used for creating receivers and the
* counter part sender or vice versa
*/
struct WdtTransferRequest {
/**
* Transfer Id for the transfer. It has to be same
* on both sender and receiver
*/
std::string transferId;
/// Encryption protocol:sessionKey / secret (not printed), empty = clear text
EncryptionParams encryptionData;
/// Protocol version on sender and receiver
int64_t protocolVersion{Protocol::protocol_version};
/// Ports on which receiver is listening / sender is sending to
std::vector<int32_t> ports;
/// Address on which receiver binded the ports / sender is sending data to
std::string hostName;
/// Unique identifier for destination. This is useful to distinguish multiple
/// destinations in the same host
std::string destIdentifier;
/// Namespace for the transfer
std::string wdtNamespace;
/// Directory to write the data to / read the data from
std::string directory;
/// Only used for the sender and when not using directory discovery
std::vector<WdtFileInfo> fileInfo;
/// Only used for the sender and when not using directory discovery.
/// Sender repeatedly invokes this function to get list of files to
/// send and stops when the function return folly::none. File transfer
/// is done in batches. After intiating the transfer for a initial list of
/// files (either via fileInfo or a call to fileInfoGenerator), we wait
/// until transfer is complete before we read the next batch, if any, by
/// invoking fileInfoGenerator again.
using FileInfoGenerator =
std::function<folly::Optional<std::vector<WdtFileInfo>>()>;
FileInfoGenerator fileInfoGenerator{};
/// Use fileInfo even if empty (don't use the directory exploring)
bool disableDirectoryTraversal{false};
// download resumption is enabled on the receiver side
// and is requested from the sender
bool downloadResumptionEnabled{false};
/// TLS is enabled on the receiver side
bool tls{false};
/// Number of GBytes after iv is changed
int64_t ivChangeInterval{0};
/// Any error associated with this transfer request upon processing
ErrorCode errorCode{OK};
/// Empty constructor
WdtTransferRequest() {
}
/**
* Constructor with start port and num ports. Fills the vector with
* ports from [startPort, startPort + numPorts)
*/
WdtTransferRequest(int startPort, int numPorts, const std::string& directory);
/// Constructor to construct the request object from a url string
explicit WdtTransferRequest(const std::string& uriString);
/// @return generates wdt connection url and has encryption secret.
/// Returned secret should not be logged
std::string genWdtUrlWithSecret() const;
/// @return returns a string describing this request. This string can be
/// logged
std::string getLogSafeString() const;
/// Serialize the ports into uri
void serializePorts(WdtUri& wdtUri) const;
/// Get stringified port list
std::string getSerializedPortsList() const;
/// Operator for finding if two request objects are equal
bool operator==(const WdtTransferRequest& that) const;
/// Overloaded operator for printing request info
friend std::ostream& operator<<(std::ostream& os,
const WdtTransferRequest& req);
const static int LEGACY_PROTCOL_VERSION;
/// Names of the get parameters for different fields
const static std::string TRANSFER_ID_PARAM;
/** Constant for for the protocol version get parameter in uri */
const static std::string RECEIVER_PROTOCOL_VERSION_PARAM;
const static std::string DIRECTORY_PARAM;
const static std::string PORTS_PARAM;
const static std::string START_PORT_PARAM;
const static std::string NUM_PORTS_PARAM;
/// Encryption parameters (proto:key for now, certificate,... potentially)
const static std::string ENCRYPTION_PARAM;
const static std::string TLS_PARAM;
const static std::string NAMESPACE_PARAM;
const static std::string DEST_IDENTIFIER_PARAM;
const static std::string DOWNLOAD_RESUMPTION_PARAM;
const static std::string IV_CHANGE_INTERVAL_PARAM;
/// Get ports vector from startPort and numPorts
static std::vector<int32_t> genPortsVector(int32_t startPort,
int32_t numPorts);
private:
/**
* Serialize this structure into a url string containing all fields
* Will only put the real encoded secret if forLogging is set to false
*/
std::string generateUrlInternal(bool genFull, bool forLogging) const;
};
} // namespace wdt
} // namespace facebook