Skip to content

Commit 969b9a5

Browse files
committed
DMC-1358: Export the transfer source and destination hosts via the Copy API
Implementation details: - Identify and store the transfer source and destination hosts in the underlying DavixCopyInternal implementation -- The transfer active party is obtained by following the redirections for the "HTTP COPY" request -- The transfer passive party is obtained via the "RemoteConnections" performance marker -- Assign the active and passive transfer hosts as the source/destination depending on the copy mode - Implement "getIPString()" helper function to extract the IP string from the "RemoteConnections" performance marker - Modify the "getIPType()" helper function to rely on the newly added "getIPString()" function
1 parent 43f1f68 commit 969b9a5

File tree

3 files changed

+127
-32
lines changed

3 files changed

+127
-32
lines changed

include/davix/copy/davixcopy.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ class DAVIX_EXPORT DavixCopy
8787
void setPerformanceCallback(PerformanceCallback callback, void *udata);
8888
void setCancellationCallback(CancellationCallback callback, void *udata);
8989

90+
std::string getTransferSourceHost() const;
91+
std::string getTransferDestinationHost() const;
92+
9093
private:
9194
class DavixCopyInternal *d_ptr;
9295

src/modules/copy/copy.cpp

+116-29
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,52 @@ void DavixCopy::setCancellationCallback(CancellationCallback callback, void *uda
120120
}
121121

122122

