Changeset 6404

Show
Ignore:
Timestamp:
07/03/08 07:19:15 (3 months ago)
Author:
eugene
Message:

Made server-side users be collected into a separate map and processed all at once when contact list is received.

Location:
trunk/licq
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • trunk/licq/include/licq_icqd.h

    r6402 r6404  
    1111#include <map> 
    1212#include <string> 
     13 
     14#include <boost/shared_array.hpp> 
    1315 
    1416#include "licq_events.h" 
     
    140142 
    141143typedef std::list<CConversation *> ConversationList; 
     144 
     145/** 
     146 * Internal template class for storing and processing received contact list. 
     147 */ 
     148class CUserProperties 
     149{ 
     150public: 
     151  CUserProperties(); 
     152 
     153private: 
     154  boost::shared_array<char> newAlias; 
     155  boost::shared_array<char> newCellular; 
     156 
     157  unsigned short normalSid; 
     158  unsigned short groupId; 
     159 
     160  unsigned short visibleSid; 
     161  unsigned short invisibleSid; 
     162  bool inIgnoreList; 
     163 
     164  bool awaitingAuth; 
     165 
     166  TLVList tlvs; 
     167 
     168friend class CICQDaemon; 
     169}; 
     170 
     171typedef std::map<std::string, CUserProperties*> ContactUserList; 
     172typedef ContactUserList::iterator ContactUserListIter; 
    142173 
    143174//=====CICQDaemon=============================================================== 
     
    745776  static pthread_cond_t  cond_reverseconnect_done; 
    746777 
     778  ContactUserList receivedUserList; 
     779 
    747780  ConversationList m_lConversations; 
    748781  pthread_mutex_t mutex_conversations; 
     
    830863  void ProcessListFam(CBuffer &, unsigned short); 
    831864  void ProcessAuthFam(CBuffer &, unsigned short); 
     865 
     866  void ProcessUserList(); 
    832867 
    833868  void ProcessSystemMessage(CBuffer &packet, unsigned long checkUin, unsigned short newCommand, time_t timeSent); 
  • trunk/licq/src/icqd-srv.cpp

    r6402 r6404  
    41394139      static unsigned short nCount = 0; 
    41404140      static bool sCheckExport = false; 
    4141       unsigned short nPacketCount; 
    4142       unsigned long nTime; 
    4143  
    4144       if (nFlags & 0x0001) 
    4145       { 
    4146         if (!hasServerEvent(nSubSequence)) 
    4147           gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 
    4148         else 
    4149           gLog.Info(tr("%sReceived contact list.\n"), L_SRVxSTR); 
    4150       } 
    4151       else 
    4152       { 
    4153         // This is the last packet so mark it as done 
    4154         ICQEvent *e = DoneServerEvent(nSubSequence, EVENT_SUCCESS); 
    4155  
    4156         if (e == NULL) 
    4157         { 
    4158           // Try acking it, even if we didn't expect it 
    4159           //gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 
    4160           gLog.Info(tr("%sActivate server contact list.\n"), L_SRVxSTR); 
    4161           CSrvPacketTcp *p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxACK); 
    4162           SendEvent_Server(p); 
    4163           //This packet had the user list in it, but we didn't ask for it. 
    4164           //Nonetheless, it appears we won't get a second chance for this packet, so process it 
    4165           //break; 
    4166         } 
    4167  
    4168         /* This isn't used anymore. At least with SSI Version 0. 
    4169         if (e->SNAC() == MAKESNAC(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_REQUESTxRIGHTS) || 
    4170             e->SNAC() == MAKESNAC(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_REQUESTxROST)) 
    4171         { 
    4172           packet.UnpackUnsignedLong(); 
    4173           packet.UnpackUnsignedLong(); 
    4174         } 
    4175         */ 
    4176  
    4177         gLog.Info(tr("%sReceived end of contact list.\n"), L_SRVxSTR); 
    4178       } 
    41794141 
    41804142      m_bOnlineNotifies = true; 
    41814143 
    41824144      packet.UnpackChar();  // SSI Version 
    4183       nPacketCount = packet.UnpackUnsignedShortBE(); 
     4145      unsigned short nPacketCount = packet.UnpackUnsignedShortBE(); 
    41844146      nCount += nPacketCount; 
    41854147 
    4186       for (unsigned short i = 0; i < nPacketCount; i++) 
    4187       { 
    4188         char *szId; 
    4189         unsigned short nTag, nID, nType, nByteLen; 
    4190  
     4148      while (nPacketCount-- != 0) 
     4149      { 
    41914150        // Can't use UnpackUserString because this may be a group name 
    4192         szId = packet.UnpackStringBE(); 
    4193         nTag = packet.UnpackUnsignedShortBE(); 
    4194         nID = packet.UnpackUnsignedShortBE(); 
    4195         nType = packet.UnpackUnsignedShortBE(); 
    4196         nByteLen = packet.UnpackUnsignedShortBE(); 
    4197  
    4198         char *szUnicodeName = gTranslator.FromUnicode(szId); 
     4151        char* szId = packet.UnpackStringBE(); 
     4152        unsigned short nTag = packet.UnpackUnsignedShortBE(); 
     4153        unsigned short nID = packet.UnpackUnsignedShortBE(); 
     4154        unsigned short nType = packet.UnpackUnsignedShortBE(); 
     4155 
     4156        unsigned short nByteLen = packet.UnpackUnsignedShortBE(); 
    41994157 
    42004158        if (nByteLen) 
     
    42164174          case ICQ_ROSTxIGNORE: 
    42174175          { 
    4218             if (!UseServerContactList()) break;  
    4219              
    4220             char *szNewName = packet.UnpackStringTLV(0x0131); 
    4221             char *szSMSNumber = packet.UnpackStringTLV(0x013A); 
    4222             bool bAwaitingAuth = packet.hasTLV(0x0066); 
    4223  
    4224             bool isOnList = true; 
    4225             if (szId && !gUserManager.IsOnList(szId, LICQ_PPID)) 
     4176            if (!UseServerContactList()) 
     4177              break; 
     4178 
     4179            std::pair<ContactUserListIter, bool> ret = 
     4180              receivedUserList.insert(make_pair(szId, (CUserProperties*)NULL)); 
     4181 
     4182            ContactUserListIter iter = ret.first; 
     4183            if (ret.second) // we inserted a new NULL pair 
     4184              iter->second = new CUserProperties(); 
     4185 
     4186            CUserProperties* data = iter->second; 
     4187 
     4188#define COPYTLV(type, var) \ 
     4189            if (packet.hasTLV(type)) \ 
     4190              data->var.reset(packet.UnpackStringTLV(type)) 
     4191 
     4192            COPYTLV(0x0131, newAlias); 
     4193            COPYTLV(0x013A, newCellular); 
     4194#undef COPYTLV 
     4195            if (packet.hasTLV(0x0066)) 
     4196              data->awaitingAuth = true; 
     4197 
     4198            if (nTag != 0) 
     4199              data->groupId = nTag; 
     4200 
     4201            if (nType == ICQ_ROSTxIGNORE) 
     4202              data->inIgnoreList = true; 
     4203 
     4204            if (nID != 0) 
    42264205            { 
    4227               isOnList = false; 
    4228               AddUserToList(szId, LICQ_PPID, false); // Don't notify server 
    4229             } 
    4230  
    4231             ICQUser *u = gUserManager.FetchUser(szId, LICQ_PPID, LOCK_W); 
    4232             if (u) 
    4233             { 
    4234               // For now, just save all the TLVs. We should change this to have awaiting auth check 
    4235               // for the 0x0066 TLV, SMS number if it has the 0x013A TLV, etc 
    4236               TLVList tlvList = packet.getTLVList(); 
    4237               TLVListIter iter; 
    4238               for (iter = tlvList.begin(); iter != tlvList.end(); ++iter) 
     4206              if (nType == ICQ_ROSTxVISIBLE) 
    42394207              { 
    4240                 TLVPtr tlv = iter->second; 
    4241                 u->AddTLV(tlv); 
     4208                data->visibleSid = nID; 
    42424209              } 
    4243  
    4244               u->SetGSID(nTag); 
    4245  
    4246               if (szNewName) 
    4247                 u->SetAlias(szNewName); 
    4248  
    4249               if (szSMSNumber) 
     4210              else if (nType == ICQ_ROSTxINVISIBLE) 
    42504211              { 
    4251                 char *szUnicodeSMS = gTranslator.FromUnicode(szSMSNumber); 
    4252                 if (szUnicodeSMS) 
    4253                 { 
    4254                   u->SetCellularNumber(szUnicodeSMS); 
    4255                   delete [] szUnicodeSMS; 
    4256                 } 
    4257               } 
    4258  
    4259               u->SetAwaitingAuth(bAwaitingAuth); 
    4260  
    4261               if (nType == ICQ_ROSTxINVISIBLE) 
    4262               { 
    4263                 u->SetInvisibleList(true); 
    4264                 u->SetInvisibleSID(nID); 
    4265               } 
    4266               else if (nType == ICQ_ROSTxVISIBLE) 
    4267               { 
    4268                 u->SetVisibleList(true); 
    4269                 u->SetVisibleSID(nID); 
     4212                data->invisibleSid = nID; 
    42704213              } 
    42714214              else 
    42724215              { 
    4273                 u->SetSID(nID); 
    4274  
    4275                 if (nType == ICQ_ROSTxNORMAL) 
    4276                 { 
    4277                   // Save the group that they are in 
    4278                   u->AddToGroup(GROUPS_USER, gUserManager.GetGroupFromID(nTag)); 
    4279                 } 
     4216                data->normalSid = nID; 
    42804217              } 
    4281  
    4282               u->SetIgnoreList(nType == ICQ_ROSTxIGNORE); 
    4283  
    4284               if (!isOnList) 
    4285               { 
    4286                 // They aren't a new user if we added them to a server list 
    4287                 u->SetNewUser(false); 
    4288               } 
    4289  
    4290               // Save GSID, SID and group memberships 
    4291               u->SaveLicqInfo(); 
    4292  
    4293               PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_GENERAL, 
    4294                 u->IdString(), u->PPID())); 
    4295               gUserManager.DropUser(u); 
    42964218            } 
    4297  
    4298             if (!isOnList) 
    4299             { 
    4300               gLog.Info(tr("%sAdded %s (%s) to list from server.\n"), L_SRVxSTR, 
    4301                 (szNewName ? szNewName : szId), szId); 
    4302             } 
    4303  
    4304             if (szNewName) 
    4305               delete [] szNewName; 
    4306             if (szSMSNumber) 
    4307               delete [] szSMSNumber; 
    4308  
    43094219            break; 
    43104220          } 
     
    43184228              // Rename the group if we have it already or else add it 
    43194229              unsigned short nGroup = gUserManager.GetGroupFromID(nTag); 
     4230              char* szUnicodeName = gTranslator.FromUnicode(szId); 
     4231 
    43204232              if (nGroup == 0) 
    43214233              { 
     
    43284240              } 
    43294241               
     4242              if (szUnicodeName) 
     4243                delete[] szUnicodeName; 
     4244 
    43304245              // This is bad, i don't think we want to call this at all.. 
    43314246              // it will add users to different groups that they werent even 
     
    43594274        }  // switch (nType) 
    43604275 
    4361         if (szUnicodeName) 
    4362           delete [] szUnicodeName; 
    4363  
    43644276        if (szId) 
    43654277          delete[] szId; 
     
    43744286 
    43754287      // Update local info about contact list 
    4376       nTime = packet.UnpackUnsignedLongBE(); 
     4288      unsigned long nTime = packet.UnpackUnsignedLongBE(); 
    43774289      ICQOwner* o = gUserManager.FetchOwner(LICQ_PPID, LOCK_W); 
    43784290      o->SetSSTime(nTime); 
     
    43804292      gUserManager.DropOwner(o); 
    43814293 
    4382       gLog.Info(tr("%sActivate server contact list.\n"), L_SRVxSTR); 
    4383       CSrvPacketTcp *p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxACK); 
    4384       SendEvent_Server(p); 
    4385  
    4386        
     4294      if (nFlags & 0x0001) 
     4295      { 
     4296        if (!hasServerEvent(nSubSequence)) 
     4297          gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 
     4298        else 
     4299          gLog.Info(tr("%sReceived contact list.\n"), L_SRVxSTR); 
     4300      } 
     4301      else 
     4302      { 
     4303        // This is the last packet so mark it as done 
     4304        DoneServerEvent(nSubSequence, EVENT_SUCCESS); 
     4305 
     4306        gLog.Info(tr("%sReceived end of contact list.\n"), L_SRVxSTR); 
     4307 
     4308        ProcessUserList(); 
     4309 
     4310        gLog.Info(tr("%sActivating server contact list.\n"), L_SRVxSTR); 
     4311        CSrvPacketTcp *p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxACK); 
     4312        SendEvent_Server(p); 
     4313      } 
     4314 
    43874315      break; 
    43884316    } // case rost reply 
     
    63946322} 
    63956323 
     6324void CICQDaemon::ProcessUserList() 
     6325{ 
     6326  if (receivedUserList.empty()) 
     6327    return; 
     6328 
     6329  ContactUserListIter iter; 
     6330 
     6331  for (iter = receivedUserList.begin(); iter != receivedUserList.end(); iter++) 
     6332  { 
     6333    const char* id = iter->first.c_str(); 
     6334    CUserProperties* data = iter->second; 
     6335 
     6336    if (id == NULL || id[0] == '\0') 
     6337    { 
     6338      gLog.Warn(tr("%sEmpty User ID was received in the contact list.\n"), 
     6339          L_SRVxSTR); 
     6340      continue; 
     6341    } 
     6342 
     6343    bool isOnList = gUserManager.IsOnList(id, LICQ_PPID); 
     6344 
     6345    if (!isOnList) 
     6346    { 
     6347      AddUserToList(id, LICQ_PPID, false, false); // Don't notify server 
     6348      gLog.Info(tr("%sAdded %s (%s) to list from server.\n"), 
     6349          L_SRVxSTR, (data->newAlias ? data->newAlias.get() : id), id); 
     6350    } 
     6351 
     6352    ICQUser* u = gUserManager.FetchUser(id, LICQ_PPID, LOCK_W); 
     6353    if (u == NULL) 
     6354      continue; 
     6355 
     6356    if (data->newAlias != NULL) 
     6357      u->SetAlias(data->newAlias.get()); 
     6358 
     6359    u->SetSID(data->normalSid); 
     6360    u->SetGSID(data->groupId); 
     6361    u->SetVisibleSID(data->visibleSid); 
     6362    u->SetVisibleList(data->visibleSid != 0); 
     6363    u->SetInvisibleSID(data->invisibleSid); 
     6364    u->SetInvisibleList(data->invisibleSid != 0); 
     6365    u->SetIgnoreList(data->inIgnoreList); 
     6366 
     6367    u->AddToGroup(GROUPS_USER, gUserManager.GetGroupFromID(data->groupId)); 
     6368 
     6369    u->SetAwaitingAuth(data->awaitingAuth); 
     6370 
     6371    if (!isOnList) 
     6372    { 
     6373      // They aren't a new user if we added them to a server list 
     6374      u->SetNewUser(false); 
     6375    } 
     6376 
     6377    if (data->newCellular != NULL) 
     6378    { 
     6379      char* tmp = gTranslator.FromUnicode(data->newCellular.get()); 
     6380      if (tmp != NULL) 
     6381      { 
     6382        u->SetCellularNumber(tmp); 
     6383        delete[] tmp; 
     6384      } 
     6385    } 
     6386 
     6387    // For now, just save all the TLVs. We should change this to have awaiting auth check 
     6388    // for the 0x0066 TLV, SMS number if it has the 0x013A TLV, etc 
     6389    TLVListIter tlvIter; 
     6390    for (tlvIter = data->tlvs.begin(); tlvIter != data->tlvs.end(); tlvIter++) 
     6391    { 
     6392      TLVPtr tlv = tlvIter->second; 
     6393      u->AddTLV(tlv); 
     6394    } 
     6395 
     6396    // Save GSID, SID and group memberships 
     6397    u->SaveLicqInfo(); 
     6398    gUserManager.DropUser(u); 
     6399 
     6400    PushPluginSignal(new CICQSignal(SIGNAL_UPDATExUSER, USER_GENERAL, id, LICQ_PPID)); 
     6401  } 
     6402 
     6403  receivedUserList.clear(); 
     6404} 
     6405 
    63966406//--------ProcessDataChannel--------------------------------------------------- 
    63976407 
  • trunk/licq/src/icqd.cpp

    r6402 r6404  
    167167 
    168168  fifo_fs = NULL; 
     169 
     170  receivedUserList.clear(); 
    169171 
    170172  // Begin parsing the config file 
     
    28272829  return (!*pcEnd); 
    28282830} 
     2831 
     2832CUserProperties::CUserProperties() 
     2833  : newAlias(NULL), 
     2834    newCellular(NULL), 
     2835    normalSid(0), 
     2836    groupId(0), 
     2837    visibleSid(0), 
     2838    invisibleSid(0), 
     2839    inIgnoreList(false), 
     2840    awaitingAuth(false) 
     2841{ 
     2842  tlvs.clear(); 
     2843}