diff options
author | Chaz Brown <iamparadox@netscape.net> | 2009-09-27 02:13:56 -0400 |
---|---|---|
committer | Chaz Brown <iamparadox@netscape.net> | 2009-09-27 02:13:56 -0400 |
commit | a635bdd0ccdf77c56c45ee1a6d456b3a2ef43ff3 (patch) | |
tree | a3716455440cd46640533cba3185f539a63417a7 /src/game/WorldSocket.cpp | |
parent | 371c6fd37184fb0c0e98fc2b8b11c2a496991211 (diff) |
* 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
Diffstat (limited to 'src/game/WorldSocket.cpp')
-rw-r--r-- | src/game/WorldSocket.cpp | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 1b63ec01421..d1cf5f91822 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -188,7 +188,8 @@ int WorldSocket::SendPacket (const WorldPacket& pct) 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; @@ -202,6 +203,12 @@ int WorldSocket::SendPacket (const WorldPacket& pct) sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed"); 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; @@ -321,10 +328,15 @@ int WorldSocket::handle_output (ACE_HANDLE) if (closing_) return -1; - const size_t send_len = m_OutBuffer->length (); + size_t send_len = m_OutBuffer->length(); if (send_len == 0) - return cancel_wakeup_output (Guard); + { + if (!iFlushPacketQueue()) + return cancel_wakeup_output(Guard); + + send_len = m_OutBuffer->length (); + } #ifdef 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) { 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; return -1; @@ -979,16 +991,73 @@ int WorldSocket::iSendPacket (const WorldPacket& pct) 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; 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) + { + // some bytes were written + haveone = true; + } + + if (result <= 0) { - if (m_PacketQueue.enqueue_head (pct) == -1) + if (m_PacketQueue.enqueue_head(pct) == -1) { delete pct; sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head"); @@ -999,7 +1068,7 @@ bool WorldSocket::iFlushPacketQueue () } else { - haveone = true; + // packet completed delete pct; } } |