123+
std::string DavixCopy::getTransferSourceHost() const
124+
{
125+
return d_ptr->getTransferSourceHost();
126+
}
127+
128+
std::string DavixCopy::getTransferDestinationHost() const
129+
{
130+
return d_ptr->getTransferDestinationHost();
131+
}
132+
133+
134+
std::string DavixCopyInternal::getTransferSourceHost() const
135+
{
136+
return sourceHost;
137+
}
138+
139+
std::string DavixCopyInternal::getTransferDestinationHost() const
140+
{
141+
return destinationHost;
142+
}
143+
144+
void DavixCopyInternal::setTransferHost(const std::string& transferHost, bool activeParty) {
145+
if (activeParty) {
146+
if (parameters->getCopyMode() == CopyMode::Push) {
147+
if (sourceHost.empty()) {
148+
sourceHost = transferHost;
149+
}
150+
} else if (parameters->getCopyMode() == CopyMode::Pull) {
151+
if (destinationHost.empty()) {
152+
destinationHost = transferHost;
153+
}
154+
}
155+
} else {
156+
if (parameters->getCopyMode() == CopyMode::Push) {
157+
if (destinationHost.empty()) {
158+
destinationHost = transferHost;
159+
}
160+
} else if (parameters->getCopyMode() == CopyMode::Pull) {
161+
if (sourceHost.empty()) {
162+
sourceHost = transferHost;
163+
}
164+
}
165+
}
166+
}
167+
168+
123169
void DavixCopyInternal::setPerformanceCallback(DavixCopy::PerformanceCallback callback,
124170
void *udata)
125171
{
@@ -339,7 +385,7 @@ void DavixCopyInternal::copy(const Uri &src, const Uri &dst,
339385
return;
340386

341387
// Finished hopping
342-
std::string finalSource = nextSrc;
388+
setTransferHost(Uri(nextSrc).getHost(), true);
343389

344390
// Just wait for it to finish
345391
monitorPerformanceMarkers(request, error);
@@ -356,44 +402,85 @@ void DavixCopyInternal::copy(const Uri &src, const Uri &dst,
356402
delete request;
357403
}
358404

359-
/* Pasrse string to determine IPv type */
360-
enum IPtype getIPv_type(char *text) {
361-
IPtype type=undefined;
362-
int start=0;
363-
int lbkt=0, rbkt=0, per=0;
364-
int i=0;
405+
// Parse "RemoteConnections" line and extract IP string
406+
// Example: tcp:[fff:aaa:192:168::100:e]:443 --> [fff:aaa:192:168::100:e]
407+
// Example: udp:192.168.1.100:8443 --> 192.168.1.100
408+
std::string getIPString(char *text) {
409+
int idx = 0;
365410

366-
while (text[start] && isspace(text[start])) //skip any initial whitespaces at the beginning
367-
start++;
411+
// Skip any initial whitespaces
412+
while (text[idx] && isspace(text[idx])) {
413+
idx++;
414+
}
368415

369-
if (!text[start])
370-
return(undefined);
416+
if (!text[idx]) {
417+
return "";
418+
}
371419

372-
if (!(strncasecmp("tcp:", text+start, 4) ||
373-
strncasecmp("udp:", text+start, 4))) //Check format validity
374-
return(undefined);
420+
if ((strncasecmp("tcp:", text + idx, 4) != 0) &&
421+
(strncasecmp("udp:", text + idx, 4) != 0)) {
422+
return "";
423+
}
375424

376-
for (i=start;text[i];i++) {
377-
if (isspace(text[i]))
378-
break;
379-
else if (text[i] == '[')
425+
if (!text[idx + 4]) {
426+
return "";
427+
}
428+
429+
std::string ipstring = text + idx + 4;
430+
size_t endpos;
431+
432+
if (ipstring.back() == '\n') {
433+
ipstring.pop_back();
434+
}
435+
436+
// Trim string to only the IP notation
437+
if (ipstring.front() == '[') {
438+
// Dealing with IPv6 scenario
439+
endpos = ipstring.find(']');
440+
441+
if (endpos == std::string::npos) {
442+
return "";
443+
}
444+
445+
endpos += 1;
446+
} else {
447+
endpos = ipstring.find(':');
448+
449+
if (endpos == std::string::npos) {
450+
endpos = ipstring.size();
451+
}
452+
}
453+
454+
ipstring = ipstring.substr(0, endpos);
455+
return ipstring;
456+
}
457+
458+
// Parse string to determine IP version
459+
enum IPtype getIPType(char *text) {
460+
int lbkt = 0, rbkt = 0, per = 0;
461+
std::string ipstring = getIPString(text);
462+
463+
for (const char& c: ipstring) {
464+
if (c == '[') {
380465
lbkt++;
381-
else if (text[i] == ']')
466+
} else if (c == ']') {
382467
rbkt++;
383-
else if (text[i] == '.')
468+
} else if (c == '.') {
384469
per++;
470+
}
385471
}
386472

387473
/*
388474
* Test for IPv4 or IPv6 address. IPv6 type contains square brackets. IPv4 contains 3 periods.
389475
* Note that IPv4-mapped IPv6 addresses are of the format [::ffff.<IPv4 address>]
390476
*/
391-
if (lbkt && rbkt)
392-
type = IPv6;
393-
else if (per == 3)
394-
type = IPv4;
477+
if (lbkt && rbkt) {
478+
return IPtype::IPv6;
479+
} else if (per == 3) {
480+
return IPtype::IPv4;
481+
}
395482

396-
return(type);
483+
return IPtype::undefined;
397484
}
398485

399486
void logPerfmarker(const std::list<std::string>& lines)
@@ -457,10 +544,10 @@ void DavixCopyInternal::monitorPerformanceMarkers(Davix::HttpRequest *request,
457544
}
458545
else if (strncasecmp("RemoteConnections:", p, 18) == 0)
459546
{
460-
// Parse to determine IPv4 or IPv6
461-
performance.ipflag = getIPv_type(p + 18);
462-
DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Got ipflag: {}", performance.ipflag);
463-
547+
std::string ipstring = getIPString(p + 18);
548+
setTransferHost(ipstring, false);
549+
performance.ipflag = getIPType(p + 18);
550+
DAVIX_SLOG(DAVIX_LOG_DEBUG, DAVIX_LOG_GRID, "Got IP: {} (ipver={})", ipstring, performance.ipflag);
464551
}
465552
else if (strncasecmp("End", p, 3) == 0)
466553
{

src/modules/copy/copy_internal.hpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,23 @@ class Davix::DavixCopyInternal
4444
void setPerformanceCallback(DavixCopy::PerformanceCallback callback, void *udata);
4545
void setCancellationCallback(DavixCopy::CancellationCallback callback, void *udata);
4646

47+
std::string getTransferSourceHost() const;
48+
std::string getTransferDestinationHost() const;
49+
4750
protected:
4851
Davix::Context &context;
4952
const Davix::RequestParams *parameters;
53+
5054
DavixCopy::PerformanceCallback perfCallback;
5155
void *perfCallbackUdata;
5256

5357
DavixCopy::CancellationCallback cancCallback;
5458
void *cancCallbackUdata;
5559

60+
std::string sourceHost;
61+
std::string destinationHost;
62+
63+
void setTransferHost(const std::string& transferHost, bool activeParty);
5664
void monitorPerformanceMarkers(Davix::HttpRequest *request, Davix::DavixError **error);
5765

5866
private:
@@ -61,9 +69,6 @@ class Davix::DavixCopyInternal
6169

6270
bool shouldCancel();
6371
bool shouldCancel(Davix::DavixError **error);
64-
65-
6672
};
6773

68-
6974
#endif //DAVIX_COPY_INTERNAL_HPP

0 commit comments

Comments
 (0)