Changeset 181 for trunk

Show
Ignore:
Timestamp:
11/19/08 13:44:02 (17 years ago)
Author:
yumileroy
Message:

[svn] Merge from Mangos:
3c7ac5bd3e20c33a22ac57c5c3bac23a0798dc9e 2008-10-23 19:06:27
Some endianess related fixes and cleanups. By VladimirMangos?.

Original author: megamage
Date: 2008-11-06 16:10:28-06:00

Location:
trunk/src
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/framework/Utilities/ByteConverter.h

    r102 r181  
    1111 * This program is distributed in the hope that it will be useful, 
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1414 * GNU General Public License for more details. 
    1515 * 
    1616 * You should have received a copy of the GNU General Public License 
    1717 * along with this program; if not, write to the Free Software 
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
     18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
    1919 */ 
    2020 
     
    4949#if TRINITY_ENDIAN == TRINITY_BIGENDIAN 
    5050template<typename T> inline void EndianConvert(T& val) { ByteConverter::apply<T>(&val); } 
     51template<typename T> inline void EndianConvertReverse(T&) { } 
    5152#else 
    5253template<typename T> inline void EndianConvert(T&) { } 
     54template<typename T> inline void EndianConvertReverse(T& val) { ByteConverter::apply<T>(&val); } 
    5355#endif 
    5456 
    55 template<typename T> inline void EndianConvert(T*) { } 
     57template<typename T> void EndianConvert(T*);         // will generate link error 
     58template<typename T> void EndianConvertReverse(T*);  // will generate link error 
     59 
    5660inline void EndianConvert(uint8&) { } 
    5761inline void EndianConvert( int8&) { } 
     62inline void EndianConvertReverse(uint8&) { } 
     63inline void EndianConvertReverse( int8&) { } 
    5864 
    5965#endif 
  • trunk/src/game/World.cpp

    r168 r181  
    129129 
    130130    if(m_resultQueue) delete m_resultQueue; 
    131      
     131 
    132132    //TODO free addSessQueue 
    133133} 
     
    183183void World::AddSession(WorldSession* s) 
    184184{ 
    185   addSessQueue.add(s); 
     185    addSessQueue.add(s); 
    186186} 
    187187 
     
    189189World::AddSession_ (WorldSession* s) 
    190190{ 
    191   ASSERT (s); 
    192  
    193   //NOTE - Still there is race condition in WorldSession* being used in the Sockets 
    194  
    195   ///- kick already loaded player with same account (if any) and remove session 
    196   ///- if player is in loading and want to load again, return 
    197   if (!RemoveSession (s->GetAccountId ())) 
    198     { 
    199       s->KickPlayer (); 
    200       m_kicked_sessions.insert (s); 
    201       return; 
    202     } 
    203  
    204   WorldSession* old = m_sessions[s->GetAccountId ()]; 
    205   m_sessions[s->GetAccountId ()] = s; 
    206  
    207   // if session already exist, prepare to it deleting at next world update 
    208   // NOTE - KickPlayer() should be called on "old" in RemoveSession() 
    209   if (old) 
    210     m_kicked_sessions.insert (old); 
    211  
    212   uint32 Sessions = GetActiveAndQueuedSessionCount (); 
    213   uint32 pLimit = GetPlayerAmountLimit (); 
    214   uint32 QueueSize = GetQueueSize (); //number of players in the queue 
    215   bool inQueue = false; 
    216   //so we don't count the user trying to  
    217   //login as a session and queue the socket that we are using 
    218   --Sessions; 
    219  
    220   if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER ) 
    221     { 
    222       AddQueuedPlayer (s); 
    223       UpdateMaxSessionCounters (); 
    224       sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize); 
    225       return; 
    226     } 
    227    
    228   WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); 
    229   packet << uint8 (AUTH_OK); 
    230   packet << uint32 (0); // unknown random value... 
    231   packet << uint8 (0); 
    232   packet << uint32 (0); 
    233   packet << uint8 (s->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account 
    234   s->SendPacket (&packet); 
    235  
    236   UpdateMaxSessionCounters (); 
    237  
    238   // Updates the population 
    239   if (pLimit > 0) 
    240     { 
    241       float popu = GetActiveSessionCount (); //updated number of users on the server 
    242       popu /= pLimit; 
    243       popu *= 2; 
    244       loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); 
    245       sLog.outDetail ("Server Population (%f).", popu); 
     191    ASSERT (s); 
     192 
     193    //NOTE - Still there is race condition in WorldSession* being used in the Sockets 
     194 
     195    ///- kick already loaded player with same account (if any) and remove session 
     196    ///- if player is in loading and want to load again, return 
     197    if (!RemoveSession (s->GetAccountId ())) 
     198    { 
     199        s->KickPlayer (); 
     200        m_kicked_sessions.insert (s); 
     201        return; 
     202    } 
     203 
     204    WorldSession* old = m_sessions[s->GetAccountId ()]; 
     205    m_sessions[s->GetAccountId ()] = s; 
     206 
     207    // if session already exist, prepare to it deleting at next world update 
     208    // NOTE - KickPlayer() should be called on "old" in RemoveSession() 
     209    if (old) 
     210        m_kicked_sessions.insert (old); 
     211 
     212    uint32 Sessions = GetActiveAndQueuedSessionCount (); 
     213    uint32 pLimit = GetPlayerAmountLimit (); 
     214    uint32 QueueSize = GetQueueSize (); //number of players in the queue 
     215    bool inQueue = false; 
     216    //so we don't count the user trying to 
     217    //login as a session and queue the socket that we are using 
     218    --Sessions; 
     219 
     220    if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER ) 
     221    { 
     222        AddQueuedPlayer (s); 
     223        UpdateMaxSessionCounters (); 
     224        sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize); 
     225        return; 
     226    } 
     227 
     228    WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); 
     229    packet << uint8 (AUTH_OK); 
     230    packet << uint32 (0); // unknown random value... 
     231    packet << uint8 (0); 
     232    packet << uint32 (0); 
     233    packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account 
     234    s->SendPacket (&packet); 
     235 
     236    UpdateMaxSessionCounters (); 
     237 
     238    // Updates the population 
     239    if (pLimit > 0) 
     240    { 
     241        float popu = GetActiveSessionCount (); //updated number of users on the server 
     242        popu /= pLimit; 
     243        popu *= 2; 
     244        loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); 
     245        sLog.outDetail ("Server Population (%f).", popu); 
    246246    } 
    247247} 
     
    261261{ 
    262262    m_QueuedPlayer.push_back (sess); 
    263      
     263 
    264264    // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. 
    265265    WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); 
     
    271271    packet << uint32(GetQueuePos (sess)); 
    272272    sess->SendPacket (&packet); 
    273      
     273 
    274274    //sess->SendAuthWaitQue (GetQueuePos (sess)); 
    275275} 
     
    22832283 
    22842284    ///- Update the database with ban information 
    2285         switch(mode) 
     2285    switch(mode) 
    22862286    { 
    22872287        case BAN_IP: 
    2288                         //No SQL injection as strings are escaped 
    2289                         resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); 
    2290                         loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); 
    2291                         break; 
    2292                 case BAN_ACCOUNT: 
    2293                         //No SQL injection as string is escaped 
    2294                         resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); 
    2295                         break; 
    2296                 case BAN_CHARACTER: 
    2297                         //No SQL injection as string is escaped 
    2298                         resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str()); 
    2299                         break; 
    2300                 default: 
    2301                         return BAN_SYNTAX_ERROR; 
    2302     } 
    2303      
    2304         if(!resultAccounts) 
    2305         { 
    2306                 if(mode==BAN_IP) 
    2307             return BAN_SUCCESS; 
    2308                 else 
    2309                         return BAN_NOTFOUND;                                // Nobody to ban 
    2310         } 
     2288            //No SQL injection as strings are escaped 
     2289            resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); 
     2290            loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); 
     2291            break; 
     2292        case BAN_ACCOUNT: 
     2293            //No SQL injection as string is escaped 
     2294            resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); 
     2295            break; 
     2296        case BAN_CHARACTER: 
     2297            //No SQL injection as string is escaped 
     2298            resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str()); 
     2299            break; 
     2300        default: 
     2301            return BAN_SYNTAX_ERROR; 
     2302    } 
     2303 
     2304    if(!resultAccounts) 
     2305    { 
     2306        if(mode==BAN_IP) 
     2307            return BAN_SUCCESS;                             // ip correctly banned but nobody affected (yet) 
     2308        else 
     2309            return BAN_NOTFOUND;                                // Nobody to ban 
     2310    } 
    23112311 
    23122312    ///- Disconnect all affected players (for IP it can be several) 
     
    23172317 
    23182318        if(mode!=BAN_IP) 
    2319                 { 
     2319        { 
    23202320            //No SQL injection as strings are escaped 
    23212321            loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')", 
    23222322                account,duration_secs,safe_author.c_str(),reason.c_str()); 
    2323                 } 
     2323        } 
    23242324 
    23252325        if (WorldSession* sess = FindSession(account)) 
     
    23432343    else 
    23442344    { 
    2345         uint32 account=0; 
     2345        uint32 account = 0; 
    23462346        if (mode == BAN_ACCOUNT) 
    23472347            account = accmgr.GetId (nameOrIP); 
     
    23492349            account = objmgr.GetPlayerAccountIdByPlayerName (nameOrIP); 
    23502350 
    2351         if(!account) 
     2351        if (!account) 
    23522352            return false; 
    2353              
     2353 
    23542354        //NO SQL injection as account is uint32 
    23552355        loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account); 
     
    24342434 
    24352435        SendServerMessage(msgid,str.c_str(),player); 
    2436         outstring_log("Server will %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutdown"), str.c_str()); 
     2436        DEBUG_LOG("Server is %s in %s",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"),str.c_str()); 
    24372437    } 
    24382438} 
     
    24742474      AddSession_ (sess); 
    24752475    } 
    2476          
     2476 
    24772477    ///- Delete kicked sessions at add new session 
    24782478    for (std::set<WorldSession*>::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr) 
    2479     {    
     2479    { 
    24802480        RemoveQueuedPlayer (*itr); 
    24812481        delete *itr; 
     
    25052505{ 
    25062506    if (cliCmdQueue.empty()) 
    2507                 return; 
     2507        return; 
    25082508 
    25092509    CliCommandHolder::Print* zprint; 
     2510 
    25102511    while (!cliCmdQueue.empty()) 
    25112512    { 
     
    25132514        CliCommandHolder *command = cliCmdQueue.next(); 
    25142515 
    2515                 zprint = command->m_print; 
    2516  
    2517                 CliHandler(zprint).ParseCommands(command->m_command); 
     2516        zprint = command->m_print; 
     2517 
     2518        CliHandler(zprint).ParseCommands(command->m_command); 
    25182519 
    25192520        delete command; 
     
    26232624void World::LoadDBVersion() 
    26242625{ 
    2625         QueryResult* result = WorldDatabase.Query("SELECT version FROM db_version LIMIT 1"); 
    2626         if(result) 
    2627         { 
    2628                 Field* fields = result->Fetch(); 
    2629  
    2630                 m_DBVersion = fields[0].GetString(); 
    2631                 delete result; 
    2632         } 
    2633         else 
    2634                 m_DBVersion = "unknown world database"; 
    2635 } 
     2626    QueryResult* result = WorldDatabase.Query("SELECT version FROM db_version LIMIT 1"); 
     2627    if(result) 
     2628    { 
     2629        Field* fields = result->Fetch(); 
     2630 
     2631        m_DBVersion = fields[0].GetString(); 
     2632        delete result; 
     2633    } 
     2634    else 
     2635        m_DBVersion = "unknown world database"; 
     2636} 
  • trunk/src/game/WorldSession.cpp

    r174 r181  
    1111 * This program is distributed in the hope that it will be useful, 
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1414 * GNU General Public License for more details. 
    1515 * 
    1616 * You should have received a copy of the GNU General Public License 
    1717 * along with this program; if not, write to the Free Software 
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
     18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
    1919 */ 
    2020 
     
    5151_logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0) 
    5252{ 
    53    if (sock) 
    54    { 
    55            m_Address = sock->GetRemoteAddress (); 
    56            sock->AddReference (); 
    57    } 
     53    if (sock) 
     54    { 
     55        m_Address = sock->GetRemoteAddress (); 
     56        sock->AddReference (); 
     57    } 
    5858} 
    5959 
     
    6262{ 
    6363    ///- unload player if not unloaded 
    64     if(_player) 
    65         LogoutPlayer(true); 
     64    if (_player) 
     65        LogoutPlayer (true); 
    6666 
    6767    /// - If have unclosed socket, close it 
    68   if (m_Socket) 
    69     { 
    70       m_Socket->CloseSocket ();    
    71       m_Socket->RemoveReference (); 
    72       m_Socket = NULL; 
     68    if (m_Socket) 
     69    { 
     70        m_Socket->CloseSocket (); 
     71        m_Socket->RemoveReference (); 
     72        m_Socket = NULL; 
    7373    } 
    7474 
     
    7676    while(!_recvQueue.empty()) 
    7777    { 
    78         WorldPacket *packet = _recvQueue.next(); 
     78        WorldPacket *packet = _recvQueue.next (); 
    7979        delete packet; 
    8080    } 
    81      
    8281} 
    8382 
     
    134133    } 
    135134 
    136         #endif                                                  // !TRINITY_DEBUG 
    137  
    138         if (m_Socket->SendPacket (*packet) == -1) 
    139                 m_Socket->CloseSocket (); 
     135    #endif                                                  // !MANGOS_DEBUG 
     136 
     137    if (m_Socket->SendPacket (*packet) == -1) 
     138        m_Socket->CloseSocket (); 
    140139} 
    141140 
     
    158157bool WorldSession::Update(uint32 /*diff*/) 
    159158{ 
    160   if (m_Socket && m_Socket->IsClosed ()) 
    161   { 
     159    if (m_Socket && m_Socket->IsClosed ()) 
     160    { 
    162161        m_Socket->RemoveReference (); 
    163162        m_Socket = NULL; 
    164   } 
    165    
     163    } 
     164 
    166165    WorldPacket *packet; 
    167166 
     
    248247        if (uint64 lguid = GetPlayer()->GetLootGUID()) 
    249248            DoLootRelease(lguid); 
    250              
     249 
    251250        ///- If the player just died before logging out, make him appear as a ghost 
    252251        //FIXME: logout must be delayed in case lost connection with client in time of combat 
     
    285284            // give honor to all attackers from set like group case 
    286285            for(std::set<Player*>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr) 
    287                 (*itr)->RewardHonor(_player, aset.size(), -1, true); 
     286                (*itr)->RewardHonor(_player,aset.size()); 
    288287 
    289288            // give bg rewards and update counters like kill by first from attackers 
     
    403402        //No SQL injection as AccountId is uint32 
    404403        CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'", 
    405                         GetAccountId()); 
     404            GetAccountId()); 
    406405        sLog.outDebug( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" ); 
    407406    } 
     
    415414void WorldSession::KickPlayer() 
    416415{ 
    417         if (m_Socket) 
    418                 m_Socket->CloseSocket (); 
     416    if (m_Socket) 
     417        m_Socket->CloseSocket (); 
    419418} 
    420419 
     
    522521     } 
    523522 } 
    524   
    525  
    526  
    527  
  • trunk/src/game/WorldSocket.cpp

    r149 r181  
    11/*  
    2  * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> 
    3  * 
    4  * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> 
    5  * 
    6  * This program is free software; you can redistribute it and/or modify 
    7  * it under the terms of the GNU General Public License as published by 
    8  * the Free Software Foundation; either version 2 of the License, or 
    9  * (at your option) any later version. 
    10  * 
    11  * This program is distributed in the hope that it will be useful, 
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
    14  * GNU General Public License for more details. 
    15  * 
    16  * You should have received a copy of the GNU General Public License 
    17  * along with this program; if not, write to the Free Software 
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
    19  */ 
     2* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> 
     3* 
     4* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> 
     5* 
     6* This program is free software; you can redistribute it and/or modify 
     7* it under the terms of the GNU General Public License as published by 
     8* the Free Software Foundation; either version 2 of the License, or 
     9* (at your option) any later version. 
     10* 
     11* This program is distributed in the hope that it will be useful, 
     12* but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
     14* GNU General Public License for more details. 
     15* 
     16* You should have received a copy of the GNU General Public License 
     17* along with this program; if not, write to the Free Software 
     18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
     19*/ 
    2020 
    2121#include <ace/Message_Block.h> 
     
    5555struct ServerPktHeader 
    5656{ 
    57   ACE_UINT16 size; 
    58   ACE_UINT16 cmd; 
     57    uint16 size; 
     58    uint16 cmd; 
    5959}; 
    6060 
    6161struct ClientPktHeader 
    6262{ 
    63   ACE_UINT16 size; 
    64   ACE_UINT32 cmd; 
     63    uint16 size; 
     64    uint32 cmd; 
    6565}; 
    6666 
     
    8484m_LastPingTime (ACE_Time_Value::zero) 
    8585{ 
    86   this->reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); 
     86    reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); 
    8787} 
    8888 
    8989WorldSocket::~WorldSocket (void) 
    9090{ 
    91   if (m_RecvWPct) 
    92     delete m_RecvWPct; 
    93  
    94   if (m_OutBuffer) 
    95     m_OutBuffer->release (); 
    96  
    97   this->closing_ = true; 
    98  
    99   this->peer ().close (); 
    100  
    101   WorldPacket* pct; 
    102   while (m_PacketQueue.dequeue_head (pct) == 0) 
    103     delete pct; 
    104 } 
    105  
    106 bool 
    107 WorldSocket::IsClosed (void) const 
    108 { 
    109   return this->closing_; 
    110 } 
    111  
    112 void 
    113 WorldSocket::CloseSocket (void) 
    114 { 
    115   { 
    116     ACE_GUARD (LockType, Guard, m_OutBufferLock); 
    117  
    118     if (this->closing_) 
    119       return; 
    120  
    121     this->closing_ = true; 
    122  
    123     this->peer ().close_writer (); 
    124   } 
    125  
    126   { 
    127     ACE_GUARD (LockType, Guard, m_SessionLock); 
    128  
    129     m_Session = NULL; 
    130   } 
    131  
    132 } 
    133  
    134 const std::string& 
    135 WorldSocket::GetRemoteAddress (void) const 
    136 { 
    137   return m_Address; 
    138 } 
    139  
    140 int 
    141 WorldSocket::SendPacket (const WorldPacket& pct) 
    142 { 
    143   ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
    144  
    145   if (this->closing_) 
    146     return -1; 
    147  
    148   // Dump outgoing packet. 
    149   if (sWorldLog.LogWorld ()) 
    150     { 
    151       sWorldLog.Log ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
     91    if (m_RecvWPct) 
     92        delete m_RecvWPct; 
     93 
     94    if (m_OutBuffer) 
     95        m_OutBuffer->release (); 
     96 
     97    closing_ = true; 
     98 
     99    peer ().close (); 
     100 
     101    WorldPacket* pct; 
     102    while (m_PacketQueue.dequeue_head (pct) == 0) 
     103        delete pct; 
     104} 
     105 
     106bool WorldSocket::IsClosed (void) const 
     107{ 
     108    return closing_; 
     109} 
     110 
     111void WorldSocket::CloseSocket (void) 
     112{ 
     113    { 
     114        ACE_GUARD (LockType, Guard, m_OutBufferLock); 
     115 
     116        if (closing_) 
     117        return; 
     118 
     119        closing_ = true; 
     120 
     121        peer ().close_writer (); 
     122    } 
     123 
     124    { 
     125        ACE_GUARD (LockType, Guard, m_SessionLock); 
     126 
     127        m_Session = NULL; 
     128    } 
     129} 
     130 
     131const std::string& WorldSocket::GetRemoteAddress (void) const 
     132{ 
     133    return m_Address; 
     134} 
     135 
     136int WorldSocket::SendPacket (const WorldPacket& pct) 
     137{ 
     138    ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
     139 
     140    if (closing_) 
     141        return -1; 
     142 
     143    // Dump outgoing packet. 
     144    if (sWorldLog.LogWorld ()) 
     145    { 
     146        sWorldLog.Log ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
    152147                     (uint32) get_handle (), 
    153148                     pct.size (), 
     
    155150                     pct.GetOpcode ()); 
    156151 
    157       uint32 p = 0; 
    158       while (p < pct.size ()) 
    159         { 
    160           for (uint32 j = 0; j < 16 && p < pct.size (); j++) 
    161             sWorldLog.Log ("%.2X ", const_cast<WorldPacket&> (pct)[p++]); 
    162  
    163           sWorldLog.Log ("\n"); 
    164         } 
    165  
    166       sWorldLog.Log ("\n\n"); 
    167     } 
    168  
    169   if (iSendPacket (pct) == -1) 
    170     { 
    171       WorldPacket* npct; 
    172  
    173       ACE_NEW_RETURN (npct, WorldPacket (pct), -1); 
    174  
    175       // NOTE maybe check of the size of the queue can be good ? 
    176       // to make it bounded instead of unbounded 
    177       if (m_PacketQueue.enqueue_tail (npct) == -1) 
    178         { 
    179           delete npct; 
    180           sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed"); 
    181           return -1; 
    182         } 
    183     } 
    184  
    185   return 0; 
    186 } 
    187  
    188 long 
    189 WorldSocket::AddReference (void) 
    190 { 
    191   return static_cast<long> (this->add_reference ()); 
    192 } 
    193  
    194 long 
    195 WorldSocket::RemoveReference (void) 
    196 { 
    197   return static_cast<long> (this->remove_reference ()); 
    198 } 
    199  
    200 int 
    201 WorldSocket::open (void *a) 
    202 { 
    203   ACE_UNUSED_ARG (a); 
    204  
    205   // Prevent double call to this func. 
    206   if (m_OutBuffer) 
    207     return -1; 
    208  
    209   // This will also prevent the socket from being Updated 
    210   // while we are initializing it. 
    211   m_OutActive = true; 
    212  
    213   // Hook for the manager. 
    214   if (sWorldSocketMgr->OnSocketOpen (this) == -1) 
    215     return -1; 
    216  
    217   // Allocate the buffer. 
    218   ACE_NEW_RETURN (m_OutBuffer, ACE_Message_Block (m_OutBufferSize), -1); 
    219  
    220   // Store peer address. 
    221   ACE_INET_Addr remote_addr; 
    222  
    223   if (this->peer ().get_remote_addr (remote_addr) == -1) 
    224     { 
    225       sLog.outError ("WorldSocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno)); 
    226       return -1; 
    227     } 
    228  
    229   m_Address = remote_addr.get_host_addr (); 
    230  
    231   // Send startup packet. 
    232   WorldPacket packet (SMSG_AUTH_CHALLENGE, 4); 
    233   packet << m_Seed; 
    234  
    235   if (SendPacket (packet) == -1) 
    236     return -1; 
    237  
    238   // Register with ACE Reactor 
    239   if (this->reactor ()->register_handler 
    240       (this, 
    241        ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1) 
    242     { 
    243       sLog.outError ("WorldSocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno)); 
    244       return -1; 
    245     } 
    246  
    247   // reactor takes care of the socket from now on 
    248   this->remove_reference (); 
    249  
    250   return 0; 
    251 } 
    252  
    253 int 
    254 WorldSocket::close (int) 
    255 { 
    256   this->shutdown (); 
    257  
    258   this->closing_ = true; 
    259  
    260   this->remove_reference (); 
    261  
    262   return 0; 
    263 } 
    264  
    265 int 
    266 WorldSocket::handle_input (ACE_HANDLE) 
    267 { 
    268   if (this->closing_) 
    269     return -1; 
    270  
    271   switch (this->handle_input_missing_data ()) 
    272     { 
    273     case -1 : 
    274       { 
    275         if ((errno == EWOULDBLOCK) || 
    276             (errno == EAGAIN)) 
    277           { 
    278             //return 0; 
    279             return this->Update (); // interesting line ,isnt it ? 
    280           } 
    281  
    282         DEBUG_LOG ("WorldSocket::handle_input: Peer error closing connection errno = %s", ACE_OS::strerror (errno)); 
    283  
    284         return -1; 
    285       } 
    286     case 0: 
    287       { 
    288         DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection\n"); 
    289  
    290         errno = ECONNRESET; 
    291  
    292         return -1; 
    293       } 
    294     case 1: 
    295       return 1; 
    296     } 
    297  
    298   //return 0; 
    299   return this->Update (); // another interesting line ;) 
    300 } 
    301  
    302 int 
    303 WorldSocket::handle_output (ACE_HANDLE) 
    304 { 
    305   ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
    306  
    307   if (this->closing_) 
    308     return -1; 
    309  
    310   const size_t send_len = m_OutBuffer->length (); 
    311  
    312   if (send_len == 0) 
    313     return this->cancel_wakeup_output (Guard); 
    314  
    315   // TODO SO_NOSIGPIPE on platforms that support it 
     152        uint32 p = 0; 
     153        while (p < pct.size ()) 
     154        { 
     155            for (uint32 j = 0; j < 16 && p < pct.size (); j++) 
     156                sWorldLog.Log ("%.2X ", const_cast<WorldPacket&>(pct)[p++]); 
     157 
     158            sWorldLog.Log ("\n"); 
     159        } 
     160 
     161        sWorldLog.Log ("\n\n"); 
     162    } 
     163 
     164    if (iSendPacket (pct) == -1) 
     165    { 
     166        WorldPacket* npct; 
     167 
     168        ACE_NEW_RETURN (npct, WorldPacket (pct), -1); 
     169 
     170        // NOTE maybe check of the size of the queue can be good ? 
     171        // to make it bounded instead of unbounded 
     172        if (m_PacketQueue.enqueue_tail (npct) == -1) 
     173        { 
     174            delete npct; 
     175            sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed"); 
     176            return -1; 
     177        } 
     178    } 
     179 
     180    return 0; 
     181} 
     182 
     183long WorldSocket::AddReference (void) 
     184{ 
     185    return static_cast<long> (add_reference ()); 
     186} 
     187 
     188long WorldSocket::RemoveReference (void) 
     189{ 
     190    return static_cast<long> (remove_reference ()); 
     191} 
     192 
     193int WorldSocket::open (void *a) 
     194{ 
     195    ACE_UNUSED_ARG (a); 
     196 
     197    // Prevent double call to this func. 
     198    if (m_OutBuffer) 
     199        return -1; 
     200 
     201    // This will also prevent the socket from being Updated 
     202    // while we are initializing it. 
     203    m_OutActive = true; 
     204 
     205    // Hook for the manager. 
     206    if (sWorldSocketMgr->OnSocketOpen (this) == -1) 
     207        return -1; 
     208 
     209    // Allocate the buffer. 
     210    ACE_NEW_RETURN (m_OutBuffer, ACE_Message_Block (m_OutBufferSize), -1); 
     211 
     212    // Store peer address. 
     213    ACE_INET_Addr remote_addr; 
     214 
     215    if (peer ().get_remote_addr (remote_addr) == -1) 
     216    { 
     217        sLog.outError ("WorldSocket::open: peer ().get_remote_addr errno = %s", ACE_OS::strerror (errno)); 
     218        return -1; 
     219    } 
     220 
     221    m_Address = remote_addr.get_host_addr (); 
     222 
     223    // Send startup packet. 
     224    WorldPacket packet (SMSG_AUTH_CHALLENGE, 4); 
     225    packet << m_Seed; 
     226 
     227    if (SendPacket (packet) == -1) 
     228        return -1; 
     229 
     230    // Register with ACE Reactor 
     231    if (reactor ()->register_handler(this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK) == -1) 
     232    { 
     233        sLog.outError ("WorldSocket::open: unable to register client handler errno = %s", ACE_OS::strerror (errno)); 
     234        return -1; 
     235    } 
     236 
     237    // reactor takes care of the socket from now on 
     238    remove_reference (); 
     239 
     240    return 0; 
     241} 
     242 
     243int WorldSocket::close (int) 
     244{ 
     245    shutdown (); 
     246 
     247    closing_ = true; 
     248 
     249    remove_reference (); 
     250 
     251    return 0; 
     252} 
     253 
     254int WorldSocket::handle_input (ACE_HANDLE) 
     255{ 
     256    if (closing_) 
     257        return -1; 
     258 
     259    switch (handle_input_missing_data ()) 
     260    { 
     261        case -1 : 
     262        { 
     263            if ((errno == EWOULDBLOCK) || 
     264                (errno == EAGAIN)) 
     265            { 
     266                return Update (); // interesting line ,isnt it ? 
     267            } 
     268 
     269            DEBUG_LOG ("WorldSocket::handle_input: Peer error closing connection errno = %s", ACE_OS::strerror (errno)); 
     270 
     271            errno = ECONNRESET; 
     272            return -1; 
     273        } 
     274        case 0: 
     275        { 
     276            DEBUG_LOG ("WorldSocket::handle_input: Peer has closed connection\n"); 
     277 
     278            errno = ECONNRESET; 
     279            return -1; 
     280        } 
     281        case 1: 
     282            return 1; 
     283        default: 
     284            return Update (); // another interesting line ;) 
     285    } 
     286 
     287    ACE_NOTREACHED(return -1); 
     288} 
     289 
     290int WorldSocket::handle_output (ACE_HANDLE) 
     291{ 
     292    ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
     293 
     294    if (closing_) 
     295        return -1; 
     296 
     297    const size_t send_len = m_OutBuffer->length (); 
     298 
     299    if (send_len == 0) 
     300        return cancel_wakeup_output (Guard); 
     301 
    316302#ifdef MSG_NOSIGNAL 
    317   ssize_t n = this->peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL); 
     303    ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL); 
    318304#else 
    319   ssize_t n = this->peer ().send (m_OutBuffer->rd_ptr (), send_len); 
     305    ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len); 
    320306#endif // MSG_NOSIGNAL 
    321307 
    322   if (n == 0) 
    323     return -1; 
    324   else if (n == -1) 
    325     { 
    326       if (errno == EWOULDBLOCK || errno == EAGAIN) 
    327         return this->schedule_wakeup_output (Guard); 
    328  
    329       return -1; 
    330     } 
    331   else if (n < send_len) //now n > 0 
    332     { 
    333       m_OutBuffer->rd_ptr (static_cast<size_t> (n)); 
    334  
    335       // move the data to the base of the buffer 
    336       m_OutBuffer->crunch (); 
    337  
    338       return this->schedule_wakeup_output (Guard); 
    339     } 
    340   else //now n == send_len 
    341     { 
    342       m_OutBuffer->reset (); 
    343  
    344       if (!iFlushPacketQueue ()) 
    345         return this->cancel_wakeup_output (Guard); 
    346       else 
    347         return this->schedule_wakeup_output (Guard); 
    348     } 
    349  
    350   ACE_NOTREACHED (return 0); 
    351 } 
    352  
    353 int 
    354 WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) 
    355 { 
    356   // Critical section 
    357   { 
    358     ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
    359  
    360     this->closing_ = true; 
    361  
    362     if (h == ACE_INVALID_HANDLE) 
    363       this->peer ().close_writer (); 
    364   } 
    365  
    366   // Critical section 
    367   { 
    368     ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
    369  
    370     m_Session = NULL; 
    371   } 
    372  
    373   return 0; 
    374 } 
    375  
    376 int 
    377 WorldSocket::Update (void) 
    378 { 
    379   if (this->closing_) 
    380     return -1; 
    381  
    382   if (m_OutActive || m_OutBuffer->length () == 0) 
     308    if (n == 0) 
     309        return -1; 
     310    else if (n == -1) 
     311    { 
     312        if (errno == EWOULDBLOCK || errno == EAGAIN) 
     313            return schedule_wakeup_output (Guard); 
     314 
     315        return -1; 
     316    } 
     317    else if (n < send_len) //now n > 0 
     318    { 
     319        m_OutBuffer->rd_ptr (static_cast<size_t> (n)); 
     320 
     321        // move the data to the base of the buffer 
     322        m_OutBuffer->crunch (); 
     323 
     324        return schedule_wakeup_output (Guard); 
     325    } 
     326    else //now n == send_len 
     327    { 
     328        m_OutBuffer->reset (); 
     329 
     330        if (!iFlushPacketQueue ()) 
     331            return cancel_wakeup_output (Guard); 
     332        else 
     333            return schedule_wakeup_output (Guard); 
     334    } 
     335 
     336    ACE_NOTREACHED (return 0); 
     337} 
     338 
     339int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) 
     340{ 
     341    // Critical section 
     342    { 
     343        ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); 
     344 
     345        closing_ = true; 
     346 
     347        if (h == ACE_INVALID_HANDLE) 
     348            peer ().close_writer (); 
     349    } 
     350 
     351    // Critical section 
     352    { 
     353        ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     354 
     355        m_Session = NULL; 
     356    } 
     357 
    383358    return 0; 
    384  
    385   return this->handle_output (this->get_handle ()); 
    386 } 
    387  
    388 int 
    389 WorldSocket::handle_input_header (void) 
    390 { 
    391   ACE_ASSERT (m_RecvWPct == NULL); 
    392  
    393   if (m_Header.length () != sizeof (ClientPktHeader)) 
    394     { 
    395       sLog.outError ("WorldSocket::handle_input_header: internal error: invalid header"); 
    396       errno = EINVAL; 
    397       return -1; 
    398     } 
    399  
    400   m_Crypt.DecryptRecv ((ACE_UINT8*) m_Header.rd_ptr (), sizeof (ClientPktHeader)); 
    401  
    402   ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr ()); 
    403  
    404   header.size = ACE_NTOHS (header.size); 
    405  
    406 #if ACE_BYTE_ORDER == ACE_BIG_ENDIAN 
    407   header.cmd = ACE_SWAP_LONG (header.cmd) 
    408 #endif // ACE_BIG_ENDIAN 
    409  
    410   if ((header.size < 4) || 
    411       (header.size > 10240) || 
    412       (header.cmd <= 0) || 
    413       (header.cmd > 10240) 
    414       ) 
    415     { 
    416       sLog.outError ("WorldSocket::handle_input_header: client sent mailformed packet size = %d , cmd = %d", 
    417                      header.size, 
    418                      header.cmd); 
    419  
    420       errno = EINVAL; 
    421       return -1; 
    422     } 
    423  
    424   header.size -= 4; 
    425  
    426   ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1); 
    427  
    428   if (header.size > 0) 
    429     { 
    430       m_RecvWPct->resize (header.size); 
    431       m_RecvPct.base ((char*) m_RecvWPct->contents (), m_RecvWPct->size ()); 
    432     } 
    433   else 
    434     { 
    435       ACE_ASSERT (m_RecvPct.space () == 0); 
    436     } 
    437  
    438  
    439   return 0; 
    440 } 
    441  
    442 int 
    443 WorldSocket::handle_input_payload (void) 
    444 { 
    445   // set errno properly here on error !!! 
    446   // now have a header and payload 
    447  
    448   ACE_ASSERT (m_RecvPct.space () == 0); 
    449   ACE_ASSERT (m_Header.space () == 0); 
    450   ACE_ASSERT (m_RecvWPct != NULL); 
    451  
    452   const int ret = this->ProcessIncoming (m_RecvWPct); 
    453  
    454   m_RecvPct.base (NULL, 0); 
    455   m_RecvPct.reset (); 
    456   m_RecvWPct = NULL; 
    457  
    458   m_Header.reset (); 
    459  
    460   if (ret == -1) 
    461     errno = EINVAL; 
    462  
    463   return ret; 
    464 } 
    465  
    466 int 
    467 WorldSocket::handle_input_missing_data (void) 
    468 { 
    469   char buf [1024]; 
    470  
    471   ACE_Data_Block db (sizeof (buf), 
    472                      ACE_Message_Block::MB_DATA, 
    473                      buf, 
    474                      0, 
    475                      0, 
    476                      ACE_Message_Block::DONT_DELETE, 
    477                      0); 
    478  
    479   ACE_Message_Block message_block (&db, 
    480                                    ACE_Message_Block::DONT_DELETE, 
    481                                    0); 
    482  
    483   const size_t recv_size = message_block.space (); 
    484  
    485   const ssize_t n = this->peer ().recv (message_block.wr_ptr (), 
    486                                         recv_size); 
    487  
    488   if (n <= 0) 
    489     return n; 
    490  
    491   message_block.wr_ptr (n); 
    492  
    493   while (message_block.length () > 0) 
    494     { 
    495       if (m_Header.space () > 0) 
    496         { 
    497           //need to recieve the header 
    498           const size_t to_header = (message_block.length () > m_Header.space () ? m_Header.space () : message_block.length ()); 
    499           m_Header.copy (message_block.rd_ptr (), to_header); 
    500           message_block.rd_ptr (to_header); 
    501  
    502           if (m_Header.space () > 0) 
     359} 
     360 
     361int WorldSocket::Update (void) 
     362{ 
     363    if (closing_) 
     364        return -1; 
     365 
     366    if (m_OutActive || m_OutBuffer->length () == 0) 
     367        return 0; 
     368 
     369    return handle_output (get_handle ()); 
     370} 
     371 
     372int WorldSocket::handle_input_header (void) 
     373{ 
     374    ACE_ASSERT (m_RecvWPct == NULL); 
     375 
     376    ACE_ASSERT (m_Header.length () == sizeof (ClientPktHeader)); 
     377 
     378    m_Crypt.DecryptRecv ((ACE_UINT8*) m_Header.rd_ptr (), sizeof (ClientPktHeader)); 
     379 
     380    ClientPktHeader& header = *((ClientPktHeader*) m_Header.rd_ptr ()); 
     381 
     382    EndianConvertReverse(header.size); 
     383    EndianConvert(header.cmd); 
     384 
     385    if ((header.size < 4) || (header.size > 10240) || 
     386        (header.cmd  < 0) || (header.cmd  > 10240) ) 
     387    { 
     388        sLog.outError ("WorldSocket::handle_input_header: client sent mailformed packet size = %d , cmd = %d", 
     389                       header.size, header.cmd); 
     390 
     391        errno = EINVAL; 
     392        return -1; 
     393    } 
     394 
     395    header.size -= 4; 
     396 
     397    ACE_NEW_RETURN (m_RecvWPct, WorldPacket ((uint16) header.cmd, header.size), -1); 
     398 
     399    if(header.size > 0) 
     400    { 
     401        m_RecvWPct->resize (header.size); 
     402        m_RecvPct.base ((char*) m_RecvWPct->contents (), m_RecvWPct->size ()); 
     403    } 
     404    else 
     405    { 
     406        ACE_ASSERT(m_RecvPct.space() == 0); 
     407    } 
     408 
     409    return 0; 
     410} 
     411 
     412int WorldSocket::handle_input_payload (void) 
     413{ 
     414    // set errno properly here on error !!! 
     415    // now have a header and payload 
     416 
     417    ACE_ASSERT (m_RecvPct.space () == 0); 
     418    ACE_ASSERT (m_Header.space () == 0); 
     419    ACE_ASSERT (m_RecvWPct != NULL); 
     420 
     421    const int ret = ProcessIncoming (m_RecvWPct); 
     422 
     423    m_RecvPct.base (NULL, 0); 
     424    m_RecvPct.reset (); 
     425    m_RecvWPct = NULL; 
     426 
     427    m_Header.reset (); 
     428 
     429    if (ret == -1) 
     430        errno = EINVAL; 
     431 
     432    return ret; 
     433} 
     434 
     435int WorldSocket::handle_input_missing_data (void) 
     436{ 
     437    char buf [1024]; 
     438 
     439    ACE_Data_Block db ( sizeof (buf), 
     440                        ACE_Message_Block::MB_DATA, 
     441                        buf, 
     442                        0, 
     443                        0, 
     444                        ACE_Message_Block::DONT_DELETE, 
     445                        0); 
     446 
     447    ACE_Message_Block message_block(&db, 
     448                                    ACE_Message_Block::DONT_DELETE, 
     449                                    0); 
     450 
     451    const size_t recv_size = message_block.space (); 
     452 
     453    const ssize_t n = peer ().recv (message_block.wr_ptr (), 
     454                                          recv_size); 
     455 
     456    if (n <= 0) 
     457        return n; 
     458 
     459    message_block.wr_ptr (n); 
     460 
     461    while (message_block.length () > 0) 
     462    { 
     463        if (m_Header.space () > 0) 
     464        { 
     465            //need to recieve the header 
     466            const size_t to_header = (message_block.length () > m_Header.space () ? m_Header.space () : message_block.length ()); 
     467            m_Header.copy (message_block.rd_ptr (), to_header); 
     468            message_block.rd_ptr (to_header); 
     469 
     470            if (m_Header.space () > 0) 
    503471            { 
    504               //couldnt recieve the whole header this time 
    505               ACE_ASSERT (message_block.length () == 0); 
    506               errno = EWOULDBLOCK; 
    507               return -1; 
     472                //couldnt recieve the whole header this time 
     473                ACE_ASSERT (message_block.length () == 0); 
     474                errno = EWOULDBLOCK; 
     475                return -1; 
    508476            } 
    509477 
    510478          //we just recieved nice new header 
    511           if (this->handle_input_header () == -1) 
     479            if (handle_input_header () == -1) 
    512480            { 
    513               ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); 
    514               return -1; 
     481                ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); 
     482                return -1; 
    515483            } 
    516484        } 
    517485 
    518       // Its possible on some error situations that this happens 
    519       // for example on closing when epoll recieves more chunked data and stuff 
    520       // hope this is not hack ,as proper m_RecvWPct is asserted around 
    521       if (!m_RecvWPct) 
    522         { 
    523           sLog.outError ("Forsing close on input m_RecvWPct = NULL"); 
    524           errno = EINVAL; 
    525           return -1; 
    526         } 
    527  
    528       // We have full readed header, now check the data payload 
    529       if (m_RecvPct.space () > 0) 
    530         { 
    531           //need more data in the payload 
    532           const size_t to_data = (message_block.length () > m_RecvPct.space () ? m_RecvPct.space () : message_block.length ()); 
    533           m_RecvPct.copy (message_block.rd_ptr (), to_data); 
    534           message_block.rd_ptr (to_data); 
    535  
    536           if (m_RecvPct.space () > 0) 
     486        // Its possible on some error situations that this happens 
     487        // for example on closing when epoll recieves more chunked data and stuff 
     488        // hope this is not hack ,as proper m_RecvWPct is asserted around 
     489        if (!m_RecvWPct) 
     490        { 
     491            sLog.outError ("Forsing close on input m_RecvWPct = NULL"); 
     492            errno = EINVAL; 
     493            return -1; 
     494        } 
     495 
     496        // We have full readed header, now check the data payload 
     497        if (m_RecvPct.space () > 0) 
     498        { 
     499            //need more data in the payload 
     500            const size_t to_data = (message_block.length () > m_RecvPct.space () ? m_RecvPct.space () : message_block.length ()); 
     501            m_RecvPct.copy (message_block.rd_ptr (), to_data); 
     502            message_block.rd_ptr (to_data); 
     503 
     504            if (m_RecvPct.space () > 0) 
    537505            { 
    538               //couldnt recieve the whole data this time 
    539               ACE_ASSERT (message_block.length () == 0); 
    540               errno = EWOULDBLOCK; 
    541               return -1; 
     506                //couldnt recieve the whole data this time 
     507                ACE_ASSERT (message_block.length () == 0); 
     508                errno = EWOULDBLOCK; 
     509                return -1; 
    542510            } 
    543511        } 
    544512 
    545       //just recieved fresh new payload 
    546       if (this->handle_input_payload () == -1) 
    547         { 
    548           ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); 
    549           return -1; 
    550         } 
    551     } 
    552  
    553   return n == recv_size ? 1 : 2; 
    554 } 
    555  
    556 int 
    557 WorldSocket::cancel_wakeup_output (GuardType& g) 
    558 { 
    559   if (!m_OutActive) 
     513        //just recieved fresh new payload 
     514        if (handle_input_payload () == -1) 
     515        { 
     516            ACE_ASSERT ((errno != EWOULDBLOCK) && (errno != EAGAIN)); 
     517            return -1; 
     518        } 
     519    } 
     520 
     521    return n == recv_size ? 1 : 2; 
     522} 
     523 
     524int WorldSocket::cancel_wakeup_output (GuardType& g) 
     525{ 
     526    if (!m_OutActive) 
     527        return 0; 
     528 
     529    m_OutActive = false; 
     530 
     531    g.release (); 
     532 
     533    if (reactor ()->cancel_wakeup 
     534        (this, ACE_Event_Handler::WRITE_MASK) == -1) 
     535    { 
     536        // would be good to store errno from reactor with errno guard 
     537        sLog.outError ("WorldSocket::cancel_wakeup_output"); 
     538        return -1; 
     539    } 
     540 
    560541    return 0; 
    561  
    562   m_OutActive = false; 
    563  
    564   g.release (); 
    565  
    566   if (this->reactor ()->cancel_wakeup 
    567       (this, ACE_Event_Handler::WRITE_MASK) == -1) 
    568     { 
    569       // would be good to store errno from reactor with errno guard 
    570       sLog.outError ("WorldSocket::cancel_wakeup_output"); 
    571       return -1; 
    572     } 
    573  
    574   return 0; 
    575 } 
    576  
    577 int 
    578 WorldSocket::schedule_wakeup_output (GuardType& g) 
    579 { 
    580   if (m_OutActive) 
     542} 
     543 
     544int WorldSocket::schedule_wakeup_output (GuardType& g) 
     545{ 
     546    if (m_OutActive) 
     547        return 0; 
     548 
     549    m_OutActive = true; 
     550 
     551    g.release (); 
     552 
     553    if (reactor ()->schedule_wakeup 
     554        (this, ACE_Event_Handler::WRITE_MASK) == -1) 
     555    { 
     556        sLog.outError ("WorldSocket::schedule_wakeup_output"); 
     557        return -1; 
     558    } 
     559 
    581560    return 0; 
    582  
    583   m_OutActive = true; 
    584  
    585   g.release (); 
    586  
    587   if (this->reactor ()->schedule_wakeup 
    588       (this, ACE_Event_Handler::WRITE_MASK) == -1) 
    589     { 
    590       sLog.outError ("WorldSocket::schedule_wakeup_output"); 
    591       return -1; 
    592     } 
    593  
    594   return 0; 
    595 } 
    596  
    597 int 
    598 WorldSocket::ProcessIncoming (WorldPacket* new_pct) 
    599 { 
    600   ACE_ASSERT (new_pct); 
    601  
    602   // manage memory ;) 
    603   ACE_Auto_Ptr<WorldPacket> aptr (new_pct); 
    604  
    605   const ACE_UINT16 opcode = new_pct->GetOpcode (); 
    606  
    607   if (this->closing_) 
    608     return -1; 
    609  
    610   // dump recieved packet 
    611   if (sWorldLog.LogWorld ()) 
    612     { 
    613       sWorldLog.Log ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
     561} 
     562 
     563int WorldSocket::ProcessIncoming (WorldPacket* new_pct) 
     564{ 
     565    ACE_ASSERT (new_pct); 
     566 
     567    // manage memory ;) 
     568    ACE_Auto_Ptr<WorldPacket> aptr (new_pct); 
     569 
     570    const ACE_UINT16 opcode = new_pct->GetOpcode (); 
     571 
     572    if (closing_) 
     573        return -1; 
     574 
     575    // dump recieved packet 
     576    if (sWorldLog.LogWorld ()) 
     577    { 
     578        sWorldLog.Log ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", 
    614579                     (uint32) get_handle (), 
    615580                     new_pct->size (), 
     
    617582                     new_pct->GetOpcode ()); 
    618583 
    619       uint32 p = 0; 
    620       while (p < new_pct->size ()) 
    621         { 
    622           for (uint32 j = 0; j < 16 && p < new_pct->size (); j++) 
    623             sWorldLog.Log ("%.2X ", (*new_pct)[p++]); 
    624           sWorldLog.Log ("\n"); 
    625         } 
    626       sWorldLog.Log ("\n\n"); 
    627     } 
    628  
    629   // like one switch ;) 
    630   if (opcode == CMSG_PING) 
    631     { 
    632       return HandlePing (*new_pct); 
    633     } 
    634   else if (opcode == CMSG_AUTH_SESSION) 
    635     { 
    636       if (m_Session) 
    637         { 
    638           sLog.outError ("WorldSocket::ProcessIncoming: Player send CMSG_AUTH_SESSION again"); 
    639           return -1; 
    640         } 
    641  
    642       return HandleAuthSession (*new_pct); 
    643     } 
    644   else if (opcode == CMSG_KEEP_ALIVE) 
    645     { 
    646       DEBUG_LOG ("CMSG_KEEP_ALIVE ,size: %d", new_pct->size ()); 
    647  
    648       return 0; 
    649     } 
    650   else 
    651     { 
    652       ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
    653  
    654       if (m_Session != NULL) 
    655         { 
    656           // OK ,give the packet to WorldSession 
    657           aptr.release (); 
    658           // WARNINIG here we call it with locks held. 
    659           // Its possible to cause deadlock if QueuePacket calls back 
    660           m_Session->QueuePacket (new_pct); 
    661           return 0; 
    662         } 
    663       else 
    664         { 
    665           sLog.outError ("WorldSocket::ProcessIncoming: Client not authed opcode = ", opcode); 
    666           return -1; 
    667         } 
    668     } 
    669  
    670   ACE_NOTREACHED (return 0); 
    671 } 
    672  
    673 int 
    674 WorldSocket::HandleAuthSession (WorldPacket& recvPacket) 
    675 { 
    676   uint8 digest[20]; 
    677   uint32 clientSeed; 
    678   uint32 unk2; 
    679   uint32 BuiltNumberClient; 
    680   uint32 id, security; 
    681   //uint8 expansion = 0; 
    682   LocaleConstant locale; 
    683   std::string account; 
    684   Sha1Hash sha1; 
    685   BigNumber v, s, g, N, x, I; 
    686   WorldPacket packet, SendAddonPacked; 
    687  
    688   BigNumber K; 
    689  
    690   if (recvPacket.size () < (4 + 4 + 1 + 4 + 20)) 
    691     { 
    692       sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size"); 
    693       return -1; 
    694     } 
    695  
    696   // Read the content of the packet 
    697   recvPacket >> BuiltNumberClient; // for now no use 
    698   recvPacket >> unk2; 
    699   recvPacket >> account; 
    700  
    701   if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) 
    702     { 
    703       sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check"); 
    704       return -1; 
    705     } 
    706  
    707   recvPacket >> clientSeed; 
    708   recvPacket.read (digest, 20); 
    709  
    710   DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", 
    711              BuiltNumberClient, 
    712              unk2, 
    713              account.c_str (), 
    714              clientSeed); 
    715  
    716   // Get the account information from the realmd database 
    717   std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below 
    718   loginDatabase.escape_string (safe_account); 
    719   // No SQL injection, username escaped. 
    720  
    721   QueryResult *result = 
     584        uint32 p = 0; 
     585        while (p < new_pct->size ()) 
     586        { 
     587            for (uint32 j = 0; j < 16 && p < new_pct->size (); j++) 
     588                sWorldLog.Log ("%.2X ", (*new_pct)[p++]); 
     589            sWorldLog.Log ("\n"); 
     590        } 
     591        sWorldLog.Log ("\n\n"); 
     592    } 
     593 
     594    // like one switch ;) 
     595    if (opcode == CMSG_PING) 
     596    { 
     597        return HandlePing (*new_pct); 
     598    } 
     599    else if (opcode == CMSG_AUTH_SESSION) 
     600    { 
     601        if (m_Session) 
     602        { 
     603            sLog.outError ("WorldSocket::ProcessIncoming: Player send CMSG_AUTH_SESSION again"); 
     604            return -1; 
     605        } 
     606 
     607        return HandleAuthSession (*new_pct); 
     608    } 
     609    else if (opcode == CMSG_KEEP_ALIVE) 
     610    { 
     611        DEBUG_LOG ("CMSG_KEEP_ALIVE ,size: %d", new_pct->size ()); 
     612 
     613        return 0; 
     614    } 
     615    else 
     616    { 
     617        ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     618 
     619        if (m_Session != NULL) 
     620        { 
     621            // OK ,give the packet to WorldSession 
     622            aptr.release (); 
     623            // WARNINIG here we call it with locks held. 
     624            // Its possible to cause deadlock if QueuePacket calls back 
     625            m_Session->QueuePacket (new_pct); 
     626            return 0; 
     627        } 
     628        else 
     629        { 
     630            sLog.outError ("WorldSocket::ProcessIncoming: Client not authed opcode = ", opcode); 
     631            return -1; 
     632        } 
     633    } 
     634 
     635    ACE_NOTREACHED (return 0); 
     636} 
     637 
     638int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) 
     639{ 
     640    // NOTE: ATM the socket is singlethreaded, have this in mind ... 
     641    uint8 digest[20]; 
     642    uint32 clientSeed; 
     643    uint32 unk2; 
     644    uint32 BuiltNumberClient; 
     645    uint32 id, security; 
     646    //uint8 expansion = 0; 
     647    LocaleConstant locale; 
     648    std::string account; 
     649    Sha1Hash sha1; 
     650    BigNumber v, s, g, N, x, I; 
     651    WorldPacket packet, SendAddonPacked; 
     652 
     653    BigNumber K; 
     654 
     655    if (recvPacket.size () < (4 + 4 + 1 + 4 + 20)) 
     656    { 
     657        sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size"); 
     658        return -1; 
     659    } 
     660 
     661    // Read the content of the packet 
     662    recvPacket >> BuiltNumberClient;                        // for now no use 
     663    recvPacket >> unk2; 
     664    recvPacket >> account; 
     665 
     666    if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) 
     667    { 
     668        sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check"); 
     669        return -1; 
     670    } 
     671 
     672    recvPacket >> clientSeed; 
     673    recvPacket.read (digest, 20); 
     674 
     675    DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", 
     676                BuiltNumberClient, 
     677                unk2, 
     678                account.c_str (), 
     679                clientSeed); 
     680 
     681    // Get the account information from the realmd database 
     682    std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below 
     683    loginDatabase.escape_string (safe_account); 
     684    // No SQL injection, username escaped. 
     685 
     686    QueryResult *result = 
    722687          loginDatabase.PQuery ("SELECT " 
    723688                                "id, " //0 
     
    736701                                safe_account.c_str ()); 
    737702 
    738   // Stop if the account is not found 
    739   if (!result) 
    740     { 
    741       packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
    742       packet << uint8 (AUTH_UNKNOWN_ACCOUNT); 
    743  
    744       SendPacket (packet); 
    745  
    746       sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); 
    747       return -1; 
    748     } 
    749  
    750   Field* fields = result->Fetch (); 
     703    // Stop if the account is not found 
     704    if (!result) 
     705    { 
     706        packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     707        packet << uint8 (AUTH_UNKNOWN_ACCOUNT); 
     708 
     709        SendPacket (packet); 
     710 
     711        sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (unknown account)."); 
     712        return -1; 
     713    } 
     714 
     715    Field* fields = result->Fetch (); 
    751716 
    752717    uint8 expansion = fields[8].GetUInt8(); 
     
    755720        expansion = world_expansion; 
    756721 
    757   N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); 
    758   g.SetDword (7); 
    759   I.SetHexStr (fields[5].GetString ()); 
    760  
    761   //In case of leading zeros in the I hash, restore them 
    762   uint8 mDigest[SHA_DIGEST_LENGTH]; 
    763   memset (mDigest, 0, SHA_DIGEST_LENGTH); 
    764  
    765   if (I.GetNumBytes () <= SHA_DIGEST_LENGTH) 
    766     memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ()); 
    767  
    768   std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH); 
    769  
    770   s.SetHexStr (fields[7].GetString ()); 
    771   sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ()); 
    772   sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH); 
    773   sha1.Finalize (); 
    774   x.SetBinary (sha1.GetDigest (), sha1.GetLength ()); 
    775   v = g.ModExp (x, N); 
    776  
    777   const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free() 
    778   const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free() 
    779   const char* vold = fields[6].GetString (); 
    780  
    781   DEBUG_LOG ("WorldSocket::HandleAuthSession: " 
    782              "(s,v) check s: %s v_old: %s v_new: %s", 
    783              sStr, 
    784              vold, 
    785              vStr); 
    786  
    787   loginDatabase.PExecute ("UPDATE account " 
    788                           "SET " 
    789                           "v = '0', " 
    790                           "s = '0' " 
    791                           "WHERE username = '%s'", 
    792                           safe_account.c_str ()); 
    793  
    794   if (!vold || strcmp (vStr, vold)) 
    795     { 
    796       packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
    797       packet << uint8 (AUTH_UNKNOWN_ACCOUNT); 
    798       SendPacket (packet); 
    799       delete result; 
    800       OPENSSL_free ((void*) sStr); 
    801       OPENSSL_free ((void*) vStr); 
    802  
    803       sLog.outBasic ("WorldSocket::HandleAuthSession: User not logged."); 
    804       return -1; 
    805     } 
    806  
    807   OPENSSL_free ((void*) sStr); 
    808   OPENSSL_free ((void*) vStr); 
    809  
    810   ///- Re-check ip locking (same check as in realmd). 
    811   if (fields[4].GetUInt8 () == 1) // if ip is locked 
    812     { 
    813       if (strcmp (fields[3].GetString (), GetRemoteAddress ().c_str ())) 
    814         { 
    815           packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
    816           packet << uint8 (AUTH_FAILED); 
    817           SendPacket (packet); 
    818  
    819           delete result; 
    820           sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); 
    821           return -1; 
    822         } 
    823     } 
    824  
    825   id = fields[0].GetUInt32 (); 
    826   security = fields[1].GetUInt16 (); 
    827   K.SetHexStr (fields[2].GetString ()); 
    828  
    829   time_t mutetime = time_t (fields[9].GetUInt64 ()); 
    830  
    831   locale = LocaleConstant (fields[10].GetUInt8 ()); 
    832   if (locale >= MAX_LOCALE) 
    833     locale = LOCALE_enUS; 
    834  
    835   delete result; 
    836  
    837   // Re-check account ban (same check as in realmd)  
    838   QueryResult *banresult = 
     722    N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); 
     723    g.SetDword (7); 
     724    I.SetHexStr (fields[5].GetString ()); 
     725 
     726    //In case of leading zeros in the I hash, restore them 
     727    uint8 mDigest[SHA_DIGEST_LENGTH]; 
     728    memset (mDigest, 0, SHA_DIGEST_LENGTH); 
     729 
     730    if (I.GetNumBytes () <= SHA_DIGEST_LENGTH) 
     731        memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ()); 
     732 
     733    std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH); 
     734 
     735    s.SetHexStr (fields[7].GetString ()); 
     736    sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ()); 
     737    sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH); 
     738    sha1.Finalize (); 
     739    x.SetBinary (sha1.GetDigest (), sha1.GetLength ()); 
     740    v = g.ModExp (x, N); 
     741 
     742    const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free() 
     743    const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free() 
     744    const char* vold = fields[6].GetString (); 
     745 
     746    DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v_old: %s v_new: %s", 
     747                sStr, 
     748                vold, 
     749                vStr); 
     750 
     751    loginDatabase.PExecute ("UPDATE account " 
     752                            "SET " 
     753                            "v = '0', " 
     754                            "s = '0' " 
     755                            "WHERE username = '%s'", 
     756                            safe_account.c_str ()); 
     757 
     758    if (!vold || strcmp (vStr, vold)) 
     759    { 
     760        packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     761        packet << uint8 (AUTH_UNKNOWN_ACCOUNT); 
     762        SendPacket (packet); 
     763        delete result; 
     764        OPENSSL_free ((void*) sStr); 
     765        OPENSSL_free ((void*) vStr); 
     766 
     767        sLog.outBasic ("WorldSocket::HandleAuthSession: User not logged."); 
     768        return -1; 
     769    } 
     770 
     771    OPENSSL_free ((void*) sStr); 
     772    OPENSSL_free ((void*) vStr); 
     773 
     774    ///- Re-check ip locking (same check as in realmd). 
     775    if (fields[4].GetUInt8 () == 1) // if ip is locked 
     776    { 
     777        if (strcmp (fields[3].GetString (), GetRemoteAddress ().c_str ())) 
     778        { 
     779            packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     780            packet << uint8 (AUTH_FAILED); 
     781            SendPacket (packet); 
     782 
     783            delete result; 
     784            sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account IP differs)."); 
     785            return -1; 
     786        } 
     787    } 
     788 
     789    id = fields[0].GetUInt32 (); 
     790    security = fields[1].GetUInt16 (); 
     791    K.SetHexStr (fields[2].GetString ()); 
     792 
     793    time_t mutetime = time_t (fields[9].GetUInt64 ()); 
     794 
     795    locale = LocaleConstant (fields[10].GetUInt8 ()); 
     796    if (locale >= MAX_LOCALE) 
     797        locale = LOCALE_enUS; 
     798 
     799    delete result; 
     800 
     801    // Re-check account ban (same check as in realmd) 
     802    QueryResult *banresult = 
    839803          loginDatabase.PQuery ("SELECT " 
    840804                                "bandate, " 
     
    845809                                id); 
    846810 
    847   if (banresult) // if account banned 
    848     { 
    849       packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
    850       packet << uint8 (AUTH_BANNED); 
    851       SendPacket (packet); 
    852  
    853       delete banresult; 
    854  
    855       sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); 
    856       return -1; 
    857     } 
    858  
    859   // Check locked state for server 
    860   AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit (); 
    861  
    862   if (allowedAccountType > SEC_PLAYER && security < allowedAccountType) 
    863     { 
    864       WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); 
    865       Packet << uint8 (AUTH_UNAVAILABLE); 
    866  
    867       SendPacket (packet); 
    868  
    869       sLog.outBasic ("WorldSocket::HandleAuthSession: User tryes to login but his security level is not enough"); 
    870       return -1; 
    871     } 
    872  
    873   // Check that Key and account name are the same on client and server 
    874   Sha1Hash sha; 
    875  
    876   uint32 t = 0; 
    877   uint32 seed = m_Seed; 
    878  
    879   sha.UpdateData (account); 
    880   sha.UpdateData ((uint8 *) & t, 4); 
    881   sha.UpdateData ((uint8 *) & clientSeed, 4); 
    882   sha.UpdateData ((uint8 *) & seed, 4); 
    883   sha.UpdateBigNumbers (&K, NULL); 
    884   sha.Finalize (); 
    885  
    886   if (memcmp (sha.GetDigest (), digest, 20)) 
    887     { 
    888       packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
    889       packet << uint8 (AUTH_FAILED); 
    890  
    891       SendPacket (packet); 
    892  
    893       sLog.outBasic ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); 
    894       return -1; 
    895     } 
    896  
    897   std::string address = this->GetRemoteAddress (); 
    898  
    899   DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", 
    900              account.c_str (), 
    901              address.c_str ()); 
    902  
    903   // Update the last_ip in the database 
    904   // No SQL injection, username escaped. 
    905   loginDatabase.escape_string (address); 
    906  
    907   loginDatabase.PExecute ("UPDATE account " 
    908                           "SET last_ip = '%s' " 
    909                           "WHERE username = '%s'", 
    910                           address.c_str (), 
    911                           safe_account.c_str ()); 
    912  
    913   // TODO protect here probably ? 
    914   // Althought atm the socket is singlethreaded 
    915   ACE_NEW_RETURN (m_Session, WorldSession (id, this, security, expansion, mutetime, locale), -1); 
    916  
    917   m_Crypt.SetKey (&K); 
    918   m_Crypt.Init (); 
    919  
    920   // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec 
    921   ACE_OS::sleep (ACE_Time_Value (0, 10000)); 
    922  
    923   // TODO error handling 
    924   sWorld.AddSession (this->m_Session); 
    925  
    926   // Create and send the Addon packet 
    927   if (sAddOnHandler.BuildAddonPacket (&recvPacket, &SendAddonPacked)) 
    928     SendPacket (SendAddonPacked); 
    929  
    930   return 0; 
    931 } 
    932  
    933 int 
    934 WorldSocket::HandlePing (WorldPacket& recvPacket) 
    935 { 
    936   uint32 ping; 
    937   uint32 latency; 
    938  
    939   if (recvPacket.size () < 8) 
    940     { 
    941       sLog.outError ("WorldSocket::_HandlePing wrong packet size"); 
    942       return -1; 
    943     } 
    944  
    945   // Get the ping packet content 
    946   recvPacket >> ping; 
    947   recvPacket >> latency; 
    948  
    949   if (m_LastPingTime == ACE_Time_Value::zero) 
    950     m_LastPingTime = ACE_OS::gettimeofday (); // for 1st ping 
    951   else 
    952     { 
    953       ACE_Time_Value cur_time = ACE_OS::gettimeofday (); 
    954       ACE_Time_Value diff_time (cur_time); 
    955       diff_time -= m_LastPingTime; 
    956       m_LastPingTime = cur_time; 
    957  
    958       if (diff_time < ACE_Time_Value (27)) 
    959         { 
    960           ++m_OverSpeedPings; 
    961  
    962           uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS); 
    963  
    964           if (max_count && m_OverSpeedPings > max_count) 
     811    if (banresult) // if account banned 
     812    { 
     813        packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     814        packet << uint8 (AUTH_BANNED); 
     815        SendPacket (packet); 
     816 
     817        delete banresult; 
     818 
     819        sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (Account banned)."); 
     820        return -1; 
     821    } 
     822 
     823    // Check locked state for server 
     824    AccountTypes allowedAccountType = sWorld.GetPlayerSecurityLimit (); 
     825 
     826    if (allowedAccountType > SEC_PLAYER && security < allowedAccountType) 
     827    { 
     828        WorldPacket Packet (SMSG_AUTH_RESPONSE, 1); 
     829        Packet << uint8 (AUTH_UNAVAILABLE); 
     830 
     831        SendPacket (packet); 
     832 
     833        sLog.outBasic ("WorldSocket::HandleAuthSession: User tryes to login but his security level is not enough"); 
     834        return -1; 
     835    } 
     836 
     837    // Check that Key and account name are the same on client and server 
     838    Sha1Hash sha; 
     839 
     840    uint32 t = 0; 
     841    uint32 seed = m_Seed; 
     842 
     843    sha.UpdateData (account); 
     844    sha.UpdateData ((uint8 *) & t, 4); 
     845    sha.UpdateData ((uint8 *) & clientSeed, 4); 
     846    sha.UpdateData ((uint8 *) & seed, 4); 
     847    sha.UpdateBigNumbers (&K, NULL); 
     848    sha.Finalize (); 
     849 
     850    if (memcmp (sha.GetDigest (), digest, 20)) 
     851    { 
     852        packet.Initialize (SMSG_AUTH_RESPONSE, 1); 
     853        packet << uint8 (AUTH_FAILED); 
     854 
     855        SendPacket (packet); 
     856 
     857        sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); 
     858        return -1; 
     859    } 
     860 
     861    std::string address = GetRemoteAddress (); 
     862 
     863    DEBUG_LOG ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", 
     864                account.c_str (), 
     865                address.c_str ()); 
     866 
     867    // Update the last_ip in the database 
     868    // No SQL injection, username escaped. 
     869    loginDatabase.escape_string (address); 
     870 
     871    loginDatabase.PExecute ("UPDATE account " 
     872                            "SET last_ip = '%s' " 
     873                            "WHERE username = '%s'", 
     874                            address.c_str (), 
     875                            safe_account.c_str ()); 
     876 
     877    // NOTE ATM the socket is singlethreaded, have this in mind ... 
     878    ACE_NEW_RETURN (m_Session, WorldSession (id, this, security, expansion, mutetime, locale), -1); 
     879 
     880    m_Crypt.SetKey (&K); 
     881    m_Crypt.Init (); 
     882 
     883    // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec 
     884    ACE_OS::sleep (ACE_Time_Value (0, 10000)); 
     885 
     886    sWorld.AddSession (m_Session); 
     887 
     888    // Create and send the Addon packet 
     889    if (sAddOnHandler.BuildAddonPacket (&recvPacket, &SendAddonPacked)) 
     890        SendPacket (SendAddonPacked); 
     891 
     892    return 0; 
     893} 
     894 
     895int WorldSocket::HandlePing (WorldPacket& recvPacket) 
     896{ 
     897    uint32 ping; 
     898    uint32 latency; 
     899 
     900    if (recvPacket.size () < 8) 
     901    { 
     902        sLog.outError ("WorldSocket::_HandlePing wrong packet size"); 
     903        return -1; 
     904    } 
     905 
     906    // Get the ping packet content 
     907    recvPacket >> ping; 
     908    recvPacket >> latency; 
     909 
     910    if (m_LastPingTime == ACE_Time_Value::zero) 
     911        m_LastPingTime = ACE_OS::gettimeofday (); // for 1st ping 
     912    else 
     913    { 
     914        ACE_Time_Value cur_time = ACE_OS::gettimeofday (); 
     915        ACE_Time_Value diff_time (cur_time); 
     916        diff_time -= m_LastPingTime; 
     917        m_LastPingTime = cur_time; 
     918 
     919        if (diff_time < ACE_Time_Value (27)) 
     920        { 
     921            ++m_OverSpeedPings; 
     922 
     923            uint32 max_count = sWorld.getConfig (CONFIG_MAX_OVERSPEED_PINGS); 
     924 
     925            if (max_count && m_OverSpeedPings > max_count) 
    965926            { 
    966               ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
    967  
    968               if (m_Session && m_Session->GetSecurity () == SEC_PLAYER) 
     927                ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     928 
     929                if (m_Session && m_Session->GetSecurity () == SEC_PLAYER) 
    969930                { 
    970                   sLog.outError ("WorldSocket::HandlePing: Player kicked for " 
    971                                  "overspeeded pings adress = %s", 
    972                                  GetRemoteAddress ().c_str ()); 
    973  
    974                   return -1; 
     931                    sLog.outError ("WorldSocket::HandlePing: Player kicked for " 
     932                                    "overspeeded pings adress = %s", 
     933                                    GetRemoteAddress ().c_str ()); 
     934 
     935                    return -1; 
    975936                } 
    976937            } 
    977938        } 
    978       else 
    979         m_OverSpeedPings = 0; 
    980     } 
    981  
    982   // critical section 
    983   { 
    984     ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
    985  
    986     if (m_Session) 
    987       m_Session->SetLatency (latency); 
    988     else 
    989       { 
    990         sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, " 
    991                        "but is not authenticated or got recently kicked," 
    992                        " adress = %s", 
    993                        this->GetRemoteAddress ().c_str ()); 
    994         return -1; 
    995       } 
    996   } 
    997  
    998   WorldPacket packet (SMSG_PONG, 4); 
    999   packet << ping; 
    1000   return this->SendPacket (packet); 
    1001 } 
    1002  
    1003 int 
    1004 WorldSocket::iSendPacket (const WorldPacket& pct) 
    1005 { 
    1006   if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader)) 
    1007     { 
    1008       errno = ENOBUFS; 
    1009       return -1; 
    1010     } 
    1011  
    1012   ServerPktHeader header; 
    1013  
    1014   header.cmd = pct.GetOpcode (); 
    1015  
    1016 #if ACE_BYTE_ORDER == ACE_BIG_ENDIAN 
    1017   header.cmd = ACE_SWAP_WORD (header.cmd) 
    1018 #endif 
    1019  
    1020           header.size = (uint16) pct.size () + 2; 
    1021   header.size = ACE_HTONS (header.size); 
    1022  
    1023   m_Crypt.EncryptSend ((uint8*) & header, sizeof (header)); 
    1024  
    1025   if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1) 
    1026     ACE_ASSERT (false); 
    1027  
    1028   if (!pct.empty ()) 
    1029     if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1) 
    1030       ACE_ASSERT (false); 
    1031  
    1032   return 0; 
    1033 } 
    1034  
    1035 bool 
    1036 WorldSocket::iFlushPacketQueue () 
    1037 { 
    1038   WorldPacket *pct; 
    1039   bool haveone = false; 
    1040  
    1041   while (m_PacketQueue.dequeue_head (pct) == 0) 
    1042     { 
    1043       if (iSendPacket (*pct) == -1) 
    1044         { 
    1045           if (m_PacketQueue.enqueue_head (pct) == -1) 
     939        else 
     940            m_OverSpeedPings = 0; 
     941    } 
     942 
     943    // critical section 
     944    { 
     945        ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1); 
     946 
     947        if (m_Session) 
     948        m_Session->SetLatency (latency); 
     949        else 
     950        { 
     951            sLog.outError ("WorldSocket::HandlePing: peer sent CMSG_PING, " 
     952                            "but is not authenticated or got recently kicked," 
     953                            " adress = %s", 
     954                            GetRemoteAddress ().c_str ()); 
     955             return -1; 
     956        } 
     957    } 
     958 
     959    WorldPacket packet (SMSG_PONG, 4); 
     960    packet << ping; 
     961    return SendPacket (packet); 
     962} 
     963 
     964int WorldSocket::iSendPacket (const WorldPacket& pct) 
     965{ 
     966    if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader)) 
     967    { 
     968        errno = ENOBUFS; 
     969        return -1; 
     970    } 
     971 
     972    ServerPktHeader header; 
     973 
     974    header.cmd = pct.GetOpcode (); 
     975    EndianConvert(header.cmd); 
     976 
     977    header.size = (uint16) pct.size () + 2; 
     978    EndianConvertReverse(header.size); 
     979 
     980    m_Crypt.EncryptSend ((uint8*) & header, sizeof (header)); 
     981 
     982    if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1) 
     983        ACE_ASSERT (false); 
     984 
     985    if (!pct.empty ()) 
     986        if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1) 
     987            ACE_ASSERT (false); 
     988 
     989    return 0; 
     990} 
     991 
     992bool WorldSocket::iFlushPacketQueue () 
     993{ 
     994    WorldPacket *pct; 
     995    bool haveone = false; 
     996 
     997    while (m_PacketQueue.dequeue_head (pct) == 0) 
     998    { 
     999        if (iSendPacket (*pct) == -1) 
     1000        { 
     1001            if (m_PacketQueue.enqueue_head (pct) == -1) 
    10461002            { 
    1047               delete pct; 
    1048               sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head"); 
    1049               return false; 
     1003                delete pct; 
     1004                sLog.outError ("WorldSocket::iFlushPacketQueue m_PacketQueue->enqueue_head"); 
     1005                return false; 
    10501006            } 
    10511007 
    1052           break; 
    1053         } 
    1054       else 
    1055         { 
    1056           haveone = true; 
    1057           delete pct; 
    1058         } 
    1059     } 
    1060  
    1061   return haveone; 
    1062 } 
     1008            break; 
     1009        } 
     1010        else 
     1011        { 
     1012            haveone = true; 
     1013            delete pct; 
     1014        } 
     1015    } 
     1016 
     1017    return haveone; 
     1018} 
  • trunk/src/game/WorldSocket.h

    r102 r181  
    1111 * This program is distributed in the hope that it will be useful, 
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1414 * GNU General Public License for more details. 
    1515 * 
    1616 * You should have received a copy of the GNU General Public License 
    1717 * along with this program; if not, write to the Free Software 
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
     18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
    1919 */ 
    2020 
     
    2626 
    2727#ifndef _WORLDSOCKET_H 
    28 #define _WORLDSOCKET_H 
     28#define _WORLDSOCKET_H 
    2929 
    3030#include <ace/Basic_Types.h> 
     
    4444 
    4545#include "Common.h" 
    46 #include "Auth/AuthCrypt.h"  
     46#include "Auth/AuthCrypt.h" 
    4747 
    4848class ACE_Message_Block; 
     
    5555/** 
    5656 * WorldSocket. 
    57  *  
    58  * This class is responsible for the comunication with  
     57 * 
     58 * This class is responsible for the comunication with 
    5959 * remote clients. 
    60  * Most methods return -1 on failure.  
     60 * Most methods return -1 on failure. 
    6161 * The class uses refferece counting. 
    6262 * 
    63  * For output the class uses one buffer (64K usually) and  
    64  * a queue where it stores packet if there is no place on  
    65  * the queue. The reason this is done, is because the server  
    66  * does realy a lot of small-size writes to it, and it doesn't  
    67  * scale well to allocate memory for every. When something is  
    68  * writen to the output buffer the socket is not immideately  
    69  * activated for output (again for the same reason), there  
    70  * is 10ms celling (thats why there is Update() method).  
    71  * This concept is simmilar to TCP_CORK, but TCP_CORK  
    72  * usses 200ms celling. As result overhead generated by  
    73  * sending packets from "producer" threads is minimal,  
     63 * For output the class uses one buffer (64K usually) and 
     64 * a queue where it stores packet if there is no place on 
     65 * the queue. The reason this is done, is because the server 
     66 * does realy a lot of small-size writes to it, and it doesn't 
     67 * scale well to allocate memory for every. When something is 
     68 * writen to the output buffer the socket is not immideately 
     69 * activated for output (again for the same reason), there 
     70 * is 10ms celling (thats why there is Update() method). 
     71 * This concept is simmilar to TCP_CORK, but TCP_CORK 
     72 * usses 200ms celling. As result overhead generated by 
     73 * sending packets from "producer" threads is minimal, 
    7474 * and doing a lot of writes with small size is tollerated. 
    75  *  
     75 * 
    7676 * The calls to Upate () method are managed by WorldSocketMgr 
    7777 * and ReactorRunnable. 
    78  *  
    79  * For input ,the class uses one 1024 bytes buffer on stack  
    80  * to which it does recv() calls. And then recieved data is  
    81  * distributed where its needed. 1024 matches pritey well the  
     78 * 
     79 * For input ,the class uses one 1024 bytes buffer on stack 
     80 * to which it does recv() calls. And then recieved data is 
     81 * distributed where its needed. 1024 matches pritey well the 
    8282 * traffic generated by client for now. 
    83  *   
    84  * The input/output do speculative reads/writes (AKA it tryes  
    85  * to read all data avaible in the kernel buffer or tryes to  
    86  * write everything avaible in userspace buffer),  
    87  * which is ok for using with Level and Edge Trigered IO  
     83 * 
     84 * The input/output do speculative reads/writes (AKA it tryes 
     85 * to read all data avaible in the kernel buffer or tryes to 
     86 * write everything avaible in userspace buffer), 
     87 * which is ok for using with Level and Edge Trigered IO 
    8888 * notification. 
    89  *  
     89 * 
    9090 */ 
    9191class WorldSocket : protected WorldHandler 
    9292{ 
    93 public: 
    94   /// Declare some friends 
    95   friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >; 
    96   friend class WorldSocketMgr; 
    97   friend class ReactorRunnable; 
    98  
    99   /// Declare the acceptor for this class 
    100   typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor; 
    101  
    102   /// Mutex type used for various syncronizations. 
    103   typedef ACE_Thread_Mutex LockType; 
    104   typedef ACE_Guard<LockType> GuardType; 
    105  
    106   /// Queue for storing packets for which there is no space. 
    107   typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT; 
    108  
    109   /// Check if socket is closed. 
    110   bool IsClosed (void) const; 
    111  
    112   /// Close the socket. 
    113   void CloseSocket (void); 
    114  
    115   /// Get address of connected peer. 
    116   const std::string& GetRemoteAddress (void) const; 
    117  
    118   /// Send A packet on the socket, this function is reentrant. 
    119   /// @param pct packet to send 
    120   /// @return -1 of failure 
    121   int SendPacket (const WorldPacket& pct); 
    122  
    123   /// Add refference to this object. 
    124   long AddReference (void); 
    125  
    126   /// Remove refference to this object. 
    127   long RemoveReference (void); 
    128  
    129 protected: 
    130   /// things called by ACE framework. 
    131   WorldSocket (void); 
    132   virtual ~WorldSocket (void); 
    133  
    134   /// Called on open ,the void* is the acceptor. 
    135   virtual int open (void *); 
    136  
    137   /// Called on failures inside of the acceptor, don't call from your code. 
    138   virtual int close (int); 
    139  
    140   /// Called when we can read from the socket. 
    141   virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); 
    142  
    143   /// Called when the socket can write. 
    144   virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE); 
    145  
    146   /// Called when connection is closed or error happens. 
    147   virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, 
    148                             ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); 
    149  
    150   /// Called by WorldSocketMgr/ReactorRunnable. 
    151   int Update (void); 
    152  
    153 private: 
    154   /// Helper functions for processing incoming data. 
    155   int handle_input_header (void); 
    156   int handle_input_payload (void); 
    157   int handle_input_missing_data (void); 
    158  
    159   /// Help functions to mark/unmark the socket for output. 
    160   /// @param g the guard is for m_OutBufferLock, the function will release it 
    161   int cancel_wakeup_output (GuardType& g); 
    162   int schedule_wakeup_output (GuardType& g); 
    163  
    164   /// process one incoming packet. 
    165   /// @param new_pct received packet ,note that you need to delete it.  
    166   int ProcessIncoming (WorldPacket* new_pct); 
    167  
    168   /// Called by ProcessIncoming() on CMSG_AUTH_SESSION. 
    169   int HandleAuthSession (WorldPacket& recvPacket); 
    170  
    171   /// Called by ProcessIncoming() on CMSG_PING. 
    172   int HandlePing (WorldPacket& recvPacket); 
    173  
    174   /// Try to write WorldPacket to m_OutBuffer ,return -1 if no space 
    175   /// Need to be called with m_OutBufferLock lock held 
    176   int iSendPacket (const WorldPacket& pct); 
    177  
    178   /// Flush m_PacketQueue if there are packets in it 
    179   /// Need to be called with m_OutBufferLock lock held 
    180   /// @return true if it wrote to the buffer ( AKA you need  
    181   /// to mark the socket for output ). 
    182   bool iFlushPacketQueue (); 
    183  
    184 private: 
    185   /// Time in which the last ping was received 
    186   ACE_Time_Value m_LastPingTime; 
    187    
    188   /// Keep track of overspeed pings ,to prevent ping flood. 
    189   uint32 m_OverSpeedPings; 
    190  
    191   /// Address of the remote peer 
    192   std::string m_Address; 
    193  
    194   /// Class used for managing encryption of the headers 
    195   AuthCrypt m_Crypt; 
    196  
    197   /// Mutex lock to protect m_Session 
    198   LockType m_SessionLock; 
    199  
    200   /// Session to which recieved packets are routed 
    201   WorldSession* m_Session; 
    202  
    203   /// here are stored the fragmens of the recieved data 
    204   WorldPacket* m_RecvWPct; 
    205  
    206   /// This block actually refers to m_RecvWPct contents, 
    207   /// which alows easy and safe writing to it.  
    208   /// It wont free memory when its deleted. m_RecvWPct takes care of freeing. 
    209   ACE_Message_Block m_RecvPct; 
    210  
    211   /// Fragment of the recieved header. 
    212   ACE_Message_Block m_Header; 
    213  
    214   /// Mutex for protecting otuput related data. 
    215   LockType m_OutBufferLock; 
    216  
    217   /// Buffer used for writing output. 
    218   ACE_Message_Block *m_OutBuffer; 
    219  
    220   /// Size of the m_OutBuffer. 
    221   size_t m_OutBufferSize; 
    222  
    223   /// Here are stored packets for which there was no space on m_OutBuffer, 
    224   /// this alows not-to kick player if its buffer is overflowed. 
    225   PacketQueueT m_PacketQueue; 
    226  
    227   /// True if the socket is registered with the reactor for output 
    228   bool m_OutActive; 
    229  
    230   uint32 m_Seed; 
     93    public: 
     94        /// Declare some friends 
     95        friend class ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR >; 
     96        friend class WorldSocketMgr; 
     97        friend class ReactorRunnable; 
     98 
     99        /// Declare the acceptor for this class 
     100        typedef ACE_Acceptor< WorldSocket, ACE_SOCK_ACCEPTOR > Acceptor; 
     101 
     102        /// Mutex type used for various syncronizations. 
     103        typedef ACE_Thread_Mutex LockType; 
     104        typedef ACE_Guard<LockType> GuardType; 
     105 
     106        /// Queue for storing packets for which there is no space. 
     107        typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT; 
     108 
     109        /// Check if socket is closed. 
     110        bool IsClosed (void) const; 
     111 
     112        /// Close the socket. 
     113        void CloseSocket (void); 
     114 
     115        /// Get address of connected peer. 
     116        const std::string& GetRemoteAddress (void) const; 
     117 
     118        /// Send A packet on the socket, this function is reentrant. 
     119        /// @param pct packet to send 
     120        /// @return -1 of failure 
     121        int SendPacket (const WorldPacket& pct); 
     122 
     123        /// Add refference to this object. 
     124        long AddReference (void); 
     125 
     126        /// Remove refference to this object. 
     127        long RemoveReference (void); 
     128 
     129    protected: 
     130        /// things called by ACE framework. 
     131        WorldSocket (void); 
     132        virtual ~WorldSocket (void); 
     133 
     134        /// Called on open ,the void* is the acceptor. 
     135        virtual int open (void *); 
     136 
     137        /// Called on failures inside of the acceptor, don't call from your code. 
     138        virtual int close (int); 
     139 
     140        /// Called when we can read from the socket. 
     141        virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE); 
     142 
     143        /// Called when the socket can write. 
     144        virtual int handle_output (ACE_HANDLE = ACE_INVALID_HANDLE); 
     145 
     146        /// Called when connection is closed or error happens. 
     147        virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, 
     148            ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); 
     149 
     150        /// Called by WorldSocketMgr/ReactorRunnable. 
     151        int Update (void); 
     152 
     153    private: 
     154        /// Helper functions for processing incoming data. 
     155        int handle_input_header (void); 
     156        int handle_input_payload (void); 
     157        int handle_input_missing_data (void); 
     158 
     159        /// Help functions to mark/unmark the socket for output. 
     160        /// @param g the guard is for m_OutBufferLock, the function will release it 
     161        int cancel_wakeup_output (GuardType& g); 
     162        int schedule_wakeup_output (GuardType& g); 
     163 
     164        /// process one incoming packet. 
     165        /// @param new_pct received packet ,note that you need to delete it. 
     166        int ProcessIncoming (WorldPacket* new_pct); 
     167 
     168        /// Called by ProcessIncoming() on CMSG_AUTH_SESSION. 
     169        int HandleAuthSession (WorldPacket& recvPacket); 
     170 
     171        /// Called by ProcessIncoming() on CMSG_PING. 
     172        int HandlePing (WorldPacket& recvPacket); 
     173 
     174        /// Try to write WorldPacket to m_OutBuffer ,return -1 if no space 
     175        /// Need to be called with m_OutBufferLock lock held 
     176        int iSendPacket (const WorldPacket& pct); 
     177 
     178        /// Flush m_PacketQueue if there are packets in it 
     179        /// Need to be called with m_OutBufferLock lock held 
     180        /// @return true if it wrote to the buffer ( AKA you need 
     181        /// to mark the socket for output ). 
     182        bool iFlushPacketQueue (); 
     183 
     184    private: 
     185        /// Time in which the last ping was received 
     186        ACE_Time_Value m_LastPingTime; 
     187 
     188        /// Keep track of overspeed pings ,to prevent ping flood. 
     189        uint32 m_OverSpeedPings; 
     190 
     191        /// Address of the remote peer 
     192        std::string m_Address; 
     193 
     194        /// Class used for managing encryption of the headers 
     195        AuthCrypt m_Crypt; 
     196 
     197        /// Mutex lock to protect m_Session 
     198        LockType m_SessionLock; 
     199 
     200        /// Session to which recieved packets are routed 
     201        WorldSession* m_Session; 
     202 
     203        /// here are stored the fragmens of the recieved data 
     204        WorldPacket* m_RecvWPct; 
     205 
     206        /// This block actually refers to m_RecvWPct contents, 
     207        /// which alows easy and safe writing to it. 
     208        /// It wont free memory when its deleted. m_RecvWPct takes care of freeing. 
     209        ACE_Message_Block m_RecvPct; 
     210 
     211        /// Fragment of the recieved header. 
     212        ACE_Message_Block m_Header; 
     213 
     214        /// Mutex for protecting otuput related data. 
     215        LockType m_OutBufferLock; 
     216 
     217        /// Buffer used for writing output. 
     218        ACE_Message_Block *m_OutBuffer; 
     219 
     220        /// Size of the m_OutBuffer. 
     221        size_t m_OutBufferSize; 
     222 
     223        /// Here are stored packets for which there was no space on m_OutBuffer, 
     224        /// this alows not-to kick player if its buffer is overflowed. 
     225        PacketQueueT m_PacketQueue; 
     226 
     227        /// True if the socket is registered with the reactor for output 
     228        bool m_OutActive; 
     229 
     230        uint32 m_Seed; 
    231231}; 
    232232 
    233 #endif  /* _WORLDSOCKET_H */ 
     233#endif  /* _WORLDSOCKET_H */ 
    234234 
    235235/// @}