diff options
Diffstat (limited to 'protocols/JabberG/jabber_iq.h')
-rw-r--r-- | protocols/JabberG/jabber_iq.h | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/protocols/JabberG/jabber_iq.h b/protocols/JabberG/jabber_iq.h new file mode 100644 index 0000000000..15ed360d86 --- /dev/null +++ b/protocols/JabberG/jabber_iq.h @@ -0,0 +1,533 @@ +/*
+
+Jabber Protocol Plugin for Miranda IM
+Copyright ( C ) 2002-04 Santithorn Bunchua
+Copyright ( C ) 2005-11 George Hazan
+Copyright ( C ) 2007 Maxim Mluhov
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or ( at your option ) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Revision : $Revision: 13870 $
+Last change on : $Date: 2011-09-16 16:30:27 +0300 (Пт, 16 сен 2011) $
+Last change by : $Author: george.hazan $
+
+*/
+
+#ifndef _JABBER_IQ_H_
+#define _JABBER_IQ_H_
+
+#include "jabber_xml.h"
+
+class CJabberIqInfo;
+
+typedef enum {
+ IQ_PROC_NONE,
+ IQ_PROC_GETAGENTS,
+ IQ_PROC_GETREGISTER,
+ IQ_PROC_SETREGISTER,
+ IQ_PROC_GETVCARD,
+ IQ_PROC_SETVCARD,
+ IQ_PROC_GETSEARCH,
+ IQ_PROC_GETSEARCHFIELDS,
+ IQ_PROC_BROWSEROOMS,
+ IQ_PROC_DISCOROOMSERVER,
+ IQ_PROC_DISCOAGENTS,
+ IQ_PROC_DISCOBOOKMARKS,
+ IQ_PROC_SETBOOKMARKS,
+ IQ_PROC_DISCOCOMMANDS,
+ IQ_PROC_EXECCOMMANDS,
+} JABBER_IQ_PROCID;
+
+struct CJabberProto;
+typedef void ( CJabberProto::*JABBER_IQ_PFUNC )( HXML iqNode );
+typedef void ( *IQ_USER_DATA_FREE_FUNC )( void *pUserData );
+
+typedef struct {
+ TCHAR* xmlns;
+ JABBER_IQ_PFUNC func;
+ BOOL allowSubNs; // e.g. #info in disco#info
+} JABBER_IQ_XMLNS_FUNC;
+
+void __stdcall replaceStr( char*& dest, const char* src );
+void __stdcall replaceStr( WCHAR*& dest, const WCHAR* src );
+
+// 2 minutes, milliseconds
+#define JABBER_DEFAULT_IQ_REQUEST_TIMEOUT 120000
+
+typedef void ( CJabberProto::*JABBER_IQ_HANDLER )( HXML iqNode, CJabberIqInfo* pInfo );
+typedef BOOL ( CJabberProto::*JABBER_PERMANENT_IQ_HANDLER )( HXML iqNode, CJabberIqInfo* pInfo );
+
+#define JABBER_IQ_PARSE_CHILD_TAG_NODE (1)
+#define JABBER_IQ_PARSE_CHILD_TAG_NAME ((1<<1)|JABBER_IQ_PARSE_CHILD_TAG_NODE)
+#define JABBER_IQ_PARSE_CHILD_TAG_XMLNS ((1<<2)|JABBER_IQ_PARSE_CHILD_TAG_NODE)
+#define JABBER_IQ_PARSE_FROM (1<<3)
+#define JABBER_IQ_PARSE_HCONTACT ((1<<4)|JABBER_IQ_PARSE_FROM)
+#define JABBER_IQ_PARSE_TO (1<<5)
+#define JABBER_IQ_PARSE_ID_STR (1<<6)
+
+#define JABBER_IQ_PARSE_DEFAULT (JABBER_IQ_PARSE_CHILD_TAG_NODE|JABBER_IQ_PARSE_CHILD_TAG_NAME|JABBER_IQ_PARSE_CHILD_TAG_XMLNS)
+
+class CJabberIqInfo
+{
+protected:
+ friend class CJabberIqManager;
+ JABBER_IQ_HANDLER m_pHandler;
+ CJabberIqInfo* m_pNext;
+
+ int m_nIqId;
+ DWORD m_dwParamsToParse;
+ DWORD m_dwRequestTime;
+ DWORD m_dwTimeout;
+ TCHAR *m_szReceiver;
+ int m_iPriority;
+public:
+ void *m_pUserData;
+public:// parsed data
+ int m_nIqType;
+ TCHAR *m_szFrom;
+ TCHAR *m_szChildTagXmlns;
+ TCHAR *m_szChildTagName;
+ HXML m_pChildNode;
+ HANDLE m_hContact;
+ TCHAR *m_szTo;
+ TCHAR *m_szId;
+public:
+ CJabberIqInfo()
+ {
+ ZeroMemory(this, sizeof(CJabberIqInfo));
+ }
+ ~CJabberIqInfo()
+ {
+ if (m_szReceiver)
+ mir_free(m_szReceiver);
+ }
+ void SetReceiver(const TCHAR *szReceiver)
+ {
+ replaceStr(m_szReceiver, szReceiver);
+ }
+ TCHAR* GetReceiver()
+ {
+ return m_szReceiver;
+ }
+ void SetParamsToParse(DWORD dwParamsToParse)
+ {
+ m_dwParamsToParse = dwParamsToParse;
+ }
+ void SetTimeout(DWORD dwTimeout)
+ {
+ m_dwTimeout = dwTimeout;
+ }
+ int GetIqId()
+ {
+ return m_nIqId;
+ }
+ DWORD GetRequestTime()
+ {
+ return m_dwRequestTime;
+ }
+ int GetIqType()
+ {
+ return m_nIqType;
+ }
+ void* GetUserData()
+ {
+ return m_pUserData;
+ }
+ TCHAR* GetFrom()
+ {
+ return m_szFrom;
+ }
+ TCHAR* GetTo()
+ {
+ return m_szTo;
+ }
+ TCHAR* GetIdStr()
+ {
+ return m_szId;
+ }
+ HANDLE GetHContact()
+ {
+ return m_hContact;
+ }
+ HXML GetChildNode()
+ {
+ return m_pChildNode;
+ }
+ TCHAR* GetChildNodeName()
+ {
+ return m_szChildTagName;
+ }
+ char* GetCharIqType()
+ {
+ switch (m_nIqType)
+ {
+ case JABBER_IQ_TYPE_SET: return "set";
+ case JABBER_IQ_TYPE_GET: return "get";
+ case JABBER_IQ_TYPE_ERROR: return "error";
+ case JABBER_IQ_TYPE_RESULT: return "result";
+ }
+ return NULL;
+ }
+};
+
+class CJabberIqPermanentInfo
+{
+ friend class CJabberIqManager;
+
+ CJabberIqPermanentInfo* m_pNext;
+
+ JABBER_PERMANENT_IQ_HANDLER m_pHandler;
+ DWORD m_dwParamsToParse;
+ int m_nIqTypes;
+ TCHAR* m_szXmlns;
+ TCHAR* m_szTag;
+ BOOL m_bAllowPartialNs;
+ void *m_pUserData;
+ IQ_USER_DATA_FREE_FUNC m_pUserDataFree;
+ int m_iPriority;
+public:
+ CJabberIqPermanentInfo()
+ {
+ ZeroMemory(this, sizeof(CJabberIqPermanentInfo));
+ }
+ ~CJabberIqPermanentInfo()
+ {
+ if ( m_pUserDataFree )
+ m_pUserDataFree(m_pUserData);
+ mir_free(m_szXmlns);
+ mir_free(m_szTag);
+ }
+};
+
+class CJabberIqManager
+{
+protected:
+ CJabberProto* ppro;
+ CRITICAL_SECTION m_cs;
+ DWORD m_dwLastUsedHandle;
+ CJabberIqInfo* m_pIqs; // list of iqs ordered by priority
+ HANDLE m_hExpirerThread;
+ BOOL m_bExpirerThreadShutdownRequest;
+
+ CJabberIqPermanentInfo* m_pPermanentHandlers;
+
+ CJabberIqInfo* DetachInfo(int nIqId)
+ {
+ if (!m_pIqs)
+ return NULL;
+
+ CJabberIqInfo* pInfo = m_pIqs;
+ if (m_pIqs->m_nIqId == nIqId)
+ {
+ m_pIqs = pInfo->m_pNext;
+ pInfo->m_pNext = NULL;
+ return pInfo;
+ }
+
+ while (pInfo->m_pNext)
+ {
+ if (pInfo->m_pNext->m_nIqId == nIqId)
+ {
+ CJabberIqInfo* pRetVal = pInfo->m_pNext;
+ pInfo->m_pNext = pInfo->m_pNext->m_pNext;
+ pRetVal->m_pNext = NULL;
+ return pRetVal;
+ }
+ pInfo = pInfo->m_pNext;
+ }
+ return NULL;
+ }
+ CJabberIqInfo* DetachInfo(void *pUserData)
+ {
+ if (!m_pIqs)
+ return NULL;
+
+ CJabberIqInfo* pInfo = m_pIqs;
+ if (m_pIqs->m_pUserData == pUserData)
+ {
+ m_pIqs = pInfo->m_pNext;
+ pInfo->m_pNext = NULL;
+ return pInfo;
+ }
+
+ while (pInfo->m_pNext)
+ {
+ if (pInfo->m_pNext->m_pUserData == pUserData)
+ {
+ CJabberIqInfo* pRetVal = pInfo->m_pNext;
+ pInfo->m_pNext = pInfo->m_pNext->m_pNext;
+ pRetVal->m_pNext = NULL;
+ return pRetVal;
+ }
+ pInfo = pInfo->m_pNext;
+ }
+ return NULL;
+ }
+ CJabberIqInfo* DetachExpired()
+ {
+ if (!m_pIqs)
+ return NULL;
+
+ DWORD dwCurrentTime = GetTickCount();
+
+ CJabberIqInfo* pInfo = m_pIqs;
+ if (dwCurrentTime - pInfo->m_dwRequestTime > pInfo->m_dwTimeout )
+ {
+ m_pIqs = pInfo->m_pNext;
+ pInfo->m_pNext = NULL;
+ return pInfo;
+ }
+
+ while (pInfo->m_pNext)
+ {
+ if (dwCurrentTime - pInfo->m_pNext->m_dwRequestTime > pInfo->m_pNext->m_dwTimeout )
+ {
+ CJabberIqInfo* pRetVal = pInfo->m_pNext;
+ pInfo->m_pNext = pInfo->m_pNext->m_pNext;
+ pRetVal->m_pNext = NULL;
+ return pRetVal;
+ }
+ pInfo = pInfo->m_pNext;
+ }
+ return NULL;
+ }
+ void ExpireInfo( CJabberIqInfo* pInfo, void *pUserData = NULL );
+ BOOL InsertIq(CJabberIqInfo* pInfo)
+ { // inserts pInfo at a place determined by pInfo->m_iPriority
+ Lock();
+ if (!m_pIqs)
+ m_pIqs = pInfo;
+ else
+ {
+ if (m_pIqs->m_iPriority > pInfo->m_iPriority) {
+ pInfo->m_pNext = m_pIqs;
+ m_pIqs = pInfo;
+ } else
+ {
+ CJabberIqInfo* pTmp = m_pIqs;
+ while (pTmp->m_pNext && pTmp->m_pNext->m_iPriority <= pInfo->m_iPriority)
+ pTmp = pTmp->m_pNext;
+ pInfo->m_pNext = pTmp->m_pNext;
+ pTmp->m_pNext = pInfo;
+ }
+ }
+ Unlock();
+ return TRUE;
+ }
+public:
+ CJabberIqManager( CJabberProto* proto )
+ {
+ InitializeCriticalSection(&m_cs);
+ m_dwLastUsedHandle = 0;
+ m_pIqs = NULL;
+ m_hExpirerThread = NULL;
+ m_pPermanentHandlers = NULL;
+ ppro = proto;
+ }
+ ~CJabberIqManager()
+ {
+ ExpireAll();
+ Lock();
+ CJabberIqPermanentInfo *pInfo = m_pPermanentHandlers;
+ while ( pInfo )
+ {
+ CJabberIqPermanentInfo *pTmp = pInfo->m_pNext;
+ delete pInfo;
+ pInfo = pTmp;
+ }
+ m_pPermanentHandlers = NULL;
+ Unlock();
+ DeleteCriticalSection(&m_cs);
+ }
+ BOOL Start();
+ BOOL Shutdown()
+ {
+ if ( m_bExpirerThreadShutdownRequest || !m_hExpirerThread )
+ return TRUE;
+
+ m_bExpirerThreadShutdownRequest = TRUE;
+
+ WaitForSingleObject( m_hExpirerThread, INFINITE );
+ CloseHandle( m_hExpirerThread );
+ m_hExpirerThread = NULL;
+
+ return TRUE;
+ }
+ void Lock()
+ {
+ EnterCriticalSection(&m_cs);
+ }
+ void Unlock()
+ {
+ LeaveCriticalSection(&m_cs);
+ }
+ // fucking params, maybe just return CJabberIqRequestInfo pointer ?
+ CJabberIqInfo* AddHandler(JABBER_IQ_HANDLER pHandler, int nIqType = JABBER_IQ_TYPE_GET, const TCHAR *szReceiver = NULL, DWORD dwParamsToParse = 0, int nIqId = -1, void *pUserData = NULL, int iPriority = JH_PRIORITY_DEFAULT);
+ CJabberIqPermanentInfo* AddPermanentHandler(JABBER_PERMANENT_IQ_HANDLER pHandler, int nIqTypes, DWORD dwParamsToParse, const TCHAR* szXmlns, BOOL bAllowPartialNs, const TCHAR* szTag, void *pUserData = NULL, IQ_USER_DATA_FREE_FUNC pUserDataFree = NULL, int iPriority = JH_PRIORITY_DEFAULT)
+ {
+ CJabberIqPermanentInfo* pInfo = new CJabberIqPermanentInfo();
+ if (!pInfo)
+ return NULL;
+
+ pInfo->m_pHandler = pHandler;
+ pInfo->m_nIqTypes = nIqTypes ? nIqTypes : JABBER_IQ_TYPE_ANY;
+ replaceStr( pInfo->m_szXmlns, szXmlns );
+ pInfo->m_bAllowPartialNs = bAllowPartialNs;
+ replaceStr( pInfo->m_szTag, szTag );
+ pInfo->m_dwParamsToParse = dwParamsToParse;
+ pInfo->m_pUserData = pUserData;
+ pInfo->m_pUserDataFree = pUserDataFree;
+ pInfo->m_iPriority = iPriority;
+
+ Lock();
+ if (!m_pPermanentHandlers)
+ m_pPermanentHandlers = pInfo;
+ else
+ {
+ if (m_pPermanentHandlers->m_iPriority > pInfo->m_iPriority) {
+ pInfo->m_pNext = m_pPermanentHandlers;
+ m_pPermanentHandlers = pInfo;
+ } else
+ {
+ CJabberIqPermanentInfo* pTmp = m_pPermanentHandlers;
+ while (pTmp->m_pNext && pTmp->m_pNext->m_iPriority <= pInfo->m_iPriority)
+ pTmp = pTmp->m_pNext;
+ pInfo->m_pNext = pTmp->m_pNext;
+ pTmp->m_pNext = pInfo;
+ }
+ }
+ Unlock();
+
+ return pInfo;
+ }
+ BOOL DeletePermanentHandler(CJabberIqPermanentInfo *pInfo)
+ { // returns TRUE when pInfo found, or FALSE otherwise
+ Lock();
+ if (!m_pPermanentHandlers)
+ {
+ Unlock();
+ return FALSE;
+ }
+ if (m_pPermanentHandlers == pInfo) // check first item
+ {
+ m_pPermanentHandlers = m_pPermanentHandlers->m_pNext;
+ delete pInfo;
+ Unlock();
+ return TRUE;
+ } else
+ {
+ CJabberIqPermanentInfo* pTmp = m_pPermanentHandlers;
+ while (pTmp->m_pNext)
+ {
+ if (pTmp->m_pNext == pInfo)
+ {
+ pTmp->m_pNext = pTmp->m_pNext->m_pNext;
+ delete pInfo;
+ Unlock();
+ return TRUE;
+ }
+ pTmp = pTmp->m_pNext;
+ }
+ }
+ Unlock();
+ return FALSE;
+ }
+ BOOL DeleteHandler(CJabberIqInfo *pInfo)
+ { // returns TRUE when pInfo found, or FALSE otherwise
+ Lock();
+ if (!m_pIqs)
+ {
+ Unlock();
+ return FALSE;
+ }
+ if (m_pIqs == pInfo) // check first item
+ {
+ m_pIqs = m_pIqs->m_pNext;
+ Unlock();
+ ExpireInfo(pInfo); // must expire it to allow the handler to free m_pUserData if necessary
+ delete pInfo;
+ return TRUE;
+ } else
+ {
+ CJabberIqInfo* pTmp = m_pIqs;
+ while (pTmp->m_pNext)
+ {
+ if (pTmp->m_pNext == pInfo)
+ {
+ pTmp->m_pNext = pTmp->m_pNext->m_pNext;
+ Unlock();
+ ExpireInfo(pInfo); // must expire it to allow the handler to free m_pUserData if necessary
+ delete pInfo;
+ return TRUE;
+ }
+ pTmp = pTmp->m_pNext;
+ }
+ }
+ Unlock();
+ return FALSE;
+ }
+ BOOL HandleIq(int nIqId, HXML pNode);
+ BOOL HandleIqPermanent(HXML pNode);
+ BOOL ExpireIq(int nIqId)
+ {
+ Lock();
+ CJabberIqInfo* pInfo = DetachInfo(nIqId);
+ Unlock();
+ if (pInfo)
+ {
+ ExpireInfo(pInfo);
+ delete pInfo;
+ return TRUE;
+ }
+ return FALSE;
+ }
+ void ExpirerThread( void );
+ BOOL ExpireByUserData(void *pUserData)
+ {
+ BOOL bRetVal = FALSE;
+ while (1)
+ {
+ Lock();
+ CJabberIqInfo* pInfo = DetachInfo(pUserData);
+ Unlock();
+ if (!pInfo)
+ break;
+ ExpireInfo(pInfo, NULL);
+ delete pInfo;
+ bRetVal = TRUE;
+ }
+ return bRetVal;
+ }
+ BOOL ExpireAll(void *pUserData = NULL)
+ {
+ while (1)
+ {
+ Lock();
+ CJabberIqInfo* pInfo = m_pIqs;
+ if (pInfo)
+ m_pIqs = m_pIqs->m_pNext;
+ Unlock();
+ if (!pInfo)
+ break;
+ pInfo->m_pNext = NULL;
+ ExpireInfo(pInfo, pUserData);
+ delete pInfo;
+ }
+ return TRUE;
+ }
+ BOOL FillPermanentHandlers();
+};
+
+#endif
|