aboutsummaryrefslogtreecommitdiff
path: root/src/game/WorldSocket.cpp
diff options
context:
space:
mode:
authorChaz Brown <iamparadox@netscape.net>2009-09-27 02:13:56 -0400
committerChaz Brown <iamparadox@netscape.net>2009-09-27 02:13:56 -0400
commita635bdd0ccdf77c56c45ee1a6d456b3a2ef43ff3 (patch)
treea3716455440cd46640533cba3185f539a63417a7 /src/game/WorldSocket.cpp
parent371c6fd37184fb0c0e98fc2b8b11c2a496991211 (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.cpp87
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;
}
}