I applied my changes to your code... hope I got all of them
Packet* CPartFile::CreateSrcInfoPacket(const CUpDownClient* forClient, uint8 byRequestedVersion, uint16 nRequestedOptions) const
{
if (!IsPartFile() || srclist.IsEmpty())
return CKnownFile::CreateSrcInfoPacket(forClient, byRequestedVersion, nRequestedOptions);
if (md4cmp(forClient->GetUploadFileID(), GetFileHash()) != 0) {
// should never happen
DEBUG_ONLY( DebugLogError(_T("*** %hs - client (%s) upload file \"%s\" does not match file \"%s\""), __FUNCTION__, forClient->DbgGetClientInfo(), DbgGetFileInfo(forClient->GetUploadFileID()), GetFileName()) );
ASSERT(0);
return NULL;
}
// check whether client has either no download status at all or a download status which is valid for this file
if (!(forClient->GetUpPartCount() == 0 && forClient->GetUpPartStatus() == NULL)
&& !(forClient->GetUpPartCount() == GetPartCount() && forClient->GetUpPartStatus() != NULL))
{
// should never happen
DEBUG_ONLY( DebugLogError(_T("*** %hs - part count (%u) of client (%s) does not match part count (%u) of file \"%s\""), __FUNCTION__, forClient->GetUpPartCount(), forClient->DbgGetClientInfo(), GetPartCount(), GetFileName()) );
ASSERT(0);
return NULL;
}
if (!(GetStatus() == PS_READY || GetStatus() == PS_EMPTY))
return NULL;
CSafeMemFile data(1024);
uint8 byUsedVersion;
bool bIsSX2Packet;
if (forClient->SupportsSourceExchange2() && byRequestedVersion > 0){
// the client uses SourceExchange2 and requested the highest version he knows
// and we send the highest version we know, but of course not higher than his request
#ifdef USE_NEO_SX // NEO: NSX - [NeoSoruceExchange]
byUsedVersion = min(byRequestedVersion, (uint8)(forClient->SupportsSourceExchangeExt() ? SOURCEEXCHANGEEXT_VERSION : SOURCEEXCHANGE2_VERSION));
#else // NEO: NSX END
byUsedVersion = min(byRequestedVersion, (uint8)SOURCEEXCHANGE2_VERSION);
#endif
bIsSX2Packet = true;
data.WriteUInt8(byUsedVersion);
// we don't support any special SX2 options yet, reserved for later use
if (nRequestedOptions != 0)
DebugLogWarning(_T("Client requested unknown options for SourceExchange2: %u (%s)"), nRequestedOptions, forClient->DbgGetClientInfo());
}
else{
byUsedVersion = forClient->GetSourceExchange1Version();
bIsSX2Packet = false;
if (forClient->SupportsSourceExchange2())
DebugLogWarning(_T("Client which announced to support SX2 sent SX1 packet instead (%s)"), forClient->DbgGetClientInfo());
}
UINT nCount = 0;
data.WriteHash16(m_FileIdentifier.GetMD4Hash());
data.WriteUInt16((uint16)nCount);
bool bNeeded;
const uint8* reqstatus = forClient->GetUpPartStatus();
for (POSITION pos = srclist.GetHeadPosition();pos != 0;){
bNeeded = false;
const CUpDownClient* cur_src = srclist.GetNext(pos);
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
if ((cur_src->HasLowID() && !cur_src->SupportsNatTraversal()) || !cur_src->IsValidSource())
#else // NEO: NAT END
if (cur_src->HasLowID() || !cur_src->IsValidSource())
#endif
continue;
const uint8* srcstatus = cur_src->GetPartStatus();
if (srcstatus){
if (cur_src->GetPartCount() == GetPartCount()){
if (reqstatus){
ASSERT( forClient->GetUpPartCount() == GetPartCount() );
// only send sources which have needed parts for this client
for (UINT x = 0; x < GetPartCount(); x++){
if (srcstatus[x] && !reqstatus[x]){
bNeeded = true;
break;
}
}
}
else{
// We know this client is valid. But don't know the part count status.. So, currently we just send them.
for (UINT x = 0; x < GetPartCount(); x++){
if (srcstatus[x]){
bNeeded = true;
break;
}
}
}
}
else{
// should never happen
if (thePrefs.GetVerbose())
DEBUG_ONLY(DebugLogError(_T("*** %hs - found source (%s) with wrong partcount (%u) attached to partfile \"%s\" (partcount=%u)"), __FUNCTION__, cur_src->DbgGetClientInfo(), cur_src->GetPartCount(), GetFileName(), GetPartCount()));
}
}
if (bNeeded){
nCount++;
uint32 dwID;
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
if (byUsedVersion >= 3 && ! cur_src->HasLowID())
#else // NEO: NAT END
if (byUsedVersion >= 3)
#endif
dwID = cur_src->GetUserIDHybrid();
else
dwID = ntohl(cur_src->GetUserIDHybrid());
data.WriteUInt32(dwID);
data.WriteUInt16(cur_src->GetUserPort());
#ifdef USE_NEO_SX // NEO: NSX - [NeoSoruceExchange]
if(forClient->SupportsSourceExchangeExt())
{
ULONGLONG pos = data.GetPosition();
uint32 tagcount = 0;
data.WriteUInt8(tagcount);
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
if (cur_src->HasLowID())
{
if(cur_src->SupportsDirectUDPCallback())
{
tagcount += 2;
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
CTag tagIPv4(CT_EMULE_ADDRESS, _ntohl(cur_src->GetIPv4().ToIPv4()));
#else // NEO: IP6 END
CTag tagIPv4(CT_EMULE_ADDRESS, cur_src->GetIP());
#endif
tagIPv4.WriteNewEd2kTag(&data);
CTag tagUdpPorts(CT_EMULE_UDPPORTS,
((uint32)cur_src->GetKadPort() << 16) |
((uint32)cur_src->GetUDPPort() << 0)
);
tagUdpPorts.WriteNewEd2kTag(&data);
}
if(cur_src->GetBuddyIP())
{
tagcount += 2;
CTag tagBuddyIP(CT_EMULE_BUDDYIP, cur_src->GetBuddyIP() );
tagBuddyIP.WriteNewEd2kTag(&data);
CTag tagBuddyPort(CT_EMULE_BUDDYUDP,
// ( RESERVED )
((uint32)cur_src->GetBuddyPort() )
);
tagBuddyPort.WriteNewEd2kTag(&data);
}
if(!isnulmd4(cur_src->GetBuddyID()))
{
tagcount += 1;
CTag tagBuddyID(CT_EMULE_BUDDYID, cur_src->GetBuddyID());
tagBuddyID.WriteNewEd2kTag(&data);
}
}
#endif // NEO: NAT END
if(cur_src->GetServerIP() != 0)
{
tagcount += 2;
CTag tagServerIP(CT_EMULE_SERVERIP, cur_src->GetServerIP());
tagServerIP.WriteNewEd2kTag(&data);
CTag tagServerPorts(CT_EMULE_SERVERTCP,
// ( RESERVED )
((uint32)cur_src->GetServerPort() )
);
tagServerPorts.WriteNewEd2kTag(&data);
}
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
if(!cur_src->IsIPv6Open())
{
tagcount += 1;
CTag tagIPv6(CT_NEOMULE_IP_V6, cur_src->GetIPv6().Data());
tagIPv6.WriteNewEd2kTag(&data);
}
#endif // NEO: IP6 END
data.Seek(pos, CFile::begin);
data.WriteUInt8(tagcount);
data.SeekToEnd();
}
else
#endif // NEO: NSX END
{
data.WriteUInt32(cur_src->GetServerIP());
data.WriteUInt16(cur_src->GetServerPort());
}
if (byUsedVersion >= 2)
data.WriteHash16(cur_src->GetUserHash());
if (byUsedVersion >= 4){
// ConnectSettings - SourceExchange V4
// 4 Reserved (!)
// 1 DirectCallback Supported/Available
// 1 CryptLayer Required
// 1 CryptLayer Requested
// 1 CryptLayer Supported
const uint8 uSupportsCryptLayer = cur_src->SupportsCryptLayer() ? 1 : 0;
const uint8 uRequestsCryptLayer = cur_src->RequestsCryptLayer() ? 1 : 0;
const uint8 uRequiresCryptLayer = cur_src->RequiresCryptLayer() ? 1 : 0;
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
uint8 byCryptOptions = (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0);
//if(forClient->SupportsSourceExchangeExt())
//{
const uint8 uDirectUDPCallback = cur_src->SupportsDirectUDPCallback() ? 1 : 0;
const uint8 uSupportsNatTraversal = cur_src->SupportsNatTraversal() ? 1 : 0;
byCryptOptions |= (uSupportsNatTraversal << 7) | (uDirectUDPCallback << 3);
//}
#else // NEO: NAT END
//const uint8 uDirectUDPCallback = cur_src->SupportsDirectUDPCallback() ? 1 : 0;
const uint8 byCryptOptions = /*(uDirectUDPCallback << 3) |*/ (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0);
#endif
data.WriteUInt8(byCryptOptions);
}
if (nCount > 500)
break;
}
}
if (!nCount)
return 0;
data.Seek(bIsSX2Packet ? 17 : 16, SEEK_SET);
data.WriteUInt16((uint16)nCount);
Packet* result = new Packet(&data, OP_EMULEPROT);
result->opcode = bIsSX2Packet ? OP_ANSWERSOURCES2 : OP_ANSWERSOURCES;
// (1+)16+2+501*(4+2+4+2+16+1) = 14547 (14548) bytes max.
if (result->size > 354)
result->PackPacket();
if (thePrefs.GetDebugSourceExchange())
AddDebugLogLine(false, _T("SXSend: Client source response SX2=%s, Version=%u; Count=%u, %s, File=\"%s\""), bIsSX2Packet ? _T("Yes") : _T("No"), byUsedVersion, nCount, forClient->DbgGetClientInfo(), GetFileName());
return result;
}
void CPartFile::AddClientSources(CSafeMemFile* sources, uint8 uClientSXVersion, bool bSourceExchange2, const CUpDownClient* pClient)
{
if (stopped)
return;
UINT nCount = 0;
if (thePrefs.GetDebugSourceExchange()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
AddDebugLogLine(false, _T("SXRecv: Client source response; SX2=%s, Ver=%u, %sFile=\"%s\""), bSourceExchange2 ? _T("Yes") : _T("No"), uClientSXVersion, strDbgClientInfo, GetFileName());
}
UINT uPacketSXVersion = 0;
if (!bSourceExchange2){
// for SX1 (deprecated):
// Check if the data size matches the 'nCount' for v1 or v2 and eventually correct the source
// exchange version while reading the packet data. Otherwise we could experience a higher
// chance in dealing with wrong source data, userhashs and finally duplicate sources.
nCount = sources->ReadUInt16();
UINT uDataSize = (UINT)(sources->GetLength() - sources->GetPosition());
// Checks if version 1 packet is correct size
if (nCount*(4+2+4+2) == uDataSize)
{
// Received v1 packet: Check if remote client supports at least v1
if (uClientSXVersion < 1) {
if (thePrefs.GetVerbose()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
DebugLogWarning(_T("Received invalid SX packet (v%u, count=%u, size=%u), %sFile=\"%s\""), uClientSXVersion, nCount, uDataSize, strDbgClientInfo, GetFileName());
}
return;
}
uPacketSXVersion = 1;
}
// Checks if version 2&3 packet is correct size
else if (nCount*(4+2+4+2+16) == uDataSize)
{
// Received v2,v3 packet: Check if remote client supports at least v2
if (uClientSXVersion < 2) {
if (thePrefs.GetVerbose()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
DebugLogWarning(_T("Received invalid SX packet (v%u, count=%u, size=%u), %sFile=\"%s\""), uClientSXVersion, nCount, uDataSize, strDbgClientInfo, GetFileName());
}
return;
}
if (uClientSXVersion == 2)
uPacketSXVersion = 2;
else
uPacketSXVersion = 3;
}
// v4 packets
else if (nCount*(4+2+4+2+16+1) == uDataSize)
{
// Received v4 packet: Check if remote client supports at least v4
if (uClientSXVersion < 4) {
if (thePrefs.GetVerbose()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
DebugLogWarning(_T("Received invalid SX packet (v%u, count=%u, size=%u), %sFile=\"%s\""), uClientSXVersion, nCount, uDataSize, strDbgClientInfo, GetFileName());
}
return;
}
uPacketSXVersion = 4;
}
else
{
// If v5+ inserts additional data (like v2), the above code will correctly filter those packets.
// If v5+ appends additional data after <count>(<Sources>)[count], we are in trouble with the
// above code. Though a client which does not understand v5+ should never receive such a packet.
if (thePrefs.GetVerbose()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
DebugLogWarning(_T("Received invalid SX packet (v%u, count=%u, size=%u), %sFile=\"%s\""), uClientSXVersion, nCount, uDataSize, strDbgClientInfo, GetFileName());
}
return;
}
ASSERT( uPacketSXVersion != 0 );
}
else{
// for SX2:
// We only check if the version is known by us and do a quick sanitize check on known version
// other then SX1, the packet will be ignored if any error appears, since it can't be a "misunderstanding" anymore
#ifdef USE_NEO_SX // NEO: NSX - [NeoSoruceExchange]
if ((pClient && uClientSXVersion > (pClient->SupportsSourceExchangeExt() ? SOURCEEXCHANGEEXT_VERSION : SOURCEEXCHANGE2_VERSION)) || uClientSXVersion == 0){
#else // NEO: NSX END
if (uClientSXVersion > SOURCEEXCHANGE2_VERSION || uClientSXVersion == 0){
#endif
if (thePrefs.GetVerbose()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
DebugLogWarning(_T("Received invalid SX2 packet - Version unknown (v%u), %sFile=\"%s\""), uClientSXVersion, strDbgClientInfo, GetFileName());
}
return;
}
// all known versions use the first 2 bytes as count and unknown version are already filtered above
nCount = sources->ReadUInt16();
#ifdef USE_NEO_SX // NEO: NSX - [NeoSoruceExchange]
if(pClient && pClient->SupportsSourceExchangeExt())
uPacketSXVersion = 4;
else // Note: Since the extended Format has variable length entries such a simpole integrity test can not be performed
#endif // NEO: NSX END
{
UINT uDataSize = (UINT)(sources->GetLength() - sources->GetPosition());
bool bError = false;
switch (uClientSXVersion){
case 1:
bError = nCount*(4+2+4+2) != uDataSize;
break;
case 2:
case 3:
bError = nCount*(4+2+4+2+16) != uDataSize;
break;
case 4:
bError = nCount*(4+2+4+2+16+1) != uDataSize;
break;
default:
ASSERT( false );
}
if (bError){
ASSERT( false );
if (thePrefs.GetVerbose()) {
CString strDbgClientInfo;
if (pClient)
strDbgClientInfo.Format(_T("%s, "), pClient->DbgGetClientInfo());
DebugLogWarning(_T("Received invalid/corrupt SX2 packet (v%u, count=%u, size=%u), %sFile=\"%s\""), uClientSXVersion, nCount, uDataSize, strDbgClientInfo, GetFileName());
}
return;
}
uPacketSXVersion = uClientSXVersion;
}
}
for (UINT i = 0; i < nCount; i++)
{
uint32 dwID = sources->ReadUInt32();
uint16 nPort = sources->ReadUInt16();
uint32 dwServerIP = 0; // sources->ReadUInt32();
uint16 nServerPort = 0; // sources->ReadUInt16();
#ifdef USE_NEO_SX // NEO: NSX - [NeoSoruceExchange]
uint32 dwIP = 0;
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
CAddress IPv6;
#endif // NEO: IP6 END
uint16 nUDPPort = 0;
uint16 nKadPort = 0;
uint32 dwBuddyIP = 0;
uint16 nBuddyPort = 0;
byte BuddyID[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(pClient && pClient->SupportsSourceExchangeExt())
{
uint8 tagcount = sources->ReadUInt8();
for (uint8 i = 0; i < tagcount; i++)
{
CTag temptag(sources, true);
switch (temptag.GetNameID())
{
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
case CT_EMULE_ADDRESS:
if(temptag.IsInt())
dwIP = temptag.GetInt();
break;
case CT_EMULE_UDPPORTS:
if(temptag.IsInt())
{
nKadPort = (uint16)(temptag.GetInt() >> 16);
nUDPPort = (uint16)temptag.GetInt();
}
break;
case CT_EMULE_BUDDYIP:
if(temptag.IsInt())
dwBuddyIP = temptag.GetInt();
break;
case CT_EMULE_BUDDYUDP:
if(temptag.IsInt())
nBuddyPort = (uint16)temptag.GetInt();
break;
case CT_EMULE_BUDDYID:
if(temptag.IsHash())
md4cpy(BuddyID, temptag.GetHash());
break;
#endif // NEO: NAT END
case CT_EMULE_SERVERIP:
if(temptag.IsInt())
dwServerIP = temptag.GetInt();
break;
case CT_EMULE_SERVERTCP:
if(temptag.IsInt())
dwServerIP = (uint16)temptag.GetInt();
break;
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
case CT_NEOMULE_IP_V6:
{
byte uIP[16];
md4cpy(uIP, temptag.GetHash());
IPv6 = CAddress(uIP);
break;
}
#endif // NEO: IP6 END
default:
AddDebugLogLine(false, _T("Ignoring unknown ExtSX Tag from: %s"), pClient->DbgGetClientInfo());
}
}
}
else
#endif // NEO: NSX END
{
dwServerIP = sources->ReadUInt32();
nServerPort = sources->ReadUInt16();
}
uchar achUserHash[16];
if (uPacketSXVersion >= 2)
sources->ReadHash16(achUserHash);
uint8 byCryptOptions = 0;
if (uPacketSXVersion >= 4)
byCryptOptions = sources->ReadUInt8();
// Clients send ID's in the Hyrbid format so highID clients with *.*.*.0 won't be falsely switched to a lowID..
if (uPacketSXVersion >= 3)
{
uint32 dwIDED2K = ntohl(dwID);
// check the HighID(IP) - "Filter LAN IPs" and "IPfilter" the received sources IP addresses
if (!IsLowID(dwID))
{
if (!IsGoodIP(dwIDED2K))
{
// check for 0-IP, localhost and optionally for LAN addresses
//if (thePrefs.GetLogFilteredIPs())
// AddDebugLogLine(false, _T("Ignored source (IP=%s) received via source exchange - bad IP"), ipstr(dwIDED2K));
continue;
}
if (theApp.ipfilter->IsFiltered(dwIDED2K))
{
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received via source exchange - IP filter (%s)"), ipstr(dwIDED2K), theApp.ipfilter->GetLastHit());
continue;
}
if (theApp.clientlist->IsBannedClient(dwIDED2K)){
#ifdef _DEBUG
if (thePrefs.GetLogBannedClients()){
CString strDbgClientInfo;
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
CUpDownClient* pClient = theApp.clientlist->FindClientByIP(CAddress(_ntohl(dwIDED2K)));
#else // NEO: IP6 END
CUpDownClient* pClient = theApp.clientlist->FindClientByIP(dwIDED2K);
#endif
if (pClient)
strDbgClientInfo.Format(L" - banned client %s", pClient->DbgGetClientInfo());
AddDebugLogLine(false, L"Ignored source (IP=%s) received via source exchange%s", ipstr(dwIDED2K), strDbgClientInfo);
}
#endif
continue;
}
}
// additionally check for LowID and own IP
if (!CanAddSource(dwID, nPort, dwServerIP, nServerPort, NULL, false))
{
//if (thePrefs.GetLogFilteredIPs())
// AddDebugLogLine(false, _T("Ignored source (IP=%s) received via source exchange"), ipstr(dwIDED2K));
continue;
}
}
else
{
// check the HighID(IP) - "Filter LAN IPs" and "IPfilter" the received sources IP addresses
if (!IsLowID(dwID))
{
if (!IsGoodIP(dwID))
{
// check for 0-IP, localhost and optionally for LAN addresses
//if (thePrefs.GetLogFilteredIPs())
// AddDebugLogLine(false, _T("Ignored source (IP=%s) received via source exchange - bad IP"), ipstr(dwID));
continue;
}
if (theApp.ipfilter->IsFiltered(dwID))
{
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Ignored source (IP=%s) received via source exchange - IP filter (%s)"), ipstr(dwID), theApp.ipfilter->GetLastHit());
continue;
}
if (theApp.clientlist->IsBannedClient(dwID)){
#ifdef _DEBUG
CString strDbgClientInfo;
if (thePrefs.GetLogBannedClients()){
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
CUpDownClient* pClient = theApp.clientlist->FindClientByIP(CAddress(_ntohl(dwID)));
#else // NEO: IP6 END
CUpDownClient* pClient = theApp.clientlist->FindClientByIP(dwID);
#endif
if (pClient)
strDbgClientInfo.Format(L" - banned client %s", pClient->DbgGetClientInfo());
AddDebugLogLine(false, L"Ignored source (IP=%s) received via source exchange%s", ipstr(dwID), strDbgClientInfo);
}
#endif
continue;
}
}
// additionally check for LowID and own IP
if (!CanAddSource(dwID, nPort, dwServerIP, nServerPort))
{
//if (thePrefs.GetLogFilteredIPs())
// AddDebugLogLine(false, _T("Ignored source (IP=%s) received via source exchange"), ipstr(dwID));
continue;
}
}
if (GetMaxSources() > GetSourceCount())
{
CUpDownClient* newsource;
if (uPacketSXVersion >= 3)
newsource = new CUpDownClient(this, nPort, dwID, dwServerIP, nServerPort, false);
else
newsource = new CUpDownClient(this, nPort, dwID, dwServerIP, nServerPort, true);
#ifdef USE_NEO_SX // NEO: NSX - [NeoSoruceExchange]
if(pClient && pClient->SupportsSourceExchangeExt())
{
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
#ifdef USE_IP_6 // NEO: IP6 - [IPv6]
if(dwIP)
newsource->SetIP(CAddress(_ntohl(dwIP)));
if(!IPv6.IsNull())
newsource->SetIPv6(IPv6);
#else // NEO: IP6 END
if(dwIP)
newsource->SetIP(dwIP);
#endif
if(nUDPPort)
newsource->SetUDPPort(nUDPPort);
if(nKadPort)
newsource->SetKadPort(nKadPort);
if(dwBuddyIP)
newsource->SetBuddyIP(dwBuddyIP);
if(nBuddyPort)
newsource->SetBuddyPort(nBuddyPort);
if(!isnulmd4(BuddyID))
newsource->SetBuddyID(BuddyID);
#endif // NEO: NAT END
}
#endif // NEO: NSX END
if (uPacketSXVersion >= 2)
newsource->SetUserHash(achUserHash);
if (uPacketSXVersion >= 4) {
#ifdef USE_NAT_T // NEO: NAT - [NatTraversal]
newsource->SetConnectOptions(byCryptOptions, true, pClient->SupportsSourceExchangeExt());
#else // NEO: NAT END
newsource->SetConnectOptions(byCryptOptions, true, false);
#endif
//if (thePrefs.GetDebugSourceExchange()) // remove this log later
// AddDebugLogLine(false, _T("Received CryptLayer aware (%u) source from V4 Sourceexchange (%s)"), byCryptOptions, newsource->DbgGetClientInfo());
}
newsource->SetSourceFrom(SF_SOURCE_EXCHANGE);
theApp.downloadqueue->CheckAndAddSource(this, newsource);
}
else
break;
}
}