00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 #include "stdafx.h"
00037 #include "SocketThreadManagerImp.h"
00038 
00039 #include "ErrorHandlerMacros.h"
00040 #include "OSManager.h"
00041 #include "GenericCriticalSection.h"
00042 
00043 #include "AsyncSocket.h"
00044 
00045 #include <vector>
00046 
00047 #ifdef _MEMORY_DEBUG 
00048     #define new    DEBUG_NEW  
00049     #define malloc DEBUG_MALLOC  
00050     static char THIS_FILE[] = __FILE__;  
00051 #endif
00052 
00053 KOMODIA_NAMESPACE_START
00054 
00055 
00056 BOOL CSocketThreadManagerImp::m_bWindow=FALSE;
00057 
00058 
00059 CSocketThreadManagerImp CSocketThreadManagerImp::m_sCleanUp;
00060 
00061 
00062 HINSTANCE CSocketThreadManagerImp::m_hInstance=0;
00063 
00064 #define CSocketThreadManagerImp_Class "CSocketThreadManagerImp"
00065 
00066 CSocketThreadManagerImp::CSocketThreadManagerImp() : CSocketThreadManager((HINSTANCE)0),
00067                                                      m_bStatic(TRUE),
00068                                                      m_hLocalInstance(0)
00069 {
00070     try
00071     {
00072         
00073         SetName(CSocketThreadManagerImp_Class);
00074     }
00075     ERROR_HANDLER("CSocketThreadManagerImp")
00076 }
00077 
00078 CSocketThreadManagerImp::CSocketThreadManagerImp(HINSTANCE hInstance) : CSocketThreadManager(hInstance),
00079                                                                         m_hLocalInstance(hInstance),
00080                                                                         m_bStatic(FALSE)
00081 {
00082     try
00083     {
00084         
00085         SetName(CSocketThreadManagerImp_Class);
00086     }
00087     ERROR_HANDLER("CSocketThreadManagerImp")
00088 }
00089 
00090 CSocketThreadManagerImp::~CSocketThreadManagerImp()
00091 {
00092     try
00093     {
00094         
00095         if (m_bStatic)
00096             
00097             if (m_bWindow)
00098             {
00099                 
00100                 ::UnregisterClass(CSocketThreadManagerImp_Class,
00101                                   m_hInstance);
00102 
00103                 
00104                 m_bWindow=FALSE;
00105             }
00106             else
00107                 ;
00108         else
00109             
00110             Uninitialize();
00111     }
00112     ERROR_HANDLER("~CSocketThreadManagerImp")
00113 }
00114 
00115 void CSocketThreadManagerImp::ParseDispatchMessage(const MSG& rMsg,
00116                                                    ThreadData* pData)
00117 {
00118     
00119     ExtensionData* pExtension;
00120     pExtension=(ExtensionData*)pData->aExtension.lpData;
00121 
00122     
00123     MSG aNewMsg(rMsg);
00124 
00125     
00126     if (rMsg.wParam &&
00127         IsSocketMessage(aNewMsg.message))
00128     {
00129         
00130         CCriticalAutoRelease aRelease(pExtension->pCSection);
00131 
00132         
00133         SocketMap::iterator aIterator;
00134         aIterator=pExtension->aSocketsMap.find((int)rMsg.wParam);
00135 
00136         
00137         if (aIterator!=pExtension->aSocketsMap.end())
00138             
00139             aNewMsg.wParam=(WPARAM)aIterator->second;
00140         else
00141             aNewMsg.wParam=0;
00142     }
00143 
00144     
00145     CSocketThreadManager::ParseDispatchMessage(aNewMsg,
00146                                                pData);
00147 }
00148 
00149 void CSocketThreadManagerImp::CreateExtendedData(ThreadDataExtend& rData)
00150 {
00151     try
00152     {
00153         
00154         ExtensionData* pData;
00155         pData=new ExtensionData;
00156 
00157         
00158         pData->pCSection=COSManager::CreateCriticalSection();
00159         
00160         
00161         rData.lpData=(LPVOID)pData;
00162     }
00163     ERROR_HANDLER("CreateExtendedData")
00164 }
00165 
00166 void CSocketThreadManagerImp::DeleteExtendedData(ThreadDataExtend& rData)
00167 {
00168     try
00169     {
00170         
00171         ExtensionData* pData;
00172         pData=(ExtensionData*)rData.lpData;
00173 
00174         
00175         if (pData)
00176         {
00177             
00178             typedef std::vector<CAsyncSocket*> DeleteVector;
00179 
00180             
00181             DeleteVector aDeleteVector;
00182 
00183             {
00184                 
00185                 CCriticalAutoRelease aRelease(pData->pCSection);
00186 
00187                 
00188                 SocketMap::iterator aIterator;
00189                 aIterator=pData->aSocketsMap.begin();
00190                 while (aIterator!=pData->aSocketsMap.end())
00191                 {
00192                     
00193                     aDeleteVector.push_back(aIterator->second);
00194 
00195                     
00196                     aIterator=pData->aSocketsMap.erase(aIterator);
00197                 }
00198             }
00199 
00200             
00201             for (int iCount=0;
00202                  iCount<aDeleteVector.size();
00203                  ++iCount)
00204                 try
00205                 {
00206                     
00207                     aDeleteVector[iCount]->SetDeleting();
00208 
00209                     
00210                     delete aDeleteVector[iCount];
00211                 }
00212                 ERROR_HANDLER("DeleteExtendedData - Socket delete")
00213 
00214             
00215             delete pData->pCSection;
00216 
00217             
00218             delete pData;
00219 
00220             
00221             rData.lpData=NULL;
00222         }
00223     }
00224     ERROR_HANDLER("DeleteExtendedData")
00225 }
00226 
00227 BOOL CSocketThreadManagerImp::Initialize(unsigned long ulThreadCount)
00228 {
00229     try
00230     {
00231         
00232         if (!m_bWindow)
00233         {
00234             
00235             m_hInstance=m_hLocalInstance;
00236 
00237             if (!RegisterWindow(m_hInstance))
00238             {
00239                 
00240                 ReportErrorOS("SetHandlers","Error registering the window, please check API error!");
00241 
00242                 
00243                 return FALSE;
00244             }
00245             else
00246                 
00247                 m_bWindow=TRUE;
00248         }
00249 
00250         
00251         return CSocketThreadManager::Initialize(ulThreadCount,
00252                                                 CSocketThreadManagerImp_Class);
00253     }
00254     ERROR_HANDLER_RETURN("Initialize",FALSE)
00255 }
00256 
00257 BOOL CSocketThreadManagerImp::RegisterWindow(HINSTANCE hInstance)
00258 {
00259     try
00260     {
00261         
00262         WNDCLASS wc;
00263         wc.style = 0;                                       
00264         wc.lpfnWndProc = (WNDPROC)SocketMessageHandler;     
00265         wc.cbClsExtra = 0;                                  
00266         wc.cbWndExtra = 0;                                  
00267         wc.hIcon = NULL;                                    
00268         wc.hInstance = hInstance;                           
00269         wc.hCursor = NULL;
00270         wc.hbrBackground = NULL;
00271         wc.lpszMenuName =  NULL;                            
00272         wc.lpszClassName = CSocketThreadManagerImp_Class ;  
00273 
00274         
00275         return ::RegisterClass(&wc);
00276     }
00277     ERROR_HANDLER_STATIC_RETURN(CSocketThreadManagerImp_Class,"RegisterWindow",FALSE)
00278 }
00279 
00280 HWND CSocketThreadManagerImp::GetWindowHandle(CAsyncSocket* pSocket)
00281 {
00282     try
00283     {
00284         
00285         HWND hHandle;
00286         hHandle=CSocketThreadManager::GetWindowHandle();
00287 
00288         
00289         if (hHandle)
00290             
00291             AddSocketToList(pSocket,
00292                             hHandle);
00293 
00294         
00295         return hHandle;
00296     }
00297     ERROR_HANDLER_RETURN("GetWindowHandle",NULL)
00298 }
00299 
00300 void CSocketThreadManagerImp::AddSocketToList(CAsyncSocket* pSocket,
00301                                               HWND hHandle)
00302 {
00303     try
00304     {
00305         
00306         ThreadData* pData;
00307         pData=GetDataByHWND(hHandle);
00308 
00309         
00310         if (!pData)
00311             
00312             ReportError("AddSocketToList","Failed to find thread data!");
00313         else
00314         {
00315             
00316             ExtensionData* pExtension;
00317             pExtension=(ExtensionData*)pData->aExtension.lpData;
00318 
00319             
00320             CCriticalAutoRelease aRelease(pExtension->pCSection);
00321 
00322             
00323             pExtension->aSocketsMap.insert(SocketMap::value_type(pSocket->GetAsyncHandle(),
00324                                                                  pSocket));
00325         }
00326     }
00327     ERROR_HANDLER("AddSocketToList")
00328 }
00329 
00330 void CSocketThreadManagerImp::RemoveSocket(CAsyncSocket* pSocket)
00331 {
00332     try
00333     {
00334         
00335         HWND hHandle;
00336         hHandle=pSocket->GetWindowHandle();
00337 
00338         
00339         if (!hHandle)
00340         {
00341             
00342             ReportError("RemoveSocket","Received socket without a handle!");
00343 
00344             
00345             return;
00346         }
00347 
00348         
00349         ThreadData* pData;
00350         pData=GetDataByHWND(hHandle);
00351 
00352         
00353         if (!pData)
00354             
00355             ReportError("RemoveSocket","Failed to find thread data!");
00356         else
00357         {
00358             
00359             ExtensionData* pExtension;
00360             pExtension=(ExtensionData*)pData->aExtension.lpData;
00361 
00362             {
00363                 
00364                 CCriticalAutoRelease aRelease(pExtension->pCSection);
00365 
00366                 
00367                 pExtension->aSocketsMap.erase(pSocket->GetAsyncHandle());
00368             }
00369 
00370             
00371             DecreaseSocketCount(hHandle,
00372                                 TRUE);
00373         }
00374     }
00375     ERROR_HANDLER("RemoveSocket")
00376 }
00377 
00378 BOOL CSocketThreadManagerImp::IsSocketMessage(unsigned int uiMsg)
00379 {
00380     return uiMsg==WM_SOCKET_DELETE ||
00381            uiMsg==WM_SOCKET_FORCED ||
00382            uiMsg==WM_SOCKET_GENERAL ||
00383            uiMsg==WM_SOCKET_CONNECT ||
00384            uiMsg==WM_SOCKET_ACCEPT ||
00385            uiMsg==WM_TIMER;
00386 }
00387 
00388 LRESULT CALLBACK CSocketThreadManagerImp::SocketMessageHandler(HWND hwnd,      
00389                                                                UINT uMsg,      
00390                                                                WPARAM wParam,  
00391                                                                LPARAM lParam)   
00392 {
00393     try
00394     {
00395         
00396         CAsyncSocket* pSocket;
00397 
00398         
00399         if (IsSocketMessage(uMsg))
00400             pSocket=(CAsyncSocket*)(wParam);
00401         else
00402             pSocket=NULL;
00403 
00404         
00405         BOOL bIgnore;
00406         if (pSocket &&
00407             pSocket->IsClosing() &&
00408             uMsg!=WM_SOCKET_DELETE)
00409             bIgnore=TRUE;
00410         else if (pSocket &&
00411                  pSocket->m_hLocalWindowHandle!=hwnd)
00412         {
00413             
00414             ReportStaticError(CAsyncSocket_Class,"SocketMessageHandler","Received loose message!");
00415 
00416             
00417             bIgnore=TRUE;
00418         }
00419         else
00420             bIgnore=FALSE;
00421 
00422         
00423         try
00424         {
00425             if (pSocket &&
00426                 !bIgnore)
00427                 
00428                 switch (uMsg)
00429                 {
00430                 case WM_SOCKET_FORCED:
00431                     return pSocket->OnSocketReceive(0);
00432                     break;
00433                 case WM_SOCKET_GENERAL:
00434                     if (WSAGETSELECTEVENT(lParam)==FD_READ)
00435                         return pSocket->SocketReceive(WSAGETSELECTERROR(lParam));
00436                     else if (WSAGETSELECTEVENT(lParam)==FD_WRITE)
00437                         return pSocket->SocketWrite(WSAGETSELECTERROR(lParam));
00438                     else if (WSAGETSELECTEVENT(lParam)==FD_OOB)
00439                         return pSocket->OnSocketOOB(WSAGETSELECTERROR(lParam));
00440                     else if (WSAGETSELECTEVENT(lParam)==FD_CLOSE)
00441                         return pSocket->SocketClosed(WSAGETSELECTERROR(lParam));
00442                     break;
00443                 case WM_SOCKET_CONNECT:
00444                     if (WSAGETSELECTEVENT(lParam)==FD_CONNECT)
00445                         return pSocket->SocketConnected(WSAGETSELECTERROR(lParam));
00446                     break;
00447                 case WM_SOCKET_ACCEPT:
00448                     if (WSAGETSELECTEVENT(lParam)==FD_ACCEPT)
00449                         return pSocket->SocketAccept(WSAGETSELECTERROR(lParam));
00450                     break;
00451                 case WM_TIMER:
00452                     
00453                     if (pSocket->HasTimeout())
00454                         
00455                         return pSocket->OnSocketTimeout();
00456                     else
00457                         return FALSE;
00458                 case WM_SOCKET_DELETE:
00459                     
00460                     pSocket->OnSocketDelete((CGenericEvent*)lParam);
00461 
00462                     
00463                     return TRUE;
00464                 default:                       
00465                     return (int)(DefWindowProc(hwnd, 
00466                                                uMsg, 
00467                                                wParam, 
00468                                                lParam));
00469                 }
00470             else
00471                 return (int)(DefWindowProc(hwnd, 
00472                                            uMsg, 
00473                                            wParam, 
00474                                            lParam));
00475         }
00476         ERROR_HANDLER_STATIC(CSocketThreadManagerImp_Class,"SocketMessageHandler - Proc")
00477 
00478         
00479         return TRUE;
00480     }
00481     ERROR_HANDLER_STATIC_RETURN(CSocketThreadManagerImp_Class,"SocketMessageHandler",TRUE)
00482 }
00483 
00484 KOMODIA_NAMESPACE_END