Changeset 6165
- Timestamp:
- 04/20/08 22:10:30 (8 months ago)
- Location:
- trunk/licq
- Files:
-
- 7 modified
-
include/licq_buffer.h (modified) (5 diffs)
-
include/licq_packets.h (modified) (1 diff)
-
include/licq_user.h (modified) (2 diffs)
-
src/buffer.cpp (modified) (17 diffs)
-
src/icqd-srv.cpp (modified) (13 diffs)
-
src/icqpacket.cpp (modified) (14 diffs)
-
src/user.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/licq/include/licq_buffer.h
r4526 r6165 1 1 #ifndef LICQ_BUFFER_H 2 2 #define LICQ_BUFFER_H 3 4 #include <map> 5 #include <vector> 6 7 #include <boost/shared_array.hpp> 8 #include <boost/shared_ptr.hpp> 3 9 4 10 /*------------------------------------------------------------------------------ … … 27 33 extern void rev_e_long(unsigned long &); 28 34 29 //===== TLV Structs=============================================================30 struct SOscarTLV35 //=====COscarTLV================================================================ 36 class COscarTLV 31 37 { 32 unsigned short nType; 33 unsigned short nLen; 34 unsigned char *pData; 38 public: 39 COscarTLV(unsigned short type = 0, unsigned short length = 0, unsigned char *data = 0) : myType(type), myLen(length) 40 { 41 if (myLen > 0) 42 { 43 myData = boost::shared_array<unsigned char>(new unsigned char[myLen]); 44 memcpy(myData.get(), data, myLen); 45 } 46 } 47 48 COscarTLV(const COscarTLV &c) 49 { 50 myType = c.myType; 51 myLen = c.myLen; 52 myData = boost::shared_array<unsigned char>(new unsigned char[c.myLen]); 53 memcpy(myData.get(), c.myData.get(), c.myLen); 54 } 55 56 unsigned short getType() const { return myType; } 57 unsigned short getLength() const { return myLen; } 58 boost::shared_array<unsigned char> getData() const { return myData; } 59 60 void setType(unsigned short type) { myType = type; } 61 void setData(unsigned char *data, unsigned short length) 62 { 63 if (length > 0) 64 { 65 myLen = length; 66 myData = boost::shared_array<unsigned char>(new unsigned char[length]); 67 memcpy(myData.get(), data, length); 68 } 69 } 70 71 private: 72 unsigned short myType; 73 unsigned short myLen; 74 boost::shared_array<unsigned char> myData; 75 76 friend class CBuffer; 35 77 }; 36 78 37 struct SOscarTLV_Chain 38 { 39 SOscarTLV *pTLV; 40 SOscarTLV_Chain *pNext; 41 }; 79 typedef boost::shared_ptr<COscarTLV> TLVPtr; 80 typedef std::map<unsigned short, TLVPtr> TLVList; 81 typedef TLVList::iterator TLVListIter; 42 82 43 83 //=====CBuffer================================================================== … … 111 151 112 152 bool readTLV(int count = -1, int bytes = -1); // This should be called automatically if m_pTLV == 0 113 void cleanupTLV();114 153 115 154 void PackTLV(unsigned short, unsigned short, const char *); 116 155 void PackTLV(unsigned short, unsigned short, CBuffer *); 156 void PackTLV(const TLVPtr&); 117 157 118 158 unsigned short getTLVLen(unsigned short); … … 123 163 unsigned char UnpackCharTLV(unsigned short); 124 164 char *UnpackStringTLV(unsigned short); // Need to delete[] returned string 165 //std::string UnpackStringTLV(unsigned short); 125 166 CBuffer UnpackTLV(unsigned short); 167 168 TLVList getTLVList(); 169 TLVPtr getTLV(unsigned short _nType); 126 170 127 171 private: … … 134 178 *m_pDataPosRead; 135 179 unsigned long m_nDataSize; 136 SOscarTLV_Chain *m_pTLV;180 TLVList myTLVs; 137 181 138 SOscarTLV *getTLV(unsigned short _nType);139 182 void antiwarning() { NetworkIpToPacketIp(PacketIpToNetworkIp(127)); } 140 183 }; -
trunk/licq/include/licq_packets.h
r5972 r6165 309 309 }; 310 310 311 //-----ListRequestRights----------------------------------------------------- 312 class CPU_ListRequestRights : public CPU_CommonFamily 313 { 314 public: 315 CPU_ListRequestRights(); 316 }; 317 311 318 //-----ImICQ------------------------------------------------------------------ 312 319 class CPU_ImICQ : public CPU_CommonFamily -
trunk/licq/include/licq_user.h
r6047 r6165 780 780 char *PortStr(char *rbuf); 781 781 782 // User TLV List handling 783 void AddTLV(TLVPtr); 784 void RemoveTLV(unsigned long); 785 TLVList GetTLVList(); 786 782 787 // Don't call these: 783 788 int SocketDesc(unsigned char); … … 953 958 unsigned short m_nGSID; 954 959 960 // Extra TLVs attached to this user's SSI info 961 // We use a map to allow fast access to the TLV by type, even though the 962 // actual type is in SOscarTLV as well. Which should make it obvious 963 // that the TLV handling should be fixed in licq_buffer.h/buffer.cpp 964 TLVList myTLVs; 965 955 966 UserEventList m_vcMessages; 956 967 -
trunk/licq/src/buffer.cpp
r4951 r6165 174 174 { 175 175 m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL; 176 m_pTLV = NULL;177 176 m_nDataSize = 0; 178 177 } … … 181 180 CBuffer::CBuffer(unsigned long _nDataSize) 182 181 { 183 m_pTLV = NULL;184 182 m_nDataSize = _nDataSize; 185 183 if (_nDataSize) … … 204 202 m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart()); 205 203 m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart()); 206 // DAW FIXME207 m_pTLV = NULL;208 204 } 209 205 … … 214 210 { 215 211 m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL; 216 m_pTLV = NULL;217 212 m_nDataSize = 0; 218 213 } 219 214 else 220 215 { 221 m_pTLV = NULL;222 216 m_nDataSize = b->getDataMaxSize(); 223 217 m_pDataStart = new char[m_nDataSize]; … … 242 236 m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart()); 243 237 m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart()); 244 m _pTLV = NULL;238 myTLVs = b.myTLVs; 245 239 246 240 return (*this); … … 275 269 m_pDataStart = new char[m_nDataSize]; 276 270 m_pDataPosRead = m_pDataPosWrite = m_pDataStart; 277 m_pTLV = NULL;278 271 } 279 272 … … 462 455 { 463 456 if (m_pDataStart != NULL) delete[] m_pDataStart; 464 if (m_pTLV) cleanupTLV(); 465 m_pTLV = NULL; 457 myTLVs.clear(); 466 458 m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL; 467 459 m_nDataSize = 0; … … 499 491 { 500 492 if (m_pDataStart != NULL) delete[] m_pDataStart; 501 if (m_pTLV) cleanupTLV();502 493 } 503 494 … … 630 621 bool CBuffer::readTLV(int nCount, int nBytes) 631 622 { 632 if (m_pTLV || !nCount) return false; // already have one 623 if (!nCount) return false; 624 625 // Clear the list if we already have some TLVs 626 if (myTLVs.size() > 0) 627 myTLVs.clear(); 633 628 634 629 int num = 0; 635 630 int nCurBytes = 0; 636 631 632 // Keep reading until it is impossible for any TLV headers to be found 637 633 while(getDataPosRead() + 4 < (getDataStart() + getDataSize())) { 638 SOscarTLV_Chain *now = new SOscarTLV_Chain; 639 now->pTLV = new SOscarTLV; 640 641 *this >> now->pTLV->nType; 642 *this >> now->pTLV->nLen; 643 644 rev_e_short(now->pTLV->nType); 645 rev_e_short(now->pTLV->nLen); 646 647 nCurBytes += 4 + now->pTLV->nLen; 648 649 if(getDataPosRead() + now->pTLV->nLen > (getDataStart() + getDataSize()) || 650 now->pTLV->nLen < 1) { 651 now->pTLV->nLen = 0; 652 now->pTLV->pData = 0; 634 TLVPtr tlv(new COscarTLV); 635 636 *this >> tlv->myType; 637 *this >> tlv->myLen; 638 639 rev_e_short(tlv->myType); 640 rev_e_short(tlv->myLen); 641 642 nCurBytes += 4 + tlv->myLen; 643 644 if(getDataPosRead() + tlv->myLen > (getDataStart() + getDataSize()) || 645 tlv->myLen < 1) { 646 tlv->myLen = 0; 653 647 } 654 648 else { 655 now->pTLV->pData = new unsigned char[now->pTLV->nLen];656 memcpy( now->pTLV->pData, m_pDataPosRead, now->pTLV->nLen);657 m_pDataPosRead += now->pTLV->nLen;649 tlv->myData.reset(new unsigned char[tlv->myLen]); 650 memcpy(tlv->myData.get(), m_pDataPosRead, tlv->myLen); 651 m_pDataPosRead += tlv->myLen; 658 652 } 659 653 660 now->pNext = m_pTLV;661 m _pTLV = now;654 // Save it in the map 655 myTLVs[tlv->myType] = tlv; 662 656 663 657 ++num; 664 if (nCount > 0 && num == nCount) 665 return true; 666 667 if (nBytes > 0 && nCurBytes == nBytes) 658 if ((nCount > 0 && num == nCount) || 659 (nBytes > 0 && nCurBytes == nBytes) ) 668 660 return true; 669 661 … … 686 678 } 687 679 688 void CBuffer::cleanupTLV()689 {690 if (!m_pTLV) return;691 692 SOscarTLV_Chain *now = m_pTLV;693 694 while (now) {695 SOscarTLV_Chain *tmp;696 697 if (now->pTLV)698 {699 if (now->pTLV->pData)700 delete [] now->pTLV->pData;701 702 delete now->pTLV;703 }704 705 tmp = now->pNext;706 delete now;707 now = tmp;708 }709 710 m_pTLV = NULL;711 }712 713 680 void CBuffer::PackTLV(unsigned short nType, unsigned short nSize, 714 681 const char *data) … … 725 692 PackUnsignedShortBE(nSize); 726 693 Pack(b); 694 } 695 696 void CBuffer::PackTLV(const TLVPtr& tlv) 697 { 698 PackUnsignedShortBE(tlv->myType); 699 PackUnsignedShortBE(tlv->myLen); 700 Pack(reinterpret_cast<const char *>(tlv->myData.get()), tlv->myLen); 727 701 } 728 702 … … 741 715 unsigned short CBuffer::getTLVLen(unsigned short nType) 742 716 { 743 SOscarTLV *pTLV = getTLV(nType);744 if (pTLV)745 return pTLV->nLen;746 747 return 0;717 unsigned short len = 0; 718 TLVListIter iter = myTLVs.find(nType); 719 if (iter != myTLVs.end()) 720 len = iter->second->myLen; 721 return len; 748 722 } 749 723 750 724 bool CBuffer::hasTLV(unsigned short nType) 751 725 { 752 bool bRet = false; 753 SOscarTLV *pTLV = getTLV(nType); 754 if (pTLV) 755 bRet = true; 756 757 return bRet; 726 TLVListIter iter = myTLVs.find(nType); 727 bool found = (iter != myTLVs.end()); 728 return found; 758 729 } 759 730 … … 762 733 unsigned long nRet = 0; 763 734 764 SOscarTLV *pTLV = getTLV(nType); 765 if (pTLV && pTLV->nLen > 3) 766 { 767 nRet |= (*((pTLV->pData)+0) << 24); 768 nRet |= (*((pTLV->pData)+1) << 16); 769 nRet |= (*((pTLV->pData)+2) << 8); 770 nRet |= (*((pTLV->pData)+3)); 735 try 736 { 737 TLVPtr tlv = getTLV(nType); 738 if (tlv->myLen > 3) 739 { 740 nRet |= (*((tlv->myData.get())+0) << 24); 741 nRet |= (*((tlv->myData.get())+1) << 16); 742 nRet |= (*((tlv->myData.get())+2) << 8); 743 nRet |= (*((tlv->myData.get())+3)); 744 } 745 } 746 catch (...) 747 { 748 // TODO Throw an exception 771 749 } 772 750 … … 778 756 unsigned short nRet = 0; 779 757 780 SOscarTLV *pTLV = getTLV(nType); 781 if (pTLV && pTLV->nLen > 1) 782 { 783 nRet |= (*((pTLV->pData)+0) << 8); 784 nRet |= (*((pTLV->pData)+1)); 758 try 759 { 760 TLVPtr tlv = getTLV(nType); 761 if (tlv->myLen > 1) 762 { 763 nRet |= (*((tlv->myData.get())+0) << 8); 764 nRet |= (*((tlv->myData.get())+1)); 765 } 766 } 767 catch (...) 768 { 769 // TODO Throw an exception 785 770 } 786 771 … … 792 777 unsigned char nRet = 0; 793 778 794 SOscarTLV *pTLV = getTLV(nType); 795 if (pTLV && pTLV->nLen > 0) 796 nRet = *(pTLV->pData); 779 try 780 { 781 TLVPtr tlv = getTLV(nType); 782 if (tlv->myLen > 0) 783 nRet = *(tlv->myData.get()); 784 } 785 catch (...) 786 { 787 // TODO Throw an exception 788 } 797 789 798 790 return nRet; … … 804 796 char *str = 0; 805 797 806 SOscarTLV *pTLV = getTLV(nType); 807 if (pTLV) 808 { 809 str = new char[pTLV->nLen+1]; 810 if (!str) return 0; 811 812 memcpy(str, pTLV->pData, pTLV->nLen); 813 *(str+pTLV->nLen) = '\0'; 798 try 799 { 800 TLVPtr tlv = getTLV(nType); 801 str = new char[tlv->myLen+1]; 802 memcpy(str, tlv->myData.get(), tlv->myLen); 803 *(str+tlv->myLen) = '\0'; 804 } 805 catch (...) 806 { 807 if (str) 808 { 809 delete [] str; 810 str = 0; 811 } 814 812 } 815 813 … … 817 815 } 818 816 817 #if 0 818 //TODO Add this function and use it everywhere so we don't have to 819 // constanly remember to call delete[] 820 std::string CBuffer::UnpackStringTLV(unsigned short nType) 821 { 822 std::string str; 823 824 try 825 { 826 TLVPtr tlv = getTLV(nType); 827 str.assign(tlv->myData.get(), tlv->myLen); 828 } 829 catch (...) 830 { 831 // TODO Throw an exception 832 } 833 834 return str; 835 } 836 #endif 837 819 838 CBuffer CBuffer::UnpackTLV(unsigned short nType) 820 839 { 821 SOscarTLV *pTLV = getTLV(nType);822 if (pTLV)823 {824 CBuffer cbuf( pTLV->nLen);825 cbuf.Pack( (const char*)pTLV->pData, pTLV->nLen);840 try 841 { 842 TLVPtr tlv = getTLV(nType); 843 CBuffer cbuf(tlv->myLen); 844 cbuf.Pack(reinterpret_cast<const char *>(tlv->myData.get()), tlv->myLen); 826 845 cbuf.Reset(); 827 846 828 847 return cbuf; 829 848 } 830 else 849 catch (...) 850 { 831 851 return CBuffer(0); 832 } 833 834 SOscarTLV *CBuffer::getTLV(unsigned short nType) 835 { 836 if (!m_pTLV) return 0; 837 838 SOscarTLV_Chain *now; 839 840 for (now = m_pTLV; now; now = now->pNext) 841 if (now && now->pTLV && now->pTLV->nType == nType) 842 return now->pTLV; 843 844 return 0; 852 } 853 } 854 855 TLVPtr CBuffer::getTLV(unsigned short nType) 856 { 857 if (myTLVs.size() == 0) 858 throw std::exception(); 859 860 TLVListIter iter = myTLVs.find(nType); 861 if (iter == myTLVs.end()) 862 throw std::exception(); 863 864 return iter->second; 865 } 866 867 TLVList CBuffer::getTLVList() 868 { 869 return myTLVs; 845 870 } 846 871 -
trunk/licq/src/icqd-srv.cpp
r6137 r6165 2216 2216 void CICQDaemon::ProcessServiceFam(CBuffer &packet, unsigned short nSubtype) 2217 2217 { 2218 packet.UnpackUnsignedShortBE(); // flags2218 unsigned short snacFlags = packet.UnpackUnsignedShortBE(); // flags 2219 2219 packet.UnpackUnsignedLongBE(); // sequence 2220 2221 // TODO The TLVs should be processed first, in a common area, instead of requiring 2222 // each case to do the same thing. However, the individual case's may depend on the tlv 2223 // coming to them, so leave this commented out for now and do some testing 2224 /* 2225 if (snacFlags & 0x8000) 2226 { 2227 unsigned short bytes = packet.UnpackUnsignedShortBE(); 2228 unsigned short tlvCount = packet.UnpackUnsignedShortBE(); 2229 if (!packet.readTLV(tlvCount, bytes)) 2230 { 2231 gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 2232 return; 2233 } 2234 } 2235 */ 2220 2236 2221 2237 switch (nSubtype) … … 2256 2272 2257 2273 gLog.Info(tr("%sRequesting list rights.\n"), L_SRVxSTR); 2258 p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_REQUESTxRIGHTS); 2274 p = new CPU_ListRequestRights(); 2275 SendExpectEvent_Server(0, p, NULL); 2276 2277 gLog.Info(tr("%sRequesting roster rights.\n"), L_SRVxSTR); 2278 p = new CPU_RequestList(); 2259 2279 SendEvent_Server(p); 2260 2261 gLog.Info(tr("%sRequesting list.\n"), L_SRVxSTR);2262 p = new CPU_RequestList();2263 SendExpectEvent_Server(0, p, NULL);2264 2280 2265 2281 gLog.Info(tr("%sRequesting location rights.\n"), L_SRVxSTR); … … 2304 2320 case ICQ_SNACxRCV_NAMExINFO: 2305 2321 { 2306 unsigned short nUserClass, nLevel; 2322 if (snacFlags & 0x8000) 2323 { 2324 unsigned short bytes = packet.UnpackUnsignedShortBE(); 2325 if (!packet.readTLV(-1, bytes)) 2326 { 2327 gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 2328 return; 2329 } 2330 } 2331 2332 unsigned short evil, tlvBlocks; 2307 2333 unsigned long nUin, realIP; 2308 2334 time_t nOnlineSince = 0; … … 2311 2337 2312 2338 nUin = packet.UnpackUinString(); 2313 nLevel = packet.UnpackUnsignedShortBE(); 2314 nUserClass = packet.UnpackUnsignedShortBE(); 2315 2316 gLog.Info("%sUIN: %lu level: %04hx Class: %04hx\n", L_SRVxSTR, 2317 nUin, nLevel, nUserClass ); 2318 2319 if (!packet.readTLV()) { 2339 evil = packet.UnpackUnsignedShortBE(); 2340 tlvBlocks = packet.UnpackUnsignedShortBE(); 2341 2342 gLog.Info("%sUIN: %lu Evil: %04hx\n", L_SRVxSTR, nUin, evil); 2343 2344 if (!packet.readTLV(tlvBlocks)) { 2320 2345 char *buf; 2321 2346 gLog.Unknown(tr("%sUnknown server response:\n%s\n"), L_UNKNOWNxSTR, … … 3959 3984 unsigned long nSubSequence = packet.UnpackUnsignedLongBE(); 3960 3985 3961 // First 8 bytes - unknown 3962 if (nSubtype != ICQ_SNACxLIST_ROSTxREPLY) 3963 { 3964 packet.UnpackUnsignedLong(); 3965 packet.UnpackUnsignedLong(); 3966 } 3986 if (nFlags & 0x8000) 3987 { 3988 unsigned short bytes = packet.UnpackUnsignedShortBE(); 3989 if (!packet.readTLV(-1, bytes)) 3990 { 3991 gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 3992 return; 3993 } 3994 } 3967 3995 3968 3996 switch (nSubtype) … … 3997 4025 if (e == NULL) 3998 4026 { 3999 gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 4027 // Try acking it, even if we didn't expect it 4028 //gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 4029 gLog.Info(tr("%sActivate server contact list.\n"), L_SRVxSTR); 4030 CSrvPacketTcp *p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxACK); 4031 SendEvent_Server(p); 4000 4032 break; 4001 4033 } … … 4069 4101 if (u) 4070 4102 { 4103 // For now, just save all the TLVs. We should change this to have awaiting auth check 4104 // for the 0x0066 TLV, SMS number if it has the 0x013A TLV, etc 4105 TLVList tlvList = packet.getTLVList(); 4106 TLVListIter iter; 4107 for (iter = tlvList.begin(); iter != tlvList.end(); ++iter) 4108 { 4109 TLVPtr tlv = iter->second; 4110 u->AddTLV(tlv); 4111 } 4112 4071 4113 u->SetGSID(nTag); 4072 4114 … … 4193 4235 delete [] szUnicodeName; 4194 4236 4195 packet.cleanupTLV();4196 4237 if (szId) 4197 4238 delete[] szId; … … 4219 4260 break; 4220 4261 } // case rost reply 4262 4263 case ICQ_SNACxLIST_ROSTxUPD_GROUP: 4264 { 4265 gLog.Info(tr("%sReceived updated contact information from server.\n"), L_SRVxSTR); 4266 4267 char *szId = packet.UnpackStringBE(); 4268 if (szId == 0) 4269 { 4270 gLog.Error(tr("%sDid not receive user ID.\n"), L_SRVxSTR); 4271 break; 4272 } 4273 4274 unsigned short gsid = packet.UnpackUnsignedShortBE(); 4275 unsigned short sid = packet.UnpackUnsignedShortBE(); 4276 /*unsigned short classid =*/ packet.UnpackUnsignedShortBE(); 4277 4278 unsigned short tlvBytes = packet.UnpackUnsignedShortBE(); 4279 4280 if (!packet.readTLV(-1, tlvBytes)) 4281 { 4282 gLog.Error(tr("%sError during parsing packet!\n"), L_ERRORxSTR); 4283 break; 4284 } 4285 4286 ICQUser *u = gUserManager.FetchUser(szId, LICQ_PPID, LOCK_W); 4287 if (u) 4288 { 4289 // First update their gsid/sid 4290 u->SetSID(sid); 4291 u->SetGSID(gsid); 4292 4293 // Now the the tlv of attributes to attach to the user 4294 TLVList tlvList = packet.getTLVList(); 4295 TLVListIter iter; 4296 for (iter = tlvList.begin(); iter != tlvList.end(); ++iter) 4297 { 4298 TLVPtr tlv = iter->second; 4299 u->AddTLV(tlv); 4300 } 4301 4302 gUserManager.DropUser(u); 4303 } 4304 4305 delete [] szId; 4306 4307 break; 4308 } 4221 4309 4222 4310 case ICQ_SNACxLIST_ROSTxSYNCED: … … 4466 4554 { 4467 4555 u->SetAwaitingAuth(false); 4556 u->RemoveTLV(0x0066); 4468 4557 gUserManager.DropUser(u); 4469 4558 }
