2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2011 Angel Vidal ( kry@amule.org )
5 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include <ec/cpp/ECTag.h> // Needed for CECTag
28 #include <ec/cpp/ECSpecialTags.h> // Needed for special EC tag creator classes
31 // Since there are only constructors defined here,
32 // removing everything from non-local builds.
35 #include "Server.h" // Needed for CServer
36 #include "PartFile.h" // Needed for CPartFile
37 #include "ServerConnect.h" // Needed for CServerConnect
38 #include "updownclient.h" // Needed for CUpDownClient
39 #include "UploadQueue.h" // Needed for CUploadQueue
40 #include "SharedFileList.h"
41 #include "SearchList.h"
44 #include "kademlia/kademlia/Kademlia.h"
47 // used for webserver, amulecmd
48 CEC_Server_Tag::CEC_Server_Tag(const CServer
*server
, EC_DETAIL_LEVEL detail_level
) :
49 CECTag(EC_TAG_SERVER
, EC_IPv4_t(server
->GetIP(), server
->GetPort()))
55 switch (detail_level
) {
56 case EC_DETAIL_INC_UPDATE
:
57 // should not get here
60 case EC_DETAIL_UPDATE
:
61 if ((tmpInt
= server
->GetPing()) != 0) {
62 AddTag(CECTag(EC_TAG_SERVER_PING
, tmpInt
));
64 if ((tmpShort
= (uint8
)server
->GetFailedCount()) != 0) {
65 AddTag(CECTag(EC_TAG_SERVER_FAILED
, tmpShort
));
70 if ((tmpInt
= server
->GetPing()) != 0) {
71 AddTag(CECTag(EC_TAG_SERVER_PING
, tmpInt
));
73 if ((tmpShort
= (uint8
)server
->GetPreferences()) != SRV_PR_NORMAL
) {
74 AddTag(CECTag(EC_TAG_SERVER_PRIO
, tmpShort
));
76 if ((tmpShort
= (uint8
)server
->GetFailedCount()) != 0) {
77 AddTag(CECTag(EC_TAG_SERVER_FAILED
, tmpShort
));
79 if ((tmpShort
= (server
->IsStaticMember() ? 1 : 0)) != 0) {
80 AddTag(CECTag(EC_TAG_SERVER_STATIC
, tmpShort
));
82 if (!(tmpStr
= server
->GetVersion()).IsEmpty()) {
83 AddTag(CECTag(EC_TAG_SERVER_VERSION
, tmpStr
));
85 if (!(tmpStr
= server
->GetDescription()).IsEmpty()) {
86 AddTag(CECTag(EC_TAG_SERVER_DESC
, tmpStr
));
88 if ((tmpInt
= server
->GetUsers()) != 0) {
89 AddTag(CECTag(EC_TAG_SERVER_USERS
, tmpInt
));
91 if ((tmpInt
= server
->GetMaxUsers()) != 0) {
92 AddTag(CECTag(EC_TAG_SERVER_USERS_MAX
, tmpInt
));
94 if ((tmpInt
= server
->GetFiles()) != 0) {
95 AddTag(CECTag(EC_TAG_SERVER_FILES
, tmpInt
));
98 if (!(tmpStr
= server
->GetListName()).IsEmpty()) {
99 AddTag(CECTag(EC_TAG_SERVER_NAME
, tmpStr
));
104 // used for amulegui (EC_DETAIL_INC_UPDATE)
105 CEC_Server_Tag::CEC_Server_Tag(const CServer
*server
, CValueMap
*valuemap
) :
106 CECTag(EC_TAG_SERVER
, server
->ECID())
108 AddTag(EC_TAG_SERVER_NAME
, server
->GetListName(), valuemap
);
109 AddTag(EC_TAG_SERVER_DESC
, server
->GetDescription(), valuemap
);
110 AddTag(EC_TAG_SERVER_VERSION
, server
->GetVersion(), valuemap
);
111 AddTag(EC_TAG_SERVER_IP
, server
->GetIP(), valuemap
);
112 AddTag(EC_TAG_SERVER_PORT
, server
->GetPort(), valuemap
);
113 AddTag(EC_TAG_SERVER_PING
, server
->GetPing(), valuemap
);
114 AddTag(EC_TAG_SERVER_PRIO
, server
->GetPreferences(), valuemap
);
115 AddTag(EC_TAG_SERVER_FAILED
, server
->GetFailedCount(), valuemap
);
116 AddTag(EC_TAG_SERVER_STATIC
, server
->IsStaticMember(), valuemap
);
117 AddTag(EC_TAG_SERVER_USERS
, server
->GetUsers(), valuemap
);
118 AddTag(EC_TAG_SERVER_USERS_MAX
, server
->GetMaxUsers(), valuemap
);
119 AddTag(EC_TAG_SERVER_FILES
, server
->GetFiles(), valuemap
);
123 CEC_ConnState_Tag::CEC_ConnState_Tag(EC_DETAIL_LEVEL detail_level
) : CECTag(EC_TAG_CONNSTATE
,
125 (theApp
->IsConnectedED2K() ? 0x01 : 0x00)
127 (theApp
->serverconnect
->IsConnecting() ? 0x02 : 0x00)
129 (theApp
->IsConnectedKad() ? 0x04 : 0x00)
131 (Kademlia::CKademlia::IsFirewalled() ? 0x08 : 0x00)
133 (Kademlia::CKademlia::IsRunning() ? 0x10 : 0x00)
136 if (theApp
->IsConnectedED2K()) {
137 if ( theApp
->serverconnect
->GetCurrentServer() ) {
138 if (detail_level
== EC_DETAIL_INC_UPDATE
) {
139 // Send no full server tag, just the ECID of the connected server
140 AddTag(CECTag(EC_TAG_SERVER
, theApp
->serverconnect
->GetCurrentServer()->ECID()));
142 AddTag(CEC_Server_Tag(theApp
->serverconnect
->GetCurrentServer(), detail_level
));
145 AddTag(CECTag(EC_TAG_ED2K_ID
, theApp
->GetED2KID()));
146 } else if (theApp
->serverconnect
->IsConnecting()) {
147 AddTag(CECTag(EC_TAG_ED2K_ID
, 0xffffffff));
150 AddTag(CECTag(EC_TAG_CLIENT_ID
, theApp
->GetID()));
152 if (Kademlia::CKademlia::IsRunning()) {
153 AddTag(CECTag(EC_TAG_KAD_ID
, Kademlia::CKademlia::GetKadID()));
157 CEC_PartFile_Tag::CEC_PartFile_Tag(const CPartFile
*file
, EC_DETAIL_LEVEL detail_level
, CValueMap
*valuemap
)
159 CEC_SharedFile_Tag(file
, detail_level
, valuemap
, EC_TAG_PARTFILE
)
161 AddTag(EC_TAG_PARTFILE_STATUS
, file
->GetStatus(), valuemap
);
162 AddTag(EC_TAG_PARTFILE_STOPPED
, file
->IsStopped(), valuemap
);
164 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT
, file
->GetSourceCount(), valuemap
);
165 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT_NOT_CURRENT
, file
->GetNotCurrentSourcesCount(), valuemap
);
166 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT_XFER
, file
->GetTransferingSrcCount(), valuemap
);
167 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT_A4AF
, file
->GetSrcA4AFCount(), valuemap
);
169 if ( (file
->GetTransferingSrcCount() > 0) || (detail_level
!= EC_DETAIL_UPDATE
) || valuemap
) {
171 AddTag(EC_TAG_PARTFILE_SIZE_XFER
, file
->GetTransferred(), valuemap
);
172 AddTag(EC_TAG_PARTFILE_SIZE_DONE
, file
->GetCompletedSize(), valuemap
);
173 AddTag(EC_TAG_PARTFILE_SPEED
, (uint64_t)(file
->GetKBpsDown()*1024), valuemap
);
176 AddTag(EC_TAG_PARTFILE_PRIO
, (file
->IsAutoDownPriority() ?
177 file
->GetDownPriority() + 10 : file
->GetDownPriority()), valuemap
);
179 AddTag(EC_TAG_PARTFILE_CAT
, file
->GetCategory(), valuemap
);
180 AddTag(EC_TAG_PARTFILE_LAST_SEEN_COMP
, file
->lastseencomplete
, valuemap
);
181 AddTag(EC_TAG_PARTFILE_LAST_RECV
, file
->GetLastChangeDatetime(), valuemap
);
182 AddTag(EC_TAG_PARTFILE_DOWNLOAD_ACTIVE
, file
->GetDlActiveTime(), valuemap
);
183 AddTag(EC_TAG_PARTFILE_AVAILABLE_PARTS
, file
->GetAvailablePartCount(), valuemap
);
184 AddTag(EC_TAG_PARTFILE_HASHED_PART_COUNT
, file
->GetHashingProgress(), valuemap
);
186 AddTag(EC_TAG_PARTFILE_LOST_CORRUPTION
, file
->GetLostDueToCorruption(), valuemap
);
187 AddTag(EC_TAG_PARTFILE_GAINED_COMPRESSION
, file
->GetGainDueToCompression(), valuemap
);
188 AddTag(EC_TAG_PARTFILE_SAVED_ICH
, file
->TotalPacketsSavedDueToICH(), valuemap
);
189 AddTag(EC_TAG_PARTFILE_A4AFAUTO
, file
->IsA4AFAuto(), valuemap
);
192 CECEmptyTag
sc(EC_TAG_PARTFILE_COMMENTS
);
195 file
->GetRatingAndComments(list
);
196 for (FileRatingList::const_iterator it
= list
.begin(); it
!= list
.end(); ++it
) {
197 // Tag children are evaluated by index, not by name
198 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, it
->UserName
));
199 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, it
->FileName
));
200 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, (uint64
) it
->Rating
));
201 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, it
->Comment
));
203 AddTag(sc
, valuemap
);
205 if (detail_level
== EC_DETAIL_UPDATE
) {
209 AddTag(EC_TAG_PARTFILE_PARTMETID
, file
->GetPartMetNumber(), valuemap
);
212 CECEmptyTag
a4afTag(EC_TAG_PARTFILE_A4AF_SOURCES
);
213 const CKnownFile::SourceSet
& a4afSources
= file
->GetA4AFList();
214 for (CKnownFile::SourceSet::const_iterator it
= a4afSources
.begin(); it
!= a4afSources
.end(); ++it
) {
215 a4afTag
.AddTag(CECTag(EC_TAG_ECID
, it
->ECID()));
217 AddTag(a4afTag
, valuemap
);
220 CEC_SharedFile_Tag::CEC_SharedFile_Tag(const CKnownFile
*file
, EC_DETAIL_LEVEL detail_level
,
221 CValueMap
*valuemap
, ec_tagname_t name
)
222 : CECTag(name
, file
->ECID())
224 AddTag(EC_TAG_KNOWNFILE_REQ_COUNT
, file
->statistic
.GetRequests(), valuemap
);
225 AddTag(EC_TAG_KNOWNFILE_REQ_COUNT_ALL
, file
->statistic
.GetAllTimeRequests(), valuemap
);
227 AddTag(EC_TAG_KNOWNFILE_ACCEPT_COUNT
, file
->statistic
.GetAccepts(), valuemap
);
228 AddTag(EC_TAG_KNOWNFILE_ACCEPT_COUNT_ALL
, file
->statistic
.GetAllTimeAccepts(), valuemap
);
230 AddTag(EC_TAG_KNOWNFILE_XFERRED
, file
->statistic
.GetTransferred(), valuemap
);
231 AddTag(EC_TAG_KNOWNFILE_XFERRED_ALL
, file
->statistic
.GetAllTimeTransferred(), valuemap
);
232 AddTag(EC_TAG_KNOWNFILE_AICH_MASTERHASH
, file
->GetAICHMasterHash(), valuemap
);
234 AddTag(EC_TAG_KNOWNFILE_PRIO
,
235 (uint8
)(file
->IsAutoUpPriority() ? file
->GetUpPriority() + 10 : file
->GetUpPriority()), valuemap
);
237 AddTag(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_LOW
, file
->m_nCompleteSourcesCountLo
, valuemap
);
238 AddTag(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_HIGH
, file
->m_nCompleteSourcesCountHi
, valuemap
);
239 AddTag(EC_TAG_KNOWNFILE_COMPLETE_SOURCES
, file
->m_nCompleteSourcesCount
, valuemap
);
241 AddTag(EC_TAG_KNOWNFILE_ON_QUEUE
, file
->GetQueuedCount(), valuemap
);
243 if (detail_level
== EC_DETAIL_UPDATE
) {
247 AddTag(EC_TAG_PARTFILE_NAME
,file
->GetFileName().GetPrintable(), valuemap
);
248 AddTag(EC_TAG_PARTFILE_HASH
, file
->GetFileHash(), valuemap
);
249 AddTag(EC_TAG_KNOWNFILE_FILENAME
,
250 file
->IsPartFile() ? wxString(CFormat(wxT("%s")) % static_cast<const CPartFile
*>(file
)->GetPartMetFileName().RemoveExt())
251 : file
->GetFilePath().GetPrintable(),
254 AddTag(EC_TAG_PARTFILE_SIZE_FULL
, file
->GetFileSize(), valuemap
);
256 AddTag(EC_TAG_PARTFILE_ED2K_LINK
,
257 theApp
->CreateED2kLink(file
, (theApp
->IsConnectedED2K() && !theApp
->serverconnect
->IsLowID())), valuemap
);
259 AddTag(EC_TAG_KNOWNFILE_COMMENT
, file
->GetFileComment(), valuemap
);
260 AddTag(EC_TAG_KNOWNFILE_RATING
, file
->GetFileRating(), valuemap
);
263 CEC_UpDownClient_Tag::CEC_UpDownClient_Tag(const CUpDownClient
* client
, EC_DETAIL_LEVEL detail_level
, CValueMap
*valuemap
) :
264 CECTag(EC_TAG_CLIENT
, client
->ECID())
267 AddTag(CECTag(EC_TAG_CLIENT_NAME
, client
->GetUserName()), valuemap
);
268 AddTag(CECTag(EC_TAG_CLIENT_HASH
, client
->GetUserHash()), valuemap
);
269 AddTag(CECTag(EC_TAG_CLIENT_USER_ID
, client
->GetUserIDHybrid()), valuemap
);
270 AddTag(CECTag(EC_TAG_CLIENT_SCORE
, client
->GetScore()), valuemap
);
271 AddTag(CECTag(EC_TAG_CLIENT_SOFTWARE
, client
->GetClientSoft()), valuemap
);
272 AddTag(CECTag(EC_TAG_CLIENT_SOFT_VER_STR
, client
->GetSoftVerStr()), valuemap
);
273 AddTag(CECTag(EC_TAG_CLIENT_USER_IP
, client
->GetIP()), valuemap
);
274 AddTag(CECTag(EC_TAG_CLIENT_USER_PORT
, client
->GetUserPort()), valuemap
);
275 AddTag(CECTag(EC_TAG_CLIENT_FROM
, (uint64
)client
->GetSourceFrom()), valuemap
);
276 AddTag(CECTag(EC_TAG_CLIENT_SERVER_IP
, client
->GetServerIP()), valuemap
);
277 AddTag(CECTag(EC_TAG_CLIENT_SERVER_PORT
, client
->GetServerPort()), valuemap
);
278 AddTag(CECTag(EC_TAG_CLIENT_SERVER_NAME
, client
->GetServerName()), valuemap
);
280 // Transfers to Client
281 AddTag(CECTag(EC_TAG_CLIENT_UP_SPEED
, client
->GetUploadDatarate()), valuemap
);
282 if (client
->GetDownloadState() == DS_DOWNLOADING
|| valuemap
) {
283 AddTag(CECTag(EC_TAG_CLIENT_DOWN_SPEED
, (double)(client
->GetKBpsDown())), valuemap
);
285 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_SESSION
, client
->GetSessionUp()), valuemap
);
286 AddTag(CECTag(EC_TAG_PARTFILE_SIZE_XFER
, client
->GetTransferredDown()), valuemap
);
287 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_TOTAL
, client
->GetUploadedTotal()), valuemap
);
288 AddTag(CECTag(EC_TAG_CLIENT_DOWNLOAD_TOTAL
, client
->GetDownloadedTotal()), valuemap
);
290 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_STATE
, client
->GetUploadState()), valuemap
);
291 AddTag(CECTag(EC_TAG_CLIENT_DOWNLOAD_STATE
, client
->GetDownloadState()), valuemap
);
292 AddTag(CECTag(EC_TAG_CLIENT_IDENT_STATE
, (uint64
) client
->GetCurrentIdentState()), valuemap
);
293 AddTag(CECTag(EC_TAG_CLIENT_EXT_PROTOCOL
, client
->ExtProtocolAvailable()), valuemap
);
294 // These are not needed atm. Keep them for now, maybe columns get reintroduced in client view.
295 //AddTag(CECTag(EC_TAG_CLIENT_WAIT_TIME, client->GetWaitTime()), valuemap);
296 //AddTag(CECTag(EC_TAG_CLIENT_XFER_TIME, client->GetUpStartTimeDelay()), valuemap);
297 //AddTag(CECTag(EC_TAG_CLIENT_QUEUE_TIME, (uint64)(::GetTickCount() - client->GetWaitStartTime())), valuemap);
298 //AddTag(CECTag(EC_TAG_CLIENT_LAST_TIME, (uint64)(::GetTickCount() - client->GetLastUpRequest())), valuemap);
299 AddTag(CECTag(EC_TAG_CLIENT_WAITING_POSITION
, client
->GetUploadQueueWaitingPosition()), valuemap
);
300 AddTag(CECTag(EC_TAG_CLIENT_REMOTE_QUEUE_RANK
, client
->IsRemoteQueueFull() ? (uint16
)0xffff : client
->GetRemoteQueueRank()), valuemap
);
301 AddTag(CECTag(EC_TAG_CLIENT_OLD_REMOTE_QUEUE_RANK
, client
->GetOldRemoteQueueRank()), valuemap
);
302 AddTag(CECTag(EC_TAG_CLIENT_OBFUSCATION_STATUS
, client
->GetObfuscationStatus()), valuemap
);
303 AddTag(CECTag(EC_TAG_CLIENT_KAD_PORT
, client
->GetKadPort()), valuemap
);
304 AddTag(CECTag(EC_TAG_CLIENT_FRIEND_SLOT
, client
->GetFriendSlot()), valuemap
);
306 if (detail_level
== EC_DETAIL_UPDATE
) {
309 const CKnownFile
* file
= client
->GetUploadFile();
311 AddTag(CECTag(EC_TAG_PARTFILE_NAME
, file
->GetFileName().GetPrintable()), valuemap
);
312 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_FILE
, file
->ECID()), valuemap
);
314 AddTag(CECIntTag(EC_TAG_CLIENT_UPLOAD_FILE
, 0), valuemap
);
316 const CPartFile
* pfile
= client
->GetRequestFile();
317 AddTag(CECTag(EC_TAG_CLIENT_REQUEST_FILE
, pfile
? pfile
->ECID() : 0), valuemap
);
318 AddTag(CECTag(EC_TAG_CLIENT_REMOTE_FILENAME
, client
->GetClientFilename()), valuemap
);
320 if (detail_level
!= EC_DETAIL_INC_UPDATE
) {
323 AddTag(CECTag(EC_TAG_CLIENT_DISABLE_VIEW_SHARED
, client
->HasDisabledSharedFiles()), valuemap
);
324 AddTag(CECTag(EC_TAG_CLIENT_VERSION
, client
->GetVersion()), valuemap
);
325 AddTag(CECTag(EC_TAG_CLIENT_MOD_VERSION
, client
->GetClientModString()), valuemap
);
326 AddTag(CECTag(EC_TAG_CLIENT_OS_INFO
, client
->GetClientOSInfo()), valuemap
);
327 AddTag(CECTag(EC_TAG_CLIENT_AVAILABLE_PARTS
, client
->GetAvailablePartCount()), valuemap
);
329 const BitVector
& partStatus
= client
->GetPartStatus();
330 if (partStatus
.size() == pfile
->GetPartCount()) {
331 if (partStatus
.AllTrue()) {
332 // send just an empty tag for a full source
333 AddTag(CECEmptyTag(EC_TAG_CLIENT_PART_STATUS
), valuemap
);
335 AddTag(CECTag(EC_TAG_CLIENT_PART_STATUS
, partStatus
.SizeBuffer(), partStatus
.GetBuffer()), valuemap
);
338 AddTag(CECTag(EC_TAG_CLIENT_NEXT_REQUESTED_PART
, client
->GetNextRequestedPart()), valuemap
);
339 AddTag(CECTag(EC_TAG_CLIENT_LAST_DOWNLOADING_PART
, client
->GetLastDownloadingPart()), valuemap
);
342 const BitVector
& upPartStatus
= client
->GetUpPartStatus();
343 if (upPartStatus
.size() == file
->GetPartCount()) {
344 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_PART_STATUS
, upPartStatus
.SizeBuffer(), upPartStatus
.GetBuffer()), valuemap
);
352 CEC_SearchFile_Tag::CEC_SearchFile_Tag(const CSearchFile
*file
, EC_DETAIL_LEVEL detail_level
, CValueMap
*valuemap
) : CECTag(EC_TAG_SEARCHFILE
, file
->ECID())
354 AddTag(CECTag(EC_TAG_PARTFILE_SOURCE_COUNT
, file
->GetSourceCount()), valuemap
);
355 AddTag(CECTag(EC_TAG_PARTFILE_SOURCE_COUNT_XFER
, file
->GetCompleteSourceCount()), valuemap
);
356 AddTag(CECTag(EC_TAG_PARTFILE_STATUS
, (uint32
)file
->GetDownloadStatus()), valuemap
);
358 if (detail_level
== EC_DETAIL_UPDATE
) {
362 AddTag(CECTag(EC_TAG_PARTFILE_NAME
, file
->GetFileName().GetPrintable()), valuemap
);
363 AddTag(CECTag(EC_TAG_PARTFILE_SIZE_FULL
, file
->GetFileSize()), valuemap
);
364 AddTag(EC_TAG_PARTFILE_HASH
, file
->GetFileHash(), valuemap
);
365 if (file
->GetParent()) {
366 AddTag(EC_TAG_SEARCH_PARENT
, file
->GetParent()->ECID(), valuemap
);
373 CEC_Friend_Tag::CEC_Friend_Tag(const CFriend
* Friend
, CValueMap
* valuemap
) : CECTag(EC_TAG_FRIEND
, Friend
->ECID())
375 AddTag(EC_TAG_FRIEND_NAME
, Friend
->GetName(), valuemap
);
376 AddTag(EC_TAG_FRIEND_HASH
, Friend
->GetUserHash(), valuemap
);
377 AddTag(EC_TAG_FRIEND_IP
, Friend
->GetIP(), valuemap
);
378 AddTag(EC_TAG_FRIEND_PORT
, Friend
->GetPort(), valuemap
);
379 const CClientRef
& linkedClient
= Friend
->GetLinkedClient();
380 AddTag(EC_TAG_FRIEND_CLIENT
, linkedClient
.IsLinked() ? linkedClient
.ECID() : 0, valuemap
);
383 // File_checked_for_headers