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()));
153 CEC_PartFile_Tag::CEC_PartFile_Tag(const CPartFile
*file
, EC_DETAIL_LEVEL detail_level
, CValueMap
*valuemap
)
155 CEC_SharedFile_Tag(file
, detail_level
, valuemap
, EC_TAG_PARTFILE
)
157 AddTag(EC_TAG_PARTFILE_STATUS
, file
->GetStatus(), valuemap
);
158 AddTag(EC_TAG_PARTFILE_STOPPED
, file
->IsStopped(), valuemap
);
160 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT
, file
->GetSourceCount(), valuemap
);
161 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT_NOT_CURRENT
, file
->GetNotCurrentSourcesCount(), valuemap
);
162 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT_XFER
, file
->GetTransferingSrcCount(), valuemap
);
163 AddTag(EC_TAG_PARTFILE_SOURCE_COUNT_A4AF
, file
->GetSrcA4AFCount(), valuemap
);
165 if ( (file
->GetTransferingSrcCount() > 0) || (detail_level
!= EC_DETAIL_UPDATE
) || valuemap
) {
167 AddTag(EC_TAG_PARTFILE_SIZE_XFER
, file
->GetTransferred(), valuemap
);
168 AddTag(EC_TAG_PARTFILE_SIZE_DONE
, file
->GetCompletedSize(), valuemap
);
169 AddTag(EC_TAG_PARTFILE_SPEED
, (uint64_t)(file
->GetKBpsDown()*1024), valuemap
);
172 AddTag(EC_TAG_PARTFILE_PRIO
, (file
->IsAutoDownPriority() ?
173 file
->GetDownPriority() + 10 : file
->GetDownPriority()), valuemap
);
175 AddTag(EC_TAG_PARTFILE_CAT
, file
->GetCategory(), valuemap
);
176 AddTag(EC_TAG_PARTFILE_LAST_SEEN_COMP
, file
->lastseencomplete
, valuemap
);
177 AddTag(EC_TAG_PARTFILE_LAST_RECV
, file
->GetLastChangeDatetime(), valuemap
);
178 AddTag(EC_TAG_PARTFILE_DOWNLOAD_ACTIVE
, file
->GetDlActiveTime(), valuemap
);
179 AddTag(EC_TAG_PARTFILE_AVAILABLE_PARTS
, file
->GetAvailablePartCount(), valuemap
);
180 AddTag(EC_TAG_PARTFILE_HASHED_PART_COUNT
, file
->GetHashingProgress(), valuemap
);
182 AddTag(EC_TAG_PARTFILE_LOST_CORRUPTION
, file
->GetLostDueToCorruption(), valuemap
);
183 AddTag(EC_TAG_PARTFILE_GAINED_COMPRESSION
, file
->GetGainDueToCompression(), valuemap
);
184 AddTag(EC_TAG_PARTFILE_SAVED_ICH
, file
->TotalPacketsSavedDueToICH(), valuemap
);
185 AddTag(EC_TAG_PARTFILE_A4AFAUTO
, file
->IsA4AFAuto(), valuemap
);
188 CECEmptyTag
sc(EC_TAG_PARTFILE_COMMENTS
);
191 file
->GetRatingAndComments(list
);
192 for (FileRatingList::const_iterator it
= list
.begin(); it
!= list
.end(); ++it
) {
193 // Tag children are evaluated by index, not by name
194 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, it
->UserName
));
195 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, it
->FileName
));
196 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, (uint64
) it
->Rating
));
197 sc
.AddTag(CECTag(EC_TAG_PARTFILE_COMMENTS
, it
->Comment
));
199 AddTag(sc
, valuemap
);
201 if (detail_level
== EC_DETAIL_UPDATE
) {
205 AddTag(EC_TAG_PARTFILE_PARTMETID
, file
->GetPartMetNumber(), valuemap
);
208 CECEmptyTag
a4afTag(EC_TAG_PARTFILE_A4AF_SOURCES
);
209 const CKnownFile::SourceSet
& a4afSources
= file
->GetA4AFList();
210 for (CKnownFile::SourceSet::const_iterator it
= a4afSources
.begin(); it
!= a4afSources
.end(); ++it
) {
211 a4afTag
.AddTag(CECTag(EC_TAG_ECID
, it
->ECID()));
213 AddTag(a4afTag
, valuemap
);
216 CEC_SharedFile_Tag::CEC_SharedFile_Tag(const CKnownFile
*file
, EC_DETAIL_LEVEL detail_level
,
217 CValueMap
*valuemap
, ec_tagname_t name
)
218 : CECTag(name
, file
->ECID())
220 AddTag(EC_TAG_KNOWNFILE_REQ_COUNT
, file
->statistic
.GetRequests(), valuemap
);
221 AddTag(EC_TAG_KNOWNFILE_REQ_COUNT_ALL
, file
->statistic
.GetAllTimeRequests(), valuemap
);
223 AddTag(EC_TAG_KNOWNFILE_ACCEPT_COUNT
, file
->statistic
.GetAccepts(), valuemap
);
224 AddTag(EC_TAG_KNOWNFILE_ACCEPT_COUNT_ALL
, file
->statistic
.GetAllTimeAccepts(), valuemap
);
226 AddTag(EC_TAG_KNOWNFILE_XFERRED
, file
->statistic
.GetTransferred(), valuemap
);
227 AddTag(EC_TAG_KNOWNFILE_XFERRED_ALL
, file
->statistic
.GetAllTimeTransferred(), valuemap
);
228 AddTag(EC_TAG_KNOWNFILE_AICH_MASTERHASH
, file
->GetAICHMasterHash(), valuemap
);
230 AddTag(EC_TAG_KNOWNFILE_PRIO
,
231 (uint8
)(file
->IsAutoUpPriority() ? file
->GetUpPriority() + 10 : file
->GetUpPriority()), valuemap
);
233 AddTag(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_LOW
, file
->m_nCompleteSourcesCountLo
, valuemap
);
234 AddTag(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_HIGH
, file
->m_nCompleteSourcesCountHi
, valuemap
);
235 AddTag(EC_TAG_KNOWNFILE_COMPLETE_SOURCES
, file
->m_nCompleteSourcesCount
, valuemap
);
237 AddTag(EC_TAG_KNOWNFILE_ON_QUEUE
, file
->GetQueuedCount(), valuemap
);
239 if (detail_level
== EC_DETAIL_UPDATE
) {
243 AddTag(EC_TAG_PARTFILE_NAME
,file
->GetFileName().GetPrintable(), valuemap
);
244 AddTag(EC_TAG_PARTFILE_HASH
, file
->GetFileHash(), valuemap
);
245 AddTag(EC_TAG_KNOWNFILE_FILENAME
,
246 file
->IsPartFile() ? wxString(CFormat(wxT("%s")) % static_cast<const CPartFile
*>(file
)->GetPartMetFileName().RemoveExt())
247 : file
->GetFilePath().GetPrintable(),
250 AddTag(EC_TAG_PARTFILE_SIZE_FULL
, file
->GetFileSize(), valuemap
);
252 AddTag(EC_TAG_PARTFILE_ED2K_LINK
,
253 theApp
->CreateED2kLink(file
, (theApp
->IsConnectedED2K() && !theApp
->serverconnect
->IsLowID())), valuemap
);
255 AddTag(EC_TAG_KNOWNFILE_COMMENT
, file
->GetFileComment(), valuemap
);
256 AddTag(EC_TAG_KNOWNFILE_RATING
, file
->GetFileRating(), valuemap
);
259 CEC_UpDownClient_Tag::CEC_UpDownClient_Tag(const CUpDownClient
* client
, EC_DETAIL_LEVEL detail_level
, CValueMap
*valuemap
) :
260 CECTag(EC_TAG_CLIENT
, client
->ECID())
263 AddTag(CECTag(EC_TAG_CLIENT_NAME
, client
->GetUserName()), valuemap
);
264 AddTag(CECTag(EC_TAG_CLIENT_HASH
, client
->GetUserHash()), valuemap
);
265 AddTag(CECTag(EC_TAG_CLIENT_USER_ID
, client
->GetUserIDHybrid()), valuemap
);
266 AddTag(CECTag(EC_TAG_CLIENT_SCORE
, client
->GetScore()), valuemap
);
267 AddTag(CECTag(EC_TAG_CLIENT_SOFTWARE
, client
->GetClientSoft()), valuemap
);
268 AddTag(CECTag(EC_TAG_CLIENT_SOFT_VER_STR
, client
->GetSoftVerStr()), valuemap
);
269 AddTag(CECTag(EC_TAG_CLIENT_USER_IP
, client
->GetIP()), valuemap
);
270 AddTag(CECTag(EC_TAG_CLIENT_USER_PORT
, client
->GetUserPort()), valuemap
);
271 AddTag(CECTag(EC_TAG_CLIENT_FROM
, (uint64
)client
->GetSourceFrom()), valuemap
);
272 AddTag(CECTag(EC_TAG_CLIENT_SERVER_IP
, client
->GetServerIP()), valuemap
);
273 AddTag(CECTag(EC_TAG_CLIENT_SERVER_PORT
, client
->GetServerPort()), valuemap
);
274 AddTag(CECTag(EC_TAG_CLIENT_SERVER_NAME
, client
->GetServerName()), valuemap
);
276 // Transfers to Client
277 AddTag(CECTag(EC_TAG_CLIENT_UP_SPEED
, client
->GetUploadDatarate()), valuemap
);
278 if (client
->GetDownloadState() == DS_DOWNLOADING
|| valuemap
) {
279 AddTag(CECTag(EC_TAG_CLIENT_DOWN_SPEED
, (double)(client
->GetKBpsDown())), valuemap
);
281 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_SESSION
, client
->GetSessionUp()), valuemap
);
282 AddTag(CECTag(EC_TAG_PARTFILE_SIZE_XFER
, client
->GetTransferredDown()), valuemap
);
283 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_TOTAL
, client
->GetUploadedTotal()), valuemap
);
284 AddTag(CECTag(EC_TAG_CLIENT_DOWNLOAD_TOTAL
, client
->GetDownloadedTotal()), valuemap
);
286 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_STATE
, client
->GetUploadState()), valuemap
);
287 AddTag(CECTag(EC_TAG_CLIENT_DOWNLOAD_STATE
, client
->GetDownloadState()), valuemap
);
288 AddTag(CECTag(EC_TAG_CLIENT_IDENT_STATE
, (uint64
) client
->GetCurrentIdentState()), valuemap
);
289 AddTag(CECTag(EC_TAG_CLIENT_EXT_PROTOCOL
, client
->ExtProtocolAvailable()), valuemap
);
290 // These are not needed atm. Keep them for now, maybe columns get reintroduced in client view.
291 //AddTag(CECTag(EC_TAG_CLIENT_WAIT_TIME, client->GetWaitTime()), valuemap);
292 //AddTag(CECTag(EC_TAG_CLIENT_XFER_TIME, client->GetUpStartTimeDelay()), valuemap);
293 //AddTag(CECTag(EC_TAG_CLIENT_QUEUE_TIME, (uint64)(::GetTickCount() - client->GetWaitStartTime())), valuemap);
294 //AddTag(CECTag(EC_TAG_CLIENT_LAST_TIME, (uint64)(::GetTickCount() - client->GetLastUpRequest())), valuemap);
295 AddTag(CECTag(EC_TAG_CLIENT_WAITING_POSITION
, client
->GetUploadQueueWaitingPosition()), valuemap
);
296 AddTag(CECTag(EC_TAG_CLIENT_REMOTE_QUEUE_RANK
, client
->IsRemoteQueueFull() ? (uint16
)0xffff : client
->GetRemoteQueueRank()), valuemap
);
297 AddTag(CECTag(EC_TAG_CLIENT_OLD_REMOTE_QUEUE_RANK
, client
->GetOldRemoteQueueRank()), valuemap
);
298 AddTag(CECTag(EC_TAG_CLIENT_OBFUSCATION_STATUS
, client
->GetObfuscationStatus()), valuemap
);
299 AddTag(CECTag(EC_TAG_CLIENT_KAD_PORT
, client
->GetKadPort()), valuemap
);
300 AddTag(CECTag(EC_TAG_CLIENT_FRIEND_SLOT
, client
->GetFriendSlot()), valuemap
);
302 if (detail_level
== EC_DETAIL_UPDATE
) {
305 const CKnownFile
* file
= client
->GetUploadFile();
307 AddTag(CECTag(EC_TAG_PARTFILE_NAME
, file
->GetFileName().GetPrintable()), valuemap
);
308 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_FILE
, file
->ECID()), valuemap
);
310 AddTag(CECIntTag(EC_TAG_CLIENT_UPLOAD_FILE
, 0), valuemap
);
312 const CPartFile
* pfile
= client
->GetRequestFile();
313 AddTag(CECTag(EC_TAG_CLIENT_REQUEST_FILE
, pfile
? pfile
->ECID() : 0), valuemap
);
314 AddTag(CECTag(EC_TAG_CLIENT_REMOTE_FILENAME
, client
->GetClientFilename()), valuemap
);
316 if (detail_level
!= EC_DETAIL_INC_UPDATE
) {
319 AddTag(CECTag(EC_TAG_CLIENT_DISABLE_VIEW_SHARED
, client
->HasDisabledSharedFiles()), valuemap
);
320 AddTag(CECTag(EC_TAG_CLIENT_VERSION
, client
->GetVersion()), valuemap
);
321 AddTag(CECTag(EC_TAG_CLIENT_MOD_VERSION
, client
->GetClientModString()), valuemap
);
322 AddTag(CECTag(EC_TAG_CLIENT_OS_INFO
, client
->GetClientOSInfo()), valuemap
);
323 AddTag(CECTag(EC_TAG_CLIENT_AVAILABLE_PARTS
, client
->GetAvailablePartCount()), valuemap
);
325 const BitVector
& partStatus
= client
->GetPartStatus();
326 if (partStatus
.size() == pfile
->GetPartCount()) {
327 if (partStatus
.AllTrue()) {
328 // send just an empty tag for a full source
329 AddTag(CECEmptyTag(EC_TAG_CLIENT_PART_STATUS
), valuemap
);
331 AddTag(CECTag(EC_TAG_CLIENT_PART_STATUS
, partStatus
.SizeBuffer(), partStatus
.GetBuffer()), valuemap
);
334 AddTag(CECTag(EC_TAG_CLIENT_NEXT_REQUESTED_PART
, client
->GetNextRequestedPart()), valuemap
);
335 AddTag(CECTag(EC_TAG_CLIENT_LAST_DOWNLOADING_PART
, client
->GetLastDownloadingPart()), valuemap
);
338 const BitVector
& upPartStatus
= client
->GetUpPartStatus();
339 if (upPartStatus
.size() == file
->GetPartCount()) {
340 AddTag(CECTag(EC_TAG_CLIENT_UPLOAD_PART_STATUS
, upPartStatus
.SizeBuffer(), upPartStatus
.GetBuffer()), valuemap
);
348 CEC_SearchFile_Tag::CEC_SearchFile_Tag(const CSearchFile
*file
, EC_DETAIL_LEVEL detail_level
, CValueMap
*valuemap
) : CECTag(EC_TAG_SEARCHFILE
, file
->ECID())
350 AddTag(CECTag(EC_TAG_PARTFILE_SOURCE_COUNT
, file
->GetSourceCount()), valuemap
);
351 AddTag(CECTag(EC_TAG_PARTFILE_SOURCE_COUNT_XFER
, file
->GetCompleteSourceCount()), valuemap
);
352 AddTag(CECTag(EC_TAG_PARTFILE_STATUS
, (uint32
)file
->GetDownloadStatus()), valuemap
);
354 if (detail_level
== EC_DETAIL_UPDATE
) {
358 AddTag(CECTag(EC_TAG_PARTFILE_NAME
, file
->GetFileName().GetPrintable()), valuemap
);
359 AddTag(CECTag(EC_TAG_PARTFILE_SIZE_FULL
, file
->GetFileSize()), valuemap
);
360 AddTag(EC_TAG_PARTFILE_HASH
, file
->GetFileHash(), valuemap
);
361 if (file
->GetParent()) {
362 AddTag(EC_TAG_SEARCH_PARENT
, file
->GetParent()->ECID(), valuemap
);
369 CEC_Friend_Tag::CEC_Friend_Tag(const CFriend
* Friend
, CValueMap
* valuemap
) : CECTag(EC_TAG_FRIEND
, Friend
->ECID())
371 AddTag(EC_TAG_FRIEND_NAME
, Friend
->GetName(), valuemap
);
372 AddTag(EC_TAG_FRIEND_HASH
, Friend
->GetUserHash(), valuemap
);
373 AddTag(EC_TAG_FRIEND_IP
, Friend
->GetIP(), valuemap
);
374 AddTag(EC_TAG_FRIEND_PORT
, Friend
->GetPort(), valuemap
);
375 const CClientRef
& linkedClient
= Friend
->GetLinkedClient();
376 AddTag(EC_TAG_FRIEND_CLIENT
, linkedClient
.IsLinked() ? linkedClient
.ECID() : 0, valuemap
);
379 // File_checked_for_headers