2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 Merkur ( devs@emule-project.net / http://www.emule-project.net )
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 "EMSocket.h" // Interface declarations.
29 #include <protocol/Protocols.h>
30 #include <protocol/ed2k/Constants.h>
32 #include "Packet.h" // Needed for CPacket
34 #include "GetTickCount.h"
35 #include "UploadBandwidthThrottler.h"
37 #include "Preferences.h"
40 const uint32 MAX_SIZE
= 2000000;
42 CEMSocket::CEMSocket(const CProxyData
*ProxyData
)
43 : CEncryptedStreamSocket(wxSOCKET_NOWAIT
, ProxyData
)
45 // If an interface has been specified,
46 // then we need to bind to it.
47 if (!thePrefs::GetAddress().IsEmpty()) {
48 amuleIPV4Address host
;
50 // No need to warn here, in case of failure to
51 // assign the hostname. That is already done
52 // in amule.cpp when starting ...
53 if (host
.Hostname(thePrefs::GetAddress())) {
58 byConnected
= ES_NOTCONNECTED
;
59 m_uTimeOut
= CONNECTION_TIMEOUT
; // default timeout for ed2k sockets
61 // Download (pseudo) rate control
63 downloadLimitEnable
= false;
64 pendingOnReceive
= false;
66 // Download partial header
67 pendingHeaderSize
= 0;
69 // Download partial packet
71 pendingPacketSize
= 0;
78 m_currentPacket_is_controlpacket
= false;
79 m_currentPackageIsFromPartFile
= false;
81 m_numberOfSentBytesCompleteFile
= 0;
82 m_numberOfSentBytesPartFile
= 0;
83 m_numberOfSentBytesControlPacket
= 0;
85 lastCalledSend
= ::GetTickCount();
86 lastSent
= ::GetTickCount()-1000;
88 m_bAccelerateUpload
= false;
90 m_actualPayloadSize
= 0;
91 m_actualPayloadSizeSent
= 0;
96 lastFinishedStandard
= 0;
102 CEMSocket::~CEMSocket()
104 // need to be locked here to know that the other methods
105 // won't be in the middle of things
107 wxMutexLocker
lock(m_sendLocker
);
108 byConnected
= ES_DISCONNECTED
;
111 // now that we know no other method will keep adding to the queue
112 // we can remove ourself from the queue
113 if (theApp
->uploadBandwidthThrottler
) {
114 theApp
->uploadBandwidthThrottler
->RemoveFromAllQueues(this);
123 void CEMSocket::Destroy() {
126 wxSocketClient::Destroy();
131 void CEMSocket::ClearQueues()
133 wxMutexLocker
lock(m_sendLocker
);
135 DeleteContents(m_control_queue
);
138 CStdPacketQueue::iterator it
= m_standard_queue
.begin();
139 for (; it
!= m_standard_queue
.end(); ++it
) {
142 m_standard_queue
.clear();
145 // Download (pseudo) rate control
147 downloadLimitEnable
= false;
148 pendingOnReceive
= false;
150 // Download partial header
151 pendingHeaderSize
= 0;
153 // Download partial packet
154 delete pendingPacket
;
155 pendingPacket
= NULL
;
156 pendingPacketSize
= 0;
166 void CEMSocket::OnClose(int WXUNUSED(nErrorCode
))
168 // need to be locked here to know that the other methods
169 // won't be in the middle of things
171 wxMutexLocker
lock(m_sendLocker
);
172 byConnected
= ES_DISCONNECTED
;
175 // now that we know no other method will keep adding to the queue
176 // we can remove ourself from the queue
177 theApp
->uploadBandwidthThrottler
->RemoveFromAllQueues(this);
183 void CEMSocket::OnReceive(int nErrorCode
)
185 // the 2 meg size was taken from another place
186 static byte GlobalReadBuffer
[MAX_SIZE
];
189 uint32 error
= LastError();
190 if (error
!= wxSOCKET_WOULDBLOCK
) {
196 // Check current connection state
197 if (byConnected
== ES_DISCONNECTED
) {
200 byConnected
= ES_CONNECTED
; // ES_DISCONNECTED, ES_NOTCONNECTED, ES_CONNECTED
203 // CPU load improvement
204 if(downloadLimitEnable
== true && downloadLimit
== 0){
205 pendingOnReceive
= true;
209 // Remark: an overflow can not occur here
210 uint32 readMax
= sizeof(GlobalReadBuffer
) - pendingHeaderSize
;
211 if((downloadLimitEnable
== true) && (readMax
> downloadLimit
)) {
212 readMax
= downloadLimit
;
216 // We attempt to read up to 2 megs at a time (minus whatever is in our internal read buffer)
220 wxMutexLocker
lock(m_sendLocker
);
221 ret
= Read(GlobalReadBuffer
+ pendingHeaderSize
, readMax
);
222 if (Error() || (ret
== 0)) {
223 if (LastError() == wxSOCKET_WOULDBLOCK
) {
224 pendingOnReceive
= true;
232 if(downloadLimitEnable
== true){
234 downloadLimit
-= GetRealReceivedBytes();
237 // CPU load improvement
238 // Detect if the socket's buffer is empty (or the size did match...)
239 pendingOnReceive
= (ret
== readMax
);
241 // Copy back the partial header into the global read buffer for processing
242 if(pendingHeaderSize
> 0) {
243 memcpy(GlobalReadBuffer
, pendingHeader
, pendingHeaderSize
);
244 ret
+= pendingHeaderSize
;
245 pendingHeaderSize
= 0;
248 byte
* rptr
= GlobalReadBuffer
; // floating index initialized with begin of buffer
249 const byte
* rend
= GlobalReadBuffer
+ ret
; // end of buffer
251 // Loop, processing packets until we run out of them
252 while((rend
- rptr
>= PACKET_HEADER_SIZE
) ||
253 ((pendingPacket
!= NULL
) && (rend
- rptr
> 0 ))){
255 // Two possibilities here:
257 // 1. There is no pending incoming packet
258 // 2. There is already a partial pending incoming packet
260 // It's important to remember that emule exchange two kinds of packet
261 // - The control packet
262 // - The data packet for the transport of the block
264 // The biggest part of the traffic is done with the data packets.
265 // The default size of one block is 10240 bytes (or less if compressed), but the
266 // maximal size for one packet on the network is 1300 bytes. It's the reason
267 // why most of the Blocks are splitted before to be sent.
269 // Conclusion: When the download limit is disabled, this method can be at least
270 // called 8 times (10240/1300) by the lower layer before a splitted packet is
271 // rebuild and transferred to the above layer for processing.
273 // The purpose of this algorithm is to limit the amount of data exchanged between buffers
275 if(pendingPacket
== NULL
){
276 pendingPacket
= new CPacket(rptr
); // Create new packet container.
277 rptr
+= 6; // Only the header is initialized so far
279 // Bugfix We still need to check for a valid protocol
280 // Remark: the default eMule v0.26b had removed this test......
281 switch (pendingPacket
->GetProtocol()){
285 case OP_ED2KV2HEADER
:
286 case OP_ED2KV2PACKEDPROT
:
289 delete pendingPacket
;
290 pendingPacket
= NULL
;
291 OnError(ERR_WRONGHEADER
);
295 // Security: Check for buffer overflow (2MB)
296 if(pendingPacket
->GetPacketSize() > sizeof(GlobalReadBuffer
)) {
297 delete pendingPacket
;
298 pendingPacket
= NULL
;
304 pendingPacket
->AllocDataBuffer();
305 pendingPacketSize
= 0;
308 // Bytes ready to be copied into packet's internal buffer
309 wxASSERT(rptr
<= rend
);
310 uint32 toCopy
= ((pendingPacket
->GetPacketSize() - pendingPacketSize
) < (uint32
)(rend
- rptr
)) ?
311 (pendingPacket
->GetPacketSize() - pendingPacketSize
) : (uint32
)(rend
- rptr
);
313 // Copy Bytes from Global buffer to packet's internal buffer
314 pendingPacket
->CopyToDataBuffer(pendingPacketSize
, rptr
, toCopy
);
315 pendingPacketSize
+= toCopy
;
318 // Check if packet is complet
319 wxASSERT(pendingPacket
->GetPacketSize() >= pendingPacketSize
);
320 if(pendingPacket
->GetPacketSize() == pendingPacketSize
) {
322 bool bPacketResult
= PacketReceived(pendingPacket
);
323 delete pendingPacket
;
324 pendingPacket
= NULL
;
325 pendingPacketSize
= 0;
327 if (!bPacketResult
) {
333 // Finally, if there is any data left over, save it for next time
334 wxASSERT(rptr
<= rend
);
335 wxASSERT(rend
- rptr
< PACKET_HEADER_SIZE
);
337 // Keep the partial head
338 pendingHeaderSize
= rend
- rptr
;
339 memcpy(pendingHeader
, rptr
, pendingHeaderSize
);
344 void CEMSocket::SetDownloadLimit(uint32 limit
)
346 downloadLimit
= limit
;
347 downloadLimitEnable
= true;
349 // CPU load improvement
350 if(limit
> 0 && pendingOnReceive
== true){
356 void CEMSocket::DisableDownloadLimit()
358 downloadLimitEnable
= false;
360 // CPU load improvement
361 if (pendingOnReceive
== true){
368 * Queues up the packet to be sent. Another thread will actually send the packet.
370 * If the packet is not a control packet, and if the socket decides that its queue is
371 * full and forceAdd is false, then the socket is allowed to refuse to add the packet
372 * to its queue. It will then return false and it is up to the calling thread to try
373 * to call SendPacket for that packet again at a later time.
375 * @param packet address to the packet that should be added to the queue
377 * @param delpacket if true, the responsibility for deleting the packet after it has been sent
378 * has been transferred to this object. If false, don't delete the packet after it
381 * @param controlpacket the packet is a controlpacket
383 * @param forceAdd this packet must be added to the queue, even if it is full. If this flag is true
384 * then the method can not refuse to add the packet, and therefore not return false.
386 * @return true if the packet was added to the queue, false otherwise
388 void CEMSocket::SendPacket(CPacket
* packet
, bool delpacket
, bool controlpacket
, uint32 actualPayloadSize
)
390 //printf("* SendPacket called on socket %p\n", this);
391 wxMutexLocker
lock(m_sendLocker
);
393 if (byConnected
== ES_DISCONNECTED
) {
394 //printf("* Disconnected, drop packet\n");
400 packet
= new CPacket(*packet
);
404 //printf("* Adding a control packet\n");
405 m_control_queue
.push_back(packet
);
407 // queue up for controlpacket
408 theApp
->uploadBandwidthThrottler
->QueueForSendingControlPacket(this, HasSent());
410 //printf("* Adding a normal packet to the queue\n");
411 bool first
= !((sendbuffer
&& !m_currentPacket_is_controlpacket
) || !m_standard_queue
.empty());
412 StandardPacketQueueEntry queueEntry
= { actualPayloadSize
, packet
};
413 m_standard_queue
.push_back(queueEntry
);
415 // reset timeout for the first time
417 lastFinishedStandard
= ::GetTickCount();
418 m_bAccelerateUpload
= true; // Always accelerate first packet in a block
425 uint64
CEMSocket::GetSentBytesCompleteFileSinceLastCallAndReset()
427 wxMutexLocker
lock( m_sendLocker
);
429 uint64 sentBytes
= m_numberOfSentBytesCompleteFile
;
430 m_numberOfSentBytesCompleteFile
= 0;
436 uint64
CEMSocket::GetSentBytesPartFileSinceLastCallAndReset()
438 wxMutexLocker
lock( m_sendLocker
);
440 uint64 sentBytes
= m_numberOfSentBytesPartFile
;
441 m_numberOfSentBytesPartFile
= 0;
446 uint64
CEMSocket::GetSentBytesControlPacketSinceLastCallAndReset()
448 wxMutexLocker
lock( m_sendLocker
);
450 uint64 sentBytes
= m_numberOfSentBytesControlPacket
;
451 m_numberOfSentBytesControlPacket
= 0;
456 uint64
CEMSocket::GetSentPayloadSinceLastCallAndReset()
458 wxMutexLocker
lock( m_sendLocker
);
460 uint64 sentBytes
= m_actualPayloadSizeSent
;
461 m_actualPayloadSizeSent
= 0;
467 void CEMSocket::OnSend(int nErrorCode
)
474 CEncryptedStreamSocket::OnSend(0);
476 wxMutexLocker
lock( m_sendLocker
);
479 if (byConnected
!= ES_DISCONNECTED
) {
480 byConnected
= ES_CONNECTED
;
482 if (m_currentPacket_is_controlpacket
) {
483 // queue up for control packet
484 theApp
->uploadBandwidthThrottler
->QueueForSendingControlPacket(this, HasSent());
491 * Try to put queued up data on the socket.
493 * Control packets have higher priority, and will be sent first, if possible.
494 * Standard packets can be split up in several package containers. In that case
495 * all the parts of a split package must be sent in a row, without any control packet
498 * @param maxNumberOfBytesToSend This is the maximum number of bytes that is allowed to be put on the socket
499 * this call. The actual number of sent bytes will be returned from the method.
501 * @param onlyAllowedToSendControlPacket This call we only try to put control packets on the sockets.
502 * If there's a standard packet "in the way", and we think that this socket
503 * is no longer an upload slot, then it is ok to send the standard packet to
504 * get it out of the way. But it is not allowed to pick a new standard packet
505 * from the queue during this call. Several split packets are counted as one
506 * standard packet though, so it is ok to finish them all off if necessary.
508 * @return the actual number of bytes that were put on the socket.
510 SocketSentBytes
CEMSocket::Send(uint32 maxNumberOfBytesToSend
, uint32 minFragSize
, bool onlyAllowedToSendControlPacket
)
512 wxMutexLocker
lock(m_sendLocker
);
514 //printf("* Attempt to send a packet on socket %p\n", this);
516 if (byConnected
== ES_DISCONNECTED
) {
517 //printf("* Disconnected socket %p\n", this);
518 SocketSentBytes returnVal
= { false, 0, 0 };
520 } else if (m_bBusy
&& onlyAllowedToSendControlPacket
) {
521 //printf("* Busy socket %p\n", this);
522 SocketSentBytes returnVal
= { true, 0, 0 };
526 bool anErrorHasOccured
= false;
527 uint32 sentStandardPacketBytesThisCall
= 0;
528 uint32 sentControlPacketBytesThisCall
= 0;
530 if (byConnected
== ES_CONNECTED
&& IsEncryptionLayerReady() && (!m_bBusy
|| onlyAllowedToSendControlPacket
)) {
532 //printf("* Internal attemptto send on %p\n", this);
534 if(minFragSize
< 1) {
538 maxNumberOfBytesToSend
= GetNextFragSize(maxNumberOfBytesToSend
, minFragSize
);
540 bool bWasLongTimeSinceSend
= (::GetTickCount() - lastSent
) > 1000;
542 lastCalledSend
= ::GetTickCount();
545 while(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
< maxNumberOfBytesToSend
&& anErrorHasOccured
== false && // don't send more than allowed. Also, there should have been no error in earlier loop
546 (!m_control_queue
.empty() || !m_standard_queue
.empty() || sendbuffer
!= NULL
) && // there must exist something to send
547 (onlyAllowedToSendControlPacket
== false || // this means we are allowed to send both types of packets, so proceed
548 (sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
> 0 && (sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
) % minFragSize
!= 0) ||
549 (sendbuffer
== NULL
&& !m_control_queue
.empty()) || // There's a control packet in queue, and we are not currently sending anything, so we will handle the control packet next
550 (sendbuffer
!= NULL
&& m_currentPacket_is_controlpacket
== true) || // We are in the progress of sending a control packet. We are always allowed to send those
551 (sendbuffer
!= NULL
&& m_currentPacket_is_controlpacket
== false && bWasLongTimeSinceSend
&& !m_control_queue
.empty() && m_standard_queue
.empty() && (sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
) < minFragSize
) // We have waited to long to clean the current packet (which may be a standard packet that is in the way). Proceed no matter what the value of onlyAllowedToSendControlPacket.
555 // If we are currently not in the progress of sending a packet, we will need to find the next one to send
556 if(sendbuffer
== NULL
) {
557 CPacket
* curPacket
= NULL
;
558 if(!m_control_queue
.empty()) {
559 // There's a control packet to send
560 m_currentPacket_is_controlpacket
= true;
561 curPacket
= m_control_queue
.front();
562 m_control_queue
.pop_front();
563 } else if(!m_standard_queue
.empty() /*&& onlyAllowedToSendControlPacket == false*/) {
564 // There's a standard packet to send
565 m_currentPacket_is_controlpacket
= false;
566 StandardPacketQueueEntry queueEntry
= m_standard_queue
.front();
567 m_standard_queue
.pop_front();
568 curPacket
= queueEntry
.packet
;
569 m_actualPayloadSize
= queueEntry
.actualPayloadSize
;
571 // remember this for statistics purposes.
572 m_currentPackageIsFromPartFile
= curPacket
->IsFromPF();
574 // Just to be safe. Shouldn't happen?
575 // if we reach this point, then there's something wrong with the while condition above!
577 AddDebugLogLineM(true, logGeneral
, wxT("EMSocket: Couldn't get a new packet! There's an error in the first while condition in EMSocket::Send()"));
579 SocketSentBytes returnVal
= { true, sentStandardPacketBytesThisCall
, sentControlPacketBytesThisCall
};
583 // We found a packet to send. Get the data to send from the
584 // package container and dispose of the container.
585 sendblen
= curPacket
->GetRealPacketSize();
586 sendbuffer
= curPacket
->DetachPacket();
590 CryptPrepareSendData((byte
*)sendbuffer
, sendblen
);
593 // At this point we've got a packet to send in sendbuffer. Try to send it. Loop until entire packet
594 // is sent, or until we reach maximum bytes to send for this call, or until we get an error.
595 // NOTE! If send would block (returns WOULDBLOCK), we will return from this method INSIDE this loop.
596 while (sent
< sendblen
&&
597 sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
< maxNumberOfBytesToSend
&&
599 onlyAllowedToSendControlPacket
== false || // this means we are allowed to send both types of packets, so proceed
600 m_currentPacket_is_controlpacket
||
601 (bWasLongTimeSinceSend
&& (sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
) < minFragSize
) ||
602 (sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
) % minFragSize
!= 0
604 anErrorHasOccured
== false) {
605 uint32 tosend
= sendblen
-sent
;
606 if(!onlyAllowedToSendControlPacket
|| m_currentPacket_is_controlpacket
) {
607 if (maxNumberOfBytesToSend
>= sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
&& tosend
> maxNumberOfBytesToSend
-(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
))
608 tosend
= maxNumberOfBytesToSend
-(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
);
609 } else if(bWasLongTimeSinceSend
&& (sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
) < minFragSize
) {
610 if (minFragSize
>= sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
&& tosend
> minFragSize
-(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
))
611 tosend
= minFragSize
-(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
);
613 uint32 nextFragMaxBytesToSent
= GetNextFragSize(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
, minFragSize
);
614 if (nextFragMaxBytesToSent
>= sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
&& tosend
> nextFragMaxBytesToSent
-(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
))
615 tosend
= nextFragMaxBytesToSent
-(sentStandardPacketBytesThisCall
+ sentControlPacketBytesThisCall
);
617 wxASSERT(tosend
!= 0 && tosend
<= sendblen
-sent
);
619 //DWORD tempStartSendTick = ::GetTickCount();
621 lastSent
= ::GetTickCount();
623 uint32 result
= CEncryptedStreamSocket::Write(sendbuffer
+sent
,tosend
);
627 uint32 error
= LastError();
628 if (error
== wxSOCKET_WOULDBLOCK
){
631 SocketSentBytes returnVal
= { true, sentStandardPacketBytesThisCall
, sentControlPacketBytesThisCall
};
633 return returnVal
; // Send() blocked, onsend will be called when ready to send again
635 // Send() gave an error
636 anErrorHasOccured
= true;
639 // we managed to send some bytes. Perform bookkeeping.
645 // Log send bytes in correct class
646 if(m_currentPacket_is_controlpacket
== false) {
647 sentStandardPacketBytesThisCall
+= result
;
649 if(m_currentPackageIsFromPartFile
== true) {
650 m_numberOfSentBytesPartFile
+= result
;
652 m_numberOfSentBytesCompleteFile
+= result
;
655 sentControlPacketBytesThisCall
+= result
;
656 m_numberOfSentBytesControlPacket
+= result
;
661 if (sent
== sendblen
){
662 // we are done sending the current packet. Delete it and set
663 // sendbuffer to NULL so a new packet can be fetched.
668 if(!m_currentPacket_is_controlpacket
) {
669 m_actualPayloadSizeSent
+= m_actualPayloadSize
;
670 m_actualPayloadSize
= 0;
672 lastFinishedStandard
= ::GetTickCount(); // reset timeout
673 m_bAccelerateUpload
= false; // Safe until told otherwise
681 if(onlyAllowedToSendControlPacket
&& (!m_control_queue
.empty() || (sendbuffer
!= NULL
&& m_currentPacket_is_controlpacket
))) {
682 // enter control packet send queue
683 // we might enter control packet queue several times for the same package,
684 // but that costs very little overhead. Less overhead than trying to make sure
685 // that we only enter the queue once.
686 //printf("* Requeueing control packet on %p\n", this);
687 theApp
->uploadBandwidthThrottler
->QueueForSendingControlPacket(this, HasSent());
690 //printf("* Finishing send debug on %p\n",this);
692 SocketSentBytes returnVal
= { !anErrorHasOccured
, sentStandardPacketBytesThisCall
, sentControlPacketBytesThisCall
};
698 uint32
CEMSocket::GetNextFragSize(uint32 current
, uint32 minFragSize
)
700 if(current
% minFragSize
== 0) {
703 return minFragSize
*(current
/minFragSize
+1);
709 * Decides the (minimum) amount the socket needs to send to prevent timeout.
713 uint32
CEMSocket::GetNeededBytes()
719 uint64 sizeleft
, sizetotal
;
722 wxMutexLocker
lock(m_sendLocker
);
724 if (byConnected
== ES_DISCONNECTED
) {
728 if (!((sendbuffer
&& !m_currentPacket_is_controlpacket
) || !m_standard_queue
.empty())) {
729 // No standard packet to send. Even if data needs to be sent to prevent timout, there's nothing to send.
733 if (((sendbuffer
&& !m_currentPacket_is_controlpacket
)) && !m_control_queue
.empty())
734 m_bAccelerateUpload
= true; // We might be trying to send a block request, accelerate packet
736 sendgap
= ::GetTickCount() - lastCalledSend
;
738 timetotal
= m_bAccelerateUpload
?45000:90000;
739 timeleft
= ::GetTickCount() - lastFinishedStandard
;
740 if (sendbuffer
&& !m_currentPacket_is_controlpacket
) {
741 sizeleft
= sendblen
-sent
;
742 sizetotal
= sendblen
;
744 sizeleft
= sizetotal
= m_standard_queue
.front().packet
->GetRealPacketSize();
748 if (timeleft
>= timetotal
)
750 timeleft
= timetotal
-timeleft
;
751 if (timeleft
*sizetotal
>= timetotal
*sizeleft
) {
752 // don't use 'GetTimeOut' here in case the timeout value is high,
753 if (sendgap
> SEC2MS(20))
754 return 1; // Don't let the socket itself time out - Might happen when switching from spread(non-focus) slot to trickle slot
757 uint64 decval
= timeleft
*sizetotal
/timetotal
;
760 if (decval
< sizeleft
)
761 return sizeleft
-decval
+1; // Round up
768 * Removes all packets from the standard queue that don't have to be sent for the socket to be able to send a control packet.
770 * Before a socket can send a new packet, the current packet has to be finished. If the current packet is part of
771 * a split packet, then all parts of that split packet must be sent before the socket can send a control packet.
773 * This method keeps in standard queue only those packets that must be sent (rest of split packet), and removes everything
774 * after it. The method doesn't touch the control packet queue.
776 void CEMSocket::TruncateQueues()
778 wxMutexLocker
lock(m_sendLocker
);
780 // Clear the standard queue totally
781 // Please note! There may still be a standardpacket in the sendbuffer variable!
782 CStdPacketQueue::iterator it
= m_standard_queue
.begin();
783 for (; it
!= m_standard_queue
.end(); ++it
) {
787 m_standard_queue
.clear();
791 uint32
CEMSocket::GetTimeOut() const
797 void CEMSocket::SetTimeOut(uint32 uTimeOut
)
799 m_uTimeOut
= uTimeOut
;
801 // File_checked_for_headers