* Fix Player getting stuck after teleport, etc. due to high number of achievements - patch by Trazom
http://www.trinitycore.org/forum/project.php?issueid=4329&page=4#note34721 --HG-- branch : trunk
This commit is contained in:
@@ -188,7 +188,8 @@ int WorldSocket::SendPacket (const WorldPacket& pct)
|
|||||||
sWorldLog.outLog ("\n");
|
sWorldLog.outLog ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iSendPacket (pct) == -1)
|
// don't try to send the packet if there are packets on the queue
|
||||||
|
if (!m_PacketQueue.is_empty() || iSendPacket(pct) == -1)
|
||||||
{
|
{
|
||||||
WorldPacket* npct;
|
WorldPacket* npct;
|
||||||
|
|
||||||
@@ -202,6 +203,12 @@ int WorldSocket::SendPacket (const WorldPacket& pct)
|
|||||||
sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed");
|
sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// iSendPacket may fail if the packet is larger than the buffer (even in the buffer is empty)
|
||||||
|
// So we must try to flush so the packet may be sent partially
|
||||||
|
// don't cancel_wakeup_output here
|
||||||
|
if (iFlushPacketQueue())
|
||||||
|
return schedule_wakeup_output(Guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -321,10 +328,15 @@ int WorldSocket::handle_output (ACE_HANDLE)
|
|||||||
if (closing_)
|
if (closing_)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const size_t send_len = m_OutBuffer->length ();
|
size_t send_len = m_OutBuffer->length();
|
||||||
|
|
||||||
if (send_len == 0)
|
if (send_len == 0)
|
||||||
return cancel_wakeup_output (Guard);
|
{
|
||||||
|
if (!iFlushPacketQueue())
|
||||||
|
return cancel_wakeup_output(Guard);
|
||||||
|
|
||||||
|
send_len = m_OutBuffer->length ();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MSG_NOSIGNAL
|
#ifdef MSG_NOSIGNAL
|
||||||
ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL);
|
ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL);
|
||||||
@@ -960,7 +972,7 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
|
|||||||
int WorldSocket::iSendPacket (const WorldPacket& pct)
|
int WorldSocket::iSendPacket (const WorldPacket& pct)
|
||||||
{
|
{
|
||||||
ServerPktHeader header(pct.size()+2, pct.GetOpcode());
|
ServerPktHeader header(pct.size()+2, pct.GetOpcode());
|
||||||
if (m_OutBuffer->space () < pct.size () + header.getHeaderLength())
|
if (m_OutBuffer->space() < pct.size () + header.getHeaderLength())
|
||||||
{
|
{
|
||||||
errno = ENOBUFS;
|
errno = ENOBUFS;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -979,16 +991,73 @@ int WorldSocket::iSendPacket (const WorldPacket& pct)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldSocket::iFlushPacketQueue ()
|
/// Return 1 if some bytes written and packet completed
|
||||||
|
/// Return 0 if no byte written, but still remaining data
|
||||||
|
/// Return -1 if some bytes written and still remaining data
|
||||||
|
int WorldSocket::iSendPartialPacket(WorldPacket& pct)
|
||||||
|
{
|
||||||
|
size_t remainingLen = pct.size() - pct.rpos();
|
||||||
|
|
||||||
|
if (pct.rpos() == 0) // nothing sent yet => send header
|
||||||
|
{
|
||||||
|
ServerPktHeader header(pct.size()+2, pct.GetOpcode());
|
||||||
|
|
||||||
|
if (m_OutBuffer->space () < pct.size () + header.getHeaderLength())
|
||||||
|
{
|
||||||
|
// be sure to send big packet (otherwise, they would stay in the queue)
|
||||||
|
// So for packet larger than 1K, just check if there are some usefull space
|
||||||
|
if (pct.size() > 1024 && m_OutBuffer->space () < header.getHeaderLength() + 1024)
|
||||||
|
{
|
||||||
|
return 0; // nothing written, still remaining data => 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Crypt.EncryptSend ( header.header, header.getHeaderLength());
|
||||||
|
|
||||||
|
if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1)
|
||||||
|
ACE_ASSERT (false);
|
||||||
|
|
||||||
|
if (remainingLen == 0)
|
||||||
|
{
|
||||||
|
return 1; // header written, nothing else => 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_OutBuffer->space()) < remainingLen) {
|
||||||
|
size_t len = m_OutBuffer->space();
|
||||||
|
|
||||||
|
if (m_OutBuffer->copy ((char*) (pct.contents() + pct.rpos()), len) == -1)
|
||||||
|
ACE_ASSERT (false);
|
||||||
|
|
||||||
|
pct.read_skip(len);
|
||||||
|
return -1; // packet will be pushed back on the queue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_OutBuffer->copy ((char*) (pct.contents() + pct.rpos()), remainingLen) == -1)
|
||||||
|
ACE_ASSERT (false);
|
||||||
|
|
||||||
|
return 1; // some byte written and packet completed
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WorldSocket::iFlushPacketQueue()
|
||||||
{
|
{
|
||||||
WorldPacket *pct;
|
WorldPacket *pct;
|
||||||
bool haveone = false;
|
bool haveone = false;
|
||||||
|
|
||||||
while (m_PacketQueue.dequeue_head (pct) == 0)
|
while (m_PacketQueue.dequeue_head(pct) == 0)
|
||||||
{
|
{
|
||||||
if (iSendPacket (*pct) == -1)
|
int result = iSendPartialPacket(*pct);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
{
|
{
|
||||||
if (m_PacketQueue.enqueue_head (pct) == -1)
|
// some bytes were written
|
||||||
|
haveone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result <= 0)
|
||||||
|
{
|
||||||
|
if (m_PacketQueue.enqueue_head(pct) == -1)
|
||||||
{
|
{
|
||||||
delete pct;
|
delete pct;
|
||||||
sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head");
|
sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head");
|
||||||
@@ -999,7 +1068,7 @@ bool WorldSocket::iFlushPacketQueue ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
haveone = true;
|
// packet completed
|
||||||
delete pct;
|
delete pct;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,10 @@ class WorldSocket : protected WorldHandler
|
|||||||
/// Need to be called with m_OutBufferLock lock held
|
/// Need to be called with m_OutBufferLock lock held
|
||||||
int iSendPacket (const WorldPacket& pct);
|
int iSendPacket (const WorldPacket& pct);
|
||||||
|
|
||||||
|
/// Try to write WorldPacket to m_OutBuffer even partially,
|
||||||
|
/// Need to be called with m_OutBufferLock lock held
|
||||||
|
int iSendPartialPacket(WorldPacket& pct);
|
||||||
|
|
||||||
/// Flush m_PacketQueue if there are packets in it
|
/// Flush m_PacketQueue if there are packets in it
|
||||||
/// Need to be called with m_OutBufferLock lock held
|
/// Need to be called with m_OutBufferLock lock held
|
||||||
/// @return true if it wrote to the buffer ( AKA you need
|
/// @return true if it wrote to the buffer ( AKA you need
|
||||||
|
|||||||
Reference in New Issue
Block a user