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

[svn] *Implement new player conditions CONDITION_NO_AURA, CONDITION_ACTIVE_EVENT
* Default behaviour of pets for creatures changed to REACT_DEFENSIVE
* Disallowed sending wrapped items as COD
* Prevent loading and saving single target auras for pet in same way as already implemented for player
* Correctly limit use some flask types to zones.
* Fixed extracting common.MPQ under *nix
* Many small xleanups and fixes.
** mangos merge rev.

TEST REV so be careful of creepy crawly bugs!

Original author: KingPin?
Date: 2008-11-02 16:53:46-06:00

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/game/WorldSocketMgr.cpp

    r102 r149  
    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/** \file WorldSocketMgr.cpp 
    22  *  \ingroup u2w 
    23  *  \author Derex <derex101@gmail.com> 
    24  */ 
     22*  \ingroup u2w 
     23*  \author Derex <derex101@gmail.com> 
     24*/ 
    2525 
    2626#include "WorldSocketMgr.h" 
     
    4848 
    4949/**  
    50  * This is a helper class to WorldSocketMgr ,that manages  
    51  * network threads, and assigning connections from acceptor thread 
    52  * to other network threads 
    53  */ 
     50* This is a helper class to WorldSocketMgr ,that manages  
     51* network threads, and assigning connections from acceptor thread 
     52* to other network threads 
     53*/ 
    5454class ReactorRunnable : protected ACE_Task_Base 
    5555{ 
    5656public: 
    5757 
    58   ReactorRunnable () : 
    59   m_ThreadId (-1), 
    60   m_Connections (0), 
    61   m_Reactor (0) 
    62   { 
    63     ACE_Reactor_Impl* imp = 0; 
     58        ReactorRunnable () : 
     59          m_ThreadId (-1), 
     60                  m_Connections (0), 
     61                  m_Reactor (0) 
     62          { 
     63                  ACE_Reactor_Impl* imp = 0; 
    6464 
    6565#if defined (ACE_HAS_EVENT_POLL) || defined (ACE_HAS_DEV_POLL) 
    66     imp = new ACE_Dev_Poll_Reactor (); 
    67  
    68     imp->max_notify_iterations (128); 
    69     imp->restart (1); 
     66 
     67                  imp = new ACE_Dev_Poll_Reactor (); 
     68 
     69                  imp->max_notify_iterations (128); 
     70                  imp->restart (1); 
     71 
    7072#else 
    71     imp = new ACE_TP_Reactor (); 
    72     imp->max_notify_iterations (128); 
     73 
     74                  imp = new ACE_TP_Reactor (); 
     75                  imp->max_notify_iterations (128); 
     76 
    7377#endif 
    7478 
    75     m_Reactor = new ACE_Reactor (imp, 1); 
    76   } 
    77  
    78   virtual 
    79   ~ReactorRunnable () 
    80   { 
    81     this->Stop (); 
    82     this->Wait (); 
    83  
    84     if (m_Reactor) 
    85       delete m_Reactor; 
    86   } 
    87  
    88   void 
    89   Stop () 
    90   { 
    91     m_Reactor->end_reactor_event_loop (); 
    92   } 
    93  
    94   int 
    95   Start () 
    96   { 
    97     if (m_ThreadId != -1) 
    98       return -1; 
    99  
    100     return (m_ThreadId = this->activate ()); 
    101   } 
    102  
    103   void 
    104   Wait () 
    105   { 
    106     ACE_Task_Base::wait (); 
    107   } 
    108  
    109   long 
    110   Connections () 
    111   { 
    112     return static_cast<long> (m_Connections.value ()); 
    113   } 
    114  
    115   int 
    116   AddSocket (WorldSocket* sock) 
    117   { 
    118     ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, m_NewSockets_Lock, -1); 
    119  
    120     ++m_Connections; 
    121     sock->AddReference(); 
    122     sock->reactor (m_Reactor); 
    123     m_NewSockets.insert (sock); 
    124  
    125     return 0; 
    126   } 
    127    
    128   ACE_Reactor* GetReactor () 
    129   { 
    130     return m_Reactor; 
    131   } 
    132    
     79                  m_Reactor = new ACE_Reactor (imp, 1); 
     80          } 
     81 
     82          virtual ~ReactorRunnable () 
     83          { 
     84                  this->Stop (); 
     85                  this->Wait (); 
     86 
     87                  if (m_Reactor) 
     88                          delete m_Reactor; 
     89          } 
     90 
     91          void Stop () 
     92          { 
     93                  m_Reactor->end_reactor_event_loop (); 
     94          } 
     95 
     96          int Start () 
     97          { 
     98                  if (m_ThreadId != -1) 
     99                          return -1; 
     100 
     101                  return (m_ThreadId = this->activate ()); 
     102          } 
     103 
     104          void Wait () 
     105          { 
     106                  ACE_Task_Base::wait (); 
     107          } 
     108 
     109          long Connections () 
     110          { 
     111                  return static_cast<long> (m_Connections.value ()); 
     112          } 
     113 
     114          int AddSocket (WorldSocket* sock) 
     115          { 
     116                  ACE_GUARD_RETURN (ACE_Thread_Mutex, Guard, m_NewSockets_Lock, -1); 
     117 
     118                  ++m_Connections; 
     119                  sock->AddReference(); 
     120                  sock->reactor (m_Reactor); 
     121                  m_NewSockets.insert (sock); 
     122 
     123                  return 0; 
     124          } 
     125 
     126          ACE_Reactor* GetReactor () 
     127          { 
     128                  return m_Reactor; 
     129          } 
     130 
    133131protected: 
    134    
    135   void 
    136   AddNewSockets () 
    137   { 
    138     ACE_GUARD (ACE_Thread_Mutex, Guard, m_NewSockets_Lock); 
    139  
    140     if (m_NewSockets.empty ()) 
    141       return; 
    142  
    143     for (SocketSet::iterator i = m_NewSockets.begin (); i != m_NewSockets.end (); ++i) 
    144       { 
    145         WorldSocket* sock = (*i); 
    146  
    147         if (sock->IsClosed ()) 
    148           { 
    149             sock->RemoveReference (); 
    150             --m_Connections; 
    151           } 
    152         else 
    153           m_Sockets.insert (sock); 
    154       } 
    155  
    156     m_NewSockets.clear (); 
    157   } 
    158  
    159   virtual int 
    160   svc (void) 
    161   { 
    162     DEBUG_LOG ("Network Thread Starting"); 
    163  
    164     WorldDatabase.ThreadStart (); 
    165  
    166     ACE_ASSERT (m_Reactor); 
    167  
    168     SocketSet::iterator i, t; 
    169  
    170     while (!m_Reactor->reactor_event_loop_done ()) 
    171       { 
    172         // dont be too smart to move this outside the loop  
    173         // the run_reactor_event_loop will modify interval 
    174         ACE_Time_Value interval (0, 10000); 
    175  
    176         if (m_Reactor->run_reactor_event_loop (interval) == -1) 
    177           break; 
    178  
    179         AddNewSockets (); 
    180  
    181         for (i = m_Sockets.begin (); i != m_Sockets.end ();) 
    182           { 
    183             if ((*i)->Update () == -1) 
    184               { 
    185                 t = i; 
    186                 i++; 
    187                 (*t)->CloseSocket (); 
    188                 (*t)->RemoveReference (); 
    189                 --m_Connections; 
    190                 m_Sockets.erase (t); 
    191               } 
    192             else 
    193               i++; 
    194           } 
    195       } 
    196  
    197     WorldDatabase.ThreadEnd (); 
    198  
    199     DEBUG_LOG ("Network Thread Exitting"); 
    200  
    201     return 0; 
    202   } 
     132 
     133        void AddNewSockets () 
     134        { 
     135                ACE_GUARD (ACE_Thread_Mutex, Guard, m_NewSockets_Lock); 
     136 
     137                if (m_NewSockets.empty ()) 
     138                        return; 
     139 
     140                for (SocketSet::iterator i = m_NewSockets.begin (); i != m_NewSockets.end (); ++i) 
     141                { 
     142                        WorldSocket* sock = (*i); 
     143 
     144                        if (sock->IsClosed ()) 
     145                        { 
     146                                sock->RemoveReference (); 
     147                                --m_Connections; 
     148                        } 
     149                        else 
     150                                m_Sockets.insert (sock); 
     151                } 
     152 
     153                m_NewSockets.clear (); 
     154        } 
     155 
     156        virtual int svc (void) 
     157        { 
     158                DEBUG_LOG ("Network Thread Starting"); 
     159 
     160                WorldDatabase.ThreadStart (); 
     161 
     162                ACE_ASSERT (m_Reactor); 
     163 
     164                SocketSet::iterator i, t; 
     165 
     166                while (!m_Reactor->reactor_event_loop_done ()) 
     167                { 
     168                        // dont be too smart to move this outside the loop  
     169                        // the run_reactor_event_loop will modify interval 
     170                        ACE_Time_Value interval (0, 10000); 
     171 
     172                        if (m_Reactor->run_reactor_event_loop (interval) == -1) 
     173                                break; 
     174 
     175                        AddNewSockets (); 
     176 
     177                        for (i = m_Sockets.begin (); i != m_Sockets.end ();) 
     178                        { 
     179                                if ((*i)->Update () == -1) 
     180                                { 
     181                                        t = i; 
     182                                        i++; 
     183                                        (*t)->CloseSocket (); 
     184                                        (*t)->RemoveReference (); 
     185                                        --m_Connections; 
     186                                        m_Sockets.erase (t); 
     187                                } 
     188                                else 
     189                                        i++; 
     190                        } 
     191                } 
     192 
     193                WorldDatabase.ThreadEnd (); 
     194 
     195                DEBUG_LOG ("Network Thread Exitting"); 
     196 
     197                return 0; 
     198        } 
    203199 
    204200private: 
    205   typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> AtomicInt; 
    206   typedef std::set<WorldSocket*> SocketSet; 
    207  
    208   ACE_Reactor* m_Reactor; 
    209   AtomicInt m_Connections; 
    210   int m_ThreadId; 
    211  
    212   SocketSet m_Sockets; 
    213  
    214   SocketSet m_NewSockets; 
    215   ACE_Thread_Mutex m_NewSockets_Lock; 
     201        typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> AtomicInt; 
     202        typedef std::set<WorldSocket*> SocketSet; 
     203 
     204        ACE_Reactor* m_Reactor; 
     205        AtomicInt m_Connections; 
     206        int m_ThreadId; 
     207 
     208        SocketSet m_Sockets; 
     209 
     210        SocketSet m_NewSockets; 
     211        ACE_Thread_Mutex m_NewSockets_Lock; 
    216212}; 
    217213 
     
    228224WorldSocketMgr::~WorldSocketMgr () 
    229225{ 
    230   if (m_NetThreads) 
    231     delete [] m_NetThreads; 
    232    
    233   if(m_Acceptor) 
    234     delete m_Acceptor; 
    235 } 
    236  
    237 int 
    238 WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) 
    239 { 
    240   m_UseNoDelay = sConfig.GetBoolDefault ("Network.TcpNodelay", true); 
    241  
    242   int num_threads = sConfig.GetIntDefault ("Network.Threads", 1); 
    243  
    244   if (num_threads <= 0) 
    245     { 
    246       sLog.outError ("Network.Threads is wrong in your config file"); 
    247       return -1; 
    248     } 
    249  
    250   m_NetThreadsCount = static_cast<size_t> (num_threads + 1); 
    251  
    252   m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; 
    253  
    254   sLog.outBasic ("Max alowed socket connections %d",ACE::max_handles ()); 
    255  
    256   m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); // -1 means use default 
    257  
    258   m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536); 
    259  
    260   if ( m_SockOutUBuff <= 0 ) 
    261     { 
    262       sLog.outError ("Network.OutUBuff is wrong in your config file"); 
    263       return -1; 
    264     } 
    265  
    266   WorldSocket::Acceptor *acc = new WorldSocket::Acceptor; 
    267   m_Acceptor = acc; 
    268  
    269   ACE_INET_Addr listen_addr (port, address); 
    270  
    271   if (acc->open (listen_addr, m_NetThreads[0].GetReactor (), ACE_NONBLOCK) == -1) 
    272     { 
    273       sLog.outError ("Failed to open acceptor ,check if the port is free"); 
    274       return -1; 
    275     } 
    276  
    277   for (size_t i = 0; i < m_NetThreadsCount; ++i) 
    278     m_NetThreads[i].Start (); 
    279  
    280   return 0; 
    281 } 
    282  
    283 int 
    284 WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address) 
    285 { 
    286   if (!sLog.IsOutDebug ()) 
    287     ACE_Log_Msg::instance ()->priority_mask (LM_ERROR, ACE_Log_Msg::PROCESS); 
    288  
    289   if (this->StartReactiveIO (port, address) == -1) 
    290     return -1; 
    291  
    292   return 0; 
    293 } 
    294  
    295 void 
    296 WorldSocketMgr::StopNetwork () 
    297 { 
    298   if (m_Acceptor) 
    299     { 
    300       WorldSocket::Acceptor* acc = dynamic_cast<WorldSocket::Acceptor*> (m_Acceptor); 
    301  
    302       if (acc) 
    303         acc->close (); 
    304     } 
    305  
    306   if (m_NetThreadsCount != 0) 
    307     { 
    308       for (size_t i = 0; i < m_NetThreadsCount; ++i) 
    309         m_NetThreads[i].Stop (); 
    310     } 
    311    
    312   this->Wait (); 
    313 } 
    314  
    315 void  
    316 WorldSocketMgr::Wait () 
    317 { 
    318   if (m_NetThreadsCount != 0) 
    319     { 
    320       for (size_t i = 0; i < m_NetThreadsCount; ++i) 
    321         m_NetThreads[i].Wait (); 
    322     } 
    323 } 
    324  
    325 int 
    326 WorldSocketMgr::OnSocketOpen (WorldSocket* sock) 
    327 { 
    328   // set some options here 
    329   if (m_SockOutKBuff >= 0) 
    330     if (sock->peer ().set_option (SOL_SOCKET, 
    331                                   SO_SNDBUF, 
    332                                   (void*) & m_SockOutKBuff, 
    333                                   sizeof (int)) == -1 && errno != ENOTSUP) 
    334       { 
    335         sLog.outError ("WorldSocketMgr::OnSocketOpen set_option SO_SNDBUF"); 
    336         return -1; 
    337       } 
    338  
    339   static const int ndoption = 1; 
    340  
    341   // Set TCP_NODELAY. 
    342   if (m_UseNoDelay) 
    343     if (sock->peer ().set_option (ACE_IPPROTO_TCP, 
    344                                   TCP_NODELAY, 
    345                                   (void*) & ndoption, 
    346                                   sizeof (int)) == -1) 
    347       { 
    348         sLog.outError ("WorldSocketMgr::OnSocketOpen: peer ().set_option TCP_NODELAY errno = %s", ACE_OS::strerror (errno)); 
    349         return -1; 
    350       } 
    351    
    352   sock->m_OutBufferSize = static_cast<size_t> (m_SockOutUBuff); 
    353  
    354   // we skip the Acceptor Thread 
    355   size_t min = 1; 
    356  
    357   ACE_ASSERT (m_NetThreadsCount >= 1); 
    358  
    359   for (size_t i = 1; i < m_NetThreadsCount; ++i) 
    360     if (m_NetThreads[i].Connections () < m_NetThreads[min].Connections ()) 
    361       min = i; 
    362  
    363   return m_NetThreads[min].AddSocket (sock); 
    364  
    365 } 
    366  
    367 WorldSocketMgr* 
    368 WorldSocketMgr::Instance () 
    369 { 
    370   return ACE_Singleton<WorldSocketMgr,ACE_Thread_Mutex>::instance(); 
    371 } 
     226        if (m_NetThreads) 
     227                delete [] m_NetThreads; 
     228 
     229        if(m_Acceptor) 
     230                delete m_Acceptor; 
     231} 
     232 
     233int WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) 
     234{ 
     235        m_UseNoDelay = sConfig.GetBoolDefault ("Network.TcpNodelay", true); 
     236 
     237        int num_threads = sConfig.GetIntDefault ("Network.Threads", 1); 
     238 
     239        if (num_threads <= 0) 
     240        { 
     241                sLog.outError ("Network.Threads is wrong in your config file"); 
     242                return -1; 
     243        } 
     244 
     245        m_NetThreadsCount = static_cast<size_t> (num_threads + 1); 
     246 
     247        m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; 
     248 
     249        sLog.outBasic ("Max alowed socket connections %d",ACE::max_handles ()); 
     250 
     251        m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); // -1 means use default 
     252 
     253        m_SockOutUBuff = sConfig.GetIntDefault ("Network.OutUBuff", 65536); 
     254 
     255        if ( m_SockOutUBuff <= 0 ) 
     256        { 
     257                sLog.outError ("Network.OutUBuff is wrong in your config file"); 
     258                return -1; 
     259        } 
     260 
     261        WorldSocket::Acceptor *acc = new WorldSocket::Acceptor; 
     262        m_Acceptor = acc; 
     263 
     264        ACE_INET_Addr listen_addr (port, address); 
     265 
     266        if (acc->open (listen_addr, m_NetThreads[0].GetReactor (), ACE_NONBLOCK) == -1) 
     267        { 
     268                sLog.outError ("Failed to open acceptor ,check if the port is free"); 
     269                return -1; 
     270        } 
     271 
     272        for (size_t i = 0; i < m_NetThreadsCount; ++i) 
     273                m_NetThreads[i].Start (); 
     274 
     275        return 0; 
     276} 
     277 
     278int WorldSocketMgr::StartNetwork (ACE_UINT16 port, const char* address) 
     279{ 
     280        if (!sLog.IsOutDebug ()) 
     281                ACE_Log_Msg::instance ()->priority_mask (LM_ERROR, ACE_Log_Msg::PROCESS); 
     282 
     283        if (this->StartReactiveIO (port, address) == -1) 
     284                return -1; 
     285 
     286        return 0; 
     287} 
     288 
     289void WorldSocketMgr::StopNetwork () 
     290{ 
     291        if (m_Acceptor) 
     292        { 
     293                WorldSocket::Acceptor* acc = dynamic_cast<WorldSocket::Acceptor*> (m_Acceptor); 
     294 
     295                if (acc) 
     296                        acc->close (); 
     297        } 
     298 
     299        if (m_NetThreadsCount != 0) 
     300        { 
     301                for (size_t i = 0; i < m_NetThreadsCount; ++i) 
     302                        m_NetThreads[i].Stop (); 
     303        } 
     304 
     305        this->Wait (); 
     306} 
     307 
     308void WorldSocketMgr::Wait () 
     309{ 
     310        if (m_NetThreadsCount != 0) 
     311        { 
     312                for (size_t i = 0; i < m_NetThreadsCount; ++i) 
     313                        m_NetThreads[i].Wait (); 
     314        } 
     315} 
     316 
     317int WorldSocketMgr::OnSocketOpen (WorldSocket* sock) 
     318{ 
     319        // set some options here 
     320        if (m_SockOutKBuff >= 0) 
     321                if (sock->peer ().set_option (SOL_SOCKET, 
     322                        SO_SNDBUF, 
     323                        (void*) & m_SockOutKBuff, 
     324                        sizeof (int)) == -1 && errno != ENOTSUP) 
     325                { 
     326                        sLog.outError ("WorldSocketMgr::OnSocketOpen set_option SO_SNDBUF"); 
     327                        return -1; 
     328                } 
     329 
     330                static const int ndoption = 1; 
     331 
     332                // Set TCP_NODELAY. 
     333                if (m_UseNoDelay) 
     334                        if (sock->peer ().set_option (ACE_IPPROTO_TCP, 
     335                                TCP_NODELAY, 
     336                                (void*) & ndoption, 
     337                                sizeof (int)) == -1) 
     338                        { 
     339                                sLog.outError ("WorldSocketMgr::OnSocketOpen: peer ().set_option TCP_NODELAY errno = %s", ACE_OS::strerror (errno)); 
     340                                return -1; 
     341                        } 
     342 
     343                        sock->m_OutBufferSize = static_cast<size_t> (m_SockOutUBuff); 
     344 
     345                        // we skip the Acceptor Thread 
     346                        size_t min = 1; 
     347 
     348                        ACE_ASSERT (m_NetThreadsCount >= 1); 
     349 
     350                        for (size_t i = 1; i < m_NetThreadsCount; ++i) 
     351                                if (m_NetThreads[i].Connections () < m_NetThreads[min].Connections ()) 
     352                                        min = i; 
     353 
     354                        return m_NetThreads[min].AddSocket (sock); 
     355} 
     356 
     357WorldSocketMgr* WorldSocketMgr::Instance () 
     358{ 
     359        return ACE_Singleton<WorldSocketMgr,ACE_Thread_Mutex>::instance(); 
     360}