*Mangos: replaced dynamic by static allocation in server packets header. Added command to test large packets. By arrai.
*Mangos: [7022] Added support for packets > 64 kb. By derex. --HG-- branch : trunk
This commit is contained in:
@@ -208,6 +208,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||||||
{ "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL },
|
{ "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL },
|
||||||
{ "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL },
|
{ "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL },
|
||||||
{ "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
|
{ "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
|
||||||
|
{ "sendlargepacket",SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendLargePacketCommand, "", NULL },
|
||||||
{ NULL, 0, false, NULL, "", NULL }
|
{ NULL, 0, false, NULL, "", NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -485,6 +485,7 @@ class ChatHandler
|
|||||||
bool HandleBindSightCommand(const char* args);
|
bool HandleBindSightCommand(const char* args);
|
||||||
bool HandleUnbindSightCommand(const char* args);
|
bool HandleUnbindSightCommand(const char* args);
|
||||||
bool HandleSpawnVehicle(const char * args);
|
bool HandleSpawnVehicle(const char * args);
|
||||||
|
bool HandleSendLargePacketCommand(const char * args);
|
||||||
|
|
||||||
Player* getSelectedPlayer();
|
Player* getSelectedPlayer();
|
||||||
Creature* getSelectedCreature();
|
Creature* getSelectedCreature();
|
||||||
|
|||||||
+22
-6
@@ -1767,14 +1767,30 @@ void ObjectMgr::LoadItemPrototypes()
|
|||||||
const_cast<ItemPrototype*>(proto)->RequiredSkill = 0;
|
const_cast<ItemPrototype*>(proto)->RequiredSkill = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE))
|
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped.",i,proto->AllowableClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE))
|
// can be used in equip slot, as page read use in inventory, or spell casting at use
|
||||||
{
|
bool req = proto->InventoryType!=INVTYPE_NON_EQUIP || proto->PageText;
|
||||||
sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped.",i,proto->AllowableRace);
|
if(!req)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 5; ++j)
|
||||||
|
{
|
||||||
|
if(proto->Spells[j].SpellId)
|
||||||
|
{
|
||||||
|
req = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(req)
|
||||||
|
{
|
||||||
|
if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE))
|
||||||
|
sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use.",i,proto->AllowableClass);
|
||||||
|
|
||||||
|
if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE))
|
||||||
|
sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use.",i,proto->AllowableRace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell))
|
if(proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell))
|
||||||
|
|||||||
+99
-31
@@ -63,14 +63,8 @@ struct ServerPktHeader
|
|||||||
if(isLargePacket())
|
if(isLargePacket())
|
||||||
{
|
{
|
||||||
sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd);
|
sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd);
|
||||||
header= new uint8[5];
|
|
||||||
header[headerIndex++] = 0x80|(0xFF &(size>>16));
|
header[headerIndex++] = 0x80|(0xFF &(size>>16));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
header= new uint8[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
header[headerIndex++] = 0xFF &(size>>8);
|
header[headerIndex++] = 0xFF &(size>>8);
|
||||||
header[headerIndex++] = 0xFF &size;
|
header[headerIndex++] = 0xFF &size;
|
||||||
|
|
||||||
@@ -78,11 +72,6 @@ struct ServerPktHeader
|
|||||||
header[headerIndex++] = 0xFF & (cmd>>8);
|
header[headerIndex++] = 0xFF & (cmd>>8);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ServerPktHeader()
|
|
||||||
{
|
|
||||||
delete[] header;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 getHeaderLength()
|
uint8 getHeaderLength()
|
||||||
{
|
{
|
||||||
// cmd = 2 bytes, size= 2||3bytes
|
// cmd = 2 bytes, size= 2||3bytes
|
||||||
@@ -95,7 +84,7 @@ struct ServerPktHeader
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint32 size;
|
const uint32 size;
|
||||||
uint8 *header;
|
uint8 header[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ClientPktHeader
|
struct ClientPktHeader
|
||||||
@@ -124,6 +113,9 @@ m_OverSpeedPings (0),
|
|||||||
m_LastPingTime (ACE_Time_Value::zero)
|
m_LastPingTime (ACE_Time_Value::zero)
|
||||||
{
|
{
|
||||||
reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
|
reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
|
||||||
|
|
||||||
|
msg_queue()->high_water_mark(8*1024*1024);
|
||||||
|
msg_queue()->low_water_mark(8*1024*1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldSocket::~WorldSocket (void)
|
WorldSocket::~WorldSocket (void)
|
||||||
@@ -137,10 +129,6 @@ WorldSocket::~WorldSocket (void)
|
|||||||
closing_ = true;
|
closing_ = true;
|
||||||
|
|
||||||
peer ().close ();
|
peer ().close ();
|
||||||
|
|
||||||
WorldPacket* pct;
|
|
||||||
while (m_PacketQueue.dequeue_head (pct) == 0)
|
|
||||||
delete pct;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldSocket::IsClosed (void) const
|
bool WorldSocket::IsClosed (void) const
|
||||||
@@ -200,18 +188,35 @@ int WorldSocket::SendPacket (const WorldPacket& pct)
|
|||||||
sWorldLog.Log ("\n\n");
|
sWorldLog.Log ("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iSendPacket (pct) == -1)
|
ServerPktHeader header(pct.size()+2, pct.GetOpcode());
|
||||||
|
m_Crypt.EncryptSend ( header.header, header.getHeaderLength());
|
||||||
|
|
||||||
|
if (m_OutBuffer->space () >= pct.size () + header.getHeaderLength() && msg_queue()->is_empty())
|
||||||
{
|
{
|
||||||
WorldPacket* npct;
|
// Put the packet on the buffer.
|
||||||
|
if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1)
|
||||||
|
ACE_ASSERT (false);
|
||||||
|
|
||||||
ACE_NEW_RETURN (npct, WorldPacket (pct), -1);
|
if (!pct.empty ())
|
||||||
|
if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1)
|
||||||
|
ACE_ASSERT (false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Enqueue the packet.
|
||||||
|
ACE_Message_Block* mb;
|
||||||
|
|
||||||
// NOTE maybe check of the size of the queue can be good ?
|
ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size () + header.getHeaderLength()), -1);
|
||||||
// to make it bounded instead of unbounded
|
|
||||||
if (m_PacketQueue.enqueue_tail (npct) == -1)
|
mb->copy((char*) header.header, header.getHeaderLength());
|
||||||
|
|
||||||
|
if (!pct.empty ())
|
||||||
|
mb->copy((const char*)pct.contents(), pct.size ());
|
||||||
|
|
||||||
|
if(msg_queue()->enqueue_tail(mb,(ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
|
||||||
{
|
{
|
||||||
delete npct;
|
sLog.outError("WorldSocket::SendPacket enqueue_tail");
|
||||||
sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed");
|
mb->release();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,7 +341,7 @@ int WorldSocket::handle_output (ACE_HANDLE)
|
|||||||
const size_t send_len = m_OutBuffer->length ();
|
const size_t send_len = m_OutBuffer->length ();
|
||||||
|
|
||||||
if (send_len == 0)
|
if (send_len == 0)
|
||||||
return cancel_wakeup_output (Guard);
|
return handle_output_queue (Guard);
|
||||||
|
|
||||||
#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);
|
||||||
@@ -366,15 +371,73 @@ int WorldSocket::handle_output (ACE_HANDLE)
|
|||||||
{
|
{
|
||||||
m_OutBuffer->reset ();
|
m_OutBuffer->reset ();
|
||||||
|
|
||||||
if (!iFlushPacketQueue ())
|
return handle_output_queue (Guard);
|
||||||
return cancel_wakeup_output (Guard);
|
|
||||||
else
|
|
||||||
return schedule_wakeup_output (Guard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ACE_NOTREACHED (return 0);
|
ACE_NOTREACHED (return 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WorldSocket::handle_output_queue (GuardType& g)
|
||||||
|
{
|
||||||
|
if(msg_queue()->is_empty())
|
||||||
|
return cancel_wakeup_output(g);
|
||||||
|
|
||||||
|
ACE_Message_Block *mblk;
|
||||||
|
|
||||||
|
if(msg_queue()->dequeue_head(mblk, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
|
||||||
|
{
|
||||||
|
sLog.outError("WorldSocket::handle_output_queue dequeue_head");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t send_len = mblk->length ();
|
||||||
|
|
||||||
|
#ifdef MSG_NOSIGNAL
|
||||||
|
ssize_t n = peer ().send (mblk->rd_ptr (), send_len, MSG_NOSIGNAL);
|
||||||
|
#else
|
||||||
|
ssize_t n = peer ().send (mblk->rd_ptr (), send_len);
|
||||||
|
#endif // MSG_NOSIGNAL
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
mblk->release();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (n == -1)
|
||||||
|
{
|
||||||
|
if (errno == EWOULDBLOCK || errno == EAGAIN)
|
||||||
|
{
|
||||||
|
msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero);
|
||||||
|
return schedule_wakeup_output (g);
|
||||||
|
}
|
||||||
|
|
||||||
|
mblk->release();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (n < send_len) //now n > 0
|
||||||
|
{
|
||||||
|
mblk->rd_ptr (static_cast<size_t> (n));
|
||||||
|
|
||||||
|
if (msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero) == -1)
|
||||||
|
{
|
||||||
|
sLog.outError("WorldSocket::handle_output_queue enqueue_head");
|
||||||
|
mblk->release();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return schedule_wakeup_output (g);
|
||||||
|
}
|
||||||
|
else //now n == send_len
|
||||||
|
{
|
||||||
|
mblk->release();
|
||||||
|
|
||||||
|
return msg_queue()->is_empty() ? cancel_wakeup_output(g) : ACE_Event_Handler::WRITE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ACE_NOTREACHED(return -1);
|
||||||
|
}
|
||||||
|
|
||||||
int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
|
int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
|
||||||
{
|
{
|
||||||
// Critical section
|
// Critical section
|
||||||
@@ -402,10 +465,15 @@ int WorldSocket::Update (void)
|
|||||||
if (closing_)
|
if (closing_)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (m_OutActive || m_OutBuffer->length () == 0)
|
if (m_OutActive || (m_OutBuffer->length () == 0 && msg_queue()->is_empty()))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return handle_output (get_handle ());
|
int ret;
|
||||||
|
do
|
||||||
|
ret = handle_output (get_handle ());
|
||||||
|
while( ret > 0 );
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WorldSocket::handle_input_header (void)
|
int WorldSocket::handle_input_header (void)
|
||||||
|
|||||||
+3
-17
@@ -103,9 +103,6 @@ class WorldSocket : protected WorldHandler
|
|||||||
typedef ACE_Thread_Mutex LockType;
|
typedef ACE_Thread_Mutex LockType;
|
||||||
typedef ACE_Guard<LockType> GuardType;
|
typedef ACE_Guard<LockType> GuardType;
|
||||||
|
|
||||||
/// Queue for storing packets for which there is no space.
|
|
||||||
typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT;
|
|
||||||
|
|
||||||
/// Check if socket is closed.
|
/// Check if socket is closed.
|
||||||
bool IsClosed (void) const;
|
bool IsClosed (void) const;
|
||||||
|
|
||||||
@@ -161,6 +158,9 @@ class WorldSocket : protected WorldHandler
|
|||||||
int cancel_wakeup_output (GuardType& g);
|
int cancel_wakeup_output (GuardType& g);
|
||||||
int schedule_wakeup_output (GuardType& g);
|
int schedule_wakeup_output (GuardType& g);
|
||||||
|
|
||||||
|
/// Drain the queue if its not empty.
|
||||||
|
int handle_output_queue (GuardType& g);
|
||||||
|
|
||||||
/// process one incoming packet.
|
/// process one incoming packet.
|
||||||
/// @param new_pct received packet ,note that you need to delete it.
|
/// @param new_pct received packet ,note that you need to delete it.
|
||||||
int ProcessIncoming (WorldPacket* new_pct);
|
int ProcessIncoming (WorldPacket* new_pct);
|
||||||
@@ -171,16 +171,6 @@ class WorldSocket : protected WorldHandler
|
|||||||
/// Called by ProcessIncoming() on CMSG_PING.
|
/// Called by ProcessIncoming() on CMSG_PING.
|
||||||
int HandlePing (WorldPacket& recvPacket);
|
int HandlePing (WorldPacket& recvPacket);
|
||||||
|
|
||||||
/// Try to write WorldPacket to m_OutBuffer ,return -1 if no space
|
|
||||||
/// Need to be called with m_OutBufferLock lock held
|
|
||||||
int iSendPacket (const WorldPacket& pct);
|
|
||||||
|
|
||||||
/// Flush m_PacketQueue if there are packets in it
|
|
||||||
/// Need to be called with m_OutBufferLock lock held
|
|
||||||
/// @return true if it wrote to the buffer ( AKA you need
|
|
||||||
/// to mark the socket for output ).
|
|
||||||
bool iFlushPacketQueue ();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Time in which the last ping was received
|
/// Time in which the last ping was received
|
||||||
ACE_Time_Value m_LastPingTime;
|
ACE_Time_Value m_LastPingTime;
|
||||||
@@ -220,10 +210,6 @@ class WorldSocket : protected WorldHandler
|
|||||||
/// Size of the m_OutBuffer.
|
/// Size of the m_OutBuffer.
|
||||||
size_t m_OutBufferSize;
|
size_t m_OutBufferSize;
|
||||||
|
|
||||||
/// Here are stored packets for which there was no space on m_OutBuffer,
|
|
||||||
/// this allows not-to kick player if its buffer is overflowed.
|
|
||||||
PacketQueueT m_PacketQueue;
|
|
||||||
|
|
||||||
/// True if the socket is registered with the reactor for output
|
/// True if the socket is registered with the reactor for output
|
||||||
bool m_OutActive;
|
bool m_OutActive;
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -620,4 +620,14 @@ bool ChatHandler::HandleSpawnVehicle(const char* args)
|
|||||||
map->Add((Creature*)v);
|
map->Add((Creature*)v);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ChatHandler::HandleSendLargePacketCommand(const char* args)
|
||||||
|
{
|
||||||
|
const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. ";
|
||||||
|
std::ostringstream ss;
|
||||||
|
while(strlen(ss.str().c_str()) < 128000)
|
||||||
|
ss << stuffingString;
|
||||||
|
SendSysMessage(ss.str().c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "7020"
|
#define REVISION_NR "7022"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|||||||
Reference in New Issue
Block a user