| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683 | // CAsyncSocketEx by Tim Kosse ([email protected])//                 Version 1.3 (2003-04-26)//---------------------------------------------------------------------------// Feel free to use this class, as long as you don't claim that you wrote it// and this copyright notice stays intact in the source files.// If you use this class in commercial applications, please send a short message// to [email protected]//---------------------------------------------------------------------------#include "stdafx.h"#include "AsyncSocketEx.h"#include "wtypes.h"#include "oleauto.h"#include "atlconv.h"#include "AsyncSocketExLayer.h"#undef TRACE_TRANSMITCCriticalSectionWrapper CAsyncSocketEx::m_sGlobalCriticalSection;CAsyncSocketEx::t_AsyncSocketExThreadDataList *CAsyncSocketEx::m_spAsyncSocketExThreadDataList = 0;///////////////////////////////Helper Window class#define WM_SOCKETEX_NOTIFY (WM_USER+3)#define MAX_SOCKETS (0xBFFF-WM_SOCKETEX_NOTIFY+1)class CAsyncSocketExHelperWindow{public:  CAsyncSocketExHelperWindow(CAsyncSocketEx::t_AsyncSocketExThreadData* pThreadData)  {    //Initialize data    m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets    memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));    m_nWindowDataSize=512;    m_nSocketCount=0;    m_nWindowDataPos=0;    m_pThreadData = pThreadData;    //Create window    WNDCLASSEX wndclass;    wndclass.cbSize=sizeof wndclass;    wndclass.style=0;    wndclass.lpfnWndProc=WindowProc;    wndclass.cbClsExtra=0;    wndclass.cbWndExtra=0;    wndclass.hInstance=GetModuleHandle(0);    wndclass.hIcon=0;    wndclass.hCursor=0;    wndclass.hbrBackground=0;    wndclass.lpszMenuName=0;    wndclass.lpszClassName=L"CAsyncSocketEx Helper Window";    wndclass.hIconSm=0;    #ifdef _DEBUG    ATOM ClassAtom =    #endif    RegisterClassEx(&wndclass);    m_hWnd=CreateWindow(L"CAsyncSocketEx Helper Window", L"CAsyncSocketEx Helper Window", 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0), 0);    DebugAssert(m_hWnd);    SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG)this);  };  virtual ~CAsyncSocketExHelperWindow()  {    //Clean up socket storage    delete [] m_pAsyncSocketExWindowData;    m_pAsyncSocketExWindowData=0;    m_nWindowDataSize=0;    m_nSocketCount=0;    //Destroy window    if (m_hWnd)    {      DestroyWindow(m_hWnd);      m_hWnd=0;    }  }  //Adds a socket to the list of attached sockets  BOOL AddSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)  {    DebugAssert(pSocket);    if (!m_nWindowDataSize)    {      DebugAssert(!m_nSocketCount);      m_nWindowDataSize=512;      m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets      memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));    }    if (nSocketIndex!=-1)    {      DebugAssert(m_pAsyncSocketExWindowData);      DebugAssert(m_nWindowDataSize>nSocketIndex);      DebugAssert(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket);      DebugAssert(m_nSocketCount);      return TRUE;    }    //Increase socket storage if too small    if (m_nSocketCount>=(m_nWindowDataSize-10))    {      int nOldWindowDataSize=m_nWindowDataSize;      DebugAssert(m_nWindowDataSize<MAX_SOCKETS);      m_nWindowDataSize+=512;      if (m_nWindowDataSize>MAX_SOCKETS)        m_nWindowDataSize=MAX_SOCKETS;      t_AsyncSocketExWindowData *tmp=m_pAsyncSocketExWindowData;      m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[m_nWindowDataSize];      memcpy(m_pAsyncSocketExWindowData, tmp, nOldWindowDataSize * sizeof(t_AsyncSocketExWindowData));      memset(m_pAsyncSocketExWindowData+nOldWindowDataSize, 0, (m_nWindowDataSize-nOldWindowDataSize)*sizeof(t_AsyncSocketExWindowData));      delete [] tmp;    }    //Search for free slot    for (int i=m_nWindowDataPos;i<(m_nWindowDataSize+m_nWindowDataPos);i++)    {      if (!m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket)      {        m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket=pSocket;        nSocketIndex=i%m_nWindowDataSize;        m_nWindowDataPos=(i+1)%m_nWindowDataSize;        m_nSocketCount++;        return TRUE;      }    }    //No slot found, maybe there are too much sockets!    return FALSE;  }  //Removes a socket from the socket storage  BOOL RemoveSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)  {    DebugAssert(pSocket);    if (nSocketIndex==-1)      return TRUE;    // Remove additional messages from queue    MSG msg;    while (PeekMessage(&msg, m_hWnd, WM_SOCKETEX_NOTIFY + nSocketIndex, WM_SOCKETEX_NOTIFY + nSocketIndex, PM_REMOVE));    DebugAssert(m_pAsyncSocketExWindowData);    DebugAssert(m_nWindowDataSize>0);    DebugAssert(m_nSocketCount>0);    DebugAssert(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket);    m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket=0;    nSocketIndex=-1;    m_nSocketCount--;    return TRUE;  }  void RemoveLayers(CAsyncSocketEx *pOrigSocket)  {    // Remove all layer messages from old socket    std::list<MSG> msgList;    MSG msg;    while (PeekMessage(&msg, m_hWnd, WM_USER, WM_USER, PM_REMOVE))    {      //Verify parameters, lookup socket and notification message      //Verify parameters      if (msg.wParam >= static_cast<UINT>(m_nWindowDataSize)) //Index is within socket storage        continue;      CAsyncSocketEx *pSocket = m_pAsyncSocketExWindowData[msg.wParam].m_pSocket;      CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=(CAsyncSocketExLayer::t_LayerNotifyMsg *)msg.lParam;      if (!pMsg || !pSocket || pSocket == pOrigSocket || pSocket->m_SocketData.hSocket != pMsg->hSocket)      {        delete pMsg;        continue;      }      msgList.push_back(msg);    }    for (std::list<MSG>::iterator iter = msgList.begin(); iter != msgList.end(); iter++)    {      PostMessage(m_hWnd, iter->message, iter->wParam, iter->lParam);    }  }  //Processes event notifications sent by the sockets or the layers  static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  {    //Verify parameters    DebugAssert(hWnd);    if (!hWnd)      return 0;    CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWL_USERDATA);    if (message>=WM_SOCKETEX_NOTIFY)    {      DebugAssert(pWnd);      if (message<static_cast<UINT>(WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize)) //Index is within socket storage      {        //Lookup socket and verify if it's valid        CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[message-WM_SOCKETEX_NOTIFY].m_pSocket;        SOCKET hSocket=wParam;        if (!pSocket)          return 0;        if (hSocket==INVALID_SOCKET)          return 0;        if (pSocket->m_SocketData.hSocket != hSocket)          return 0;        int nEvent=lParam&0xFFFF;        int nErrorCode=lParam>>16;        //Dispatch notification        if (!pSocket->m_pFirstLayer)        {          //Dispatch to CAsyncSocketEx instance          switch (nEvent)          {          case FD_READ:            if (pSocket->GetState() == connecting && !nErrorCode)            {              pSocket->m_nPendingEvents |= FD_READ;              break;            }            else if (pSocket->GetState() == attached)            {              pSocket->SetState(connected);            }            if (pSocket->GetState() != connected)              break;            // Ignore further FD_READ events after FD_CLOSE has been received            if (pSocket->m_SocketData.onCloseCalled)              break;            if (pSocket->m_lEvent & FD_READ)            {              DWORD nBytes = 0;              if (!nErrorCode)                if (!pSocket->IOCtl(FIONREAD, &nBytes))                  nErrorCode = WSAGetLastError();              if (nErrorCode)              {                pSocket->SetState(aborted);              }              if (nBytes != 0 || nErrorCode != 0)                pSocket->OnReceive(nErrorCode);            }            break;          case FD_FORCEREAD: //Forceread does not check if there's data waiting            if (pSocket->GetState() == connecting && !nErrorCode)            {              pSocket->m_nPendingEvents |= FD_FORCEREAD;              break;            }            else if (pSocket->GetState() == attached)            {              pSocket->SetState(connected);            }            if (pSocket->GetState() != connected)              break;            if (pSocket->m_lEvent & FD_READ)            {              if (nErrorCode)              {                pSocket->SetState(aborted);              }              pSocket->OnReceive(nErrorCode);            }            break;          case FD_WRITE:            if (pSocket->GetState() == connecting && !nErrorCode)            {              pSocket->m_nPendingEvents |= FD_WRITE;              break;            }            else if (pSocket->GetState() == attached && !nErrorCode)            {              pSocket->SetState(connected);            }            if (pSocket->GetState() != connected)              break;            if (pSocket->m_lEvent & FD_WRITE)            {              if (nErrorCode)              {                pSocket->SetState(aborted);              }              pSocket->OnSend(nErrorCode);            }            break;          case FD_CONNECT:            if (pSocket->GetState() == connecting)            {              if (nErrorCode && pSocket->m_SocketData.nextAddr)              {                if (pSocket->TryNextProtocol())                                    break;              }              pSocket->SetState(connected);            }            else if (pSocket->GetState() == attached && !nErrorCode)            {              pSocket->SetState(connected);            }            if (pSocket->m_lEvent & FD_CONNECT)              pSocket->OnConnect(nErrorCode);            if (!nErrorCode)            {              if ((pSocket->m_nPendingEvents&FD_READ) && pSocket->GetState() == connected)                pSocket->OnReceive(0);              if ((pSocket->m_nPendingEvents&FD_FORCEREAD) && pSocket->GetState() == connected)                pSocket->OnReceive(0);              if ((pSocket->m_nPendingEvents&FD_WRITE) && pSocket->GetState() == connected)                pSocket->OnSend(0);            }            pSocket->m_nPendingEvents = 0;            break;          case FD_ACCEPT:            if (pSocket->GetState() != listening && pSocket->GetState() != attached)              break;            if (pSocket->m_lEvent & FD_ACCEPT)              pSocket->OnAccept(nErrorCode);            break;          case FD_CLOSE:            if (pSocket->GetState() != connected && pSocket->GetState() != attached)              break;            // If there are still bytes left to read, call OnReceive instead of            // OnClose and trigger a new OnClose            DWORD nBytes = 0;            if (!nErrorCode && pSocket->IOCtl(FIONREAD, &nBytes))            {              if (nBytes > 0)              {                // Just repeat message.                PostMessage(hWnd, message, wParam, lParam);                pSocket->m_SocketData.onCloseCalled = true;                pSocket->OnReceive(WSAESHUTDOWN);                break;              }            }            pSocket->SetState(nErrorCode?aborted:closed);            pSocket->OnClose(nErrorCode);            break;          }        }        else //Dispatch notification to the lowest layer        {          if (nEvent == FD_READ)          {            // Ignore further FD_READ events after FD_CLOSE has been received            if (pSocket->m_SocketData.onCloseCalled)              return 0;            DWORD nBytes;            if (!pSocket->IOCtl(FIONREAD, &nBytes))              nErrorCode = WSAGetLastError();            if (nBytes != 0 || nErrorCode != 0)              pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);          }          else if (nEvent == FD_CLOSE)          {            // If there are still bytes left to read, call OnReceive instead of            // OnClose and trigger a new OnClose            DWORD nBytes = 0;            if (!nErrorCode && pSocket->IOCtl(FIONREAD, &nBytes))            {              if (nBytes > 0)              {                // Just repeat message.                pSocket->ResendCloseNotify();                pSocket->m_pLastLayer->CallEvent(FD_READ, 0);                return 0;              }            }            pSocket->m_SocketData.onCloseCalled = true;            pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);          }          else          {            pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);          }        }      }      return 0;    }    else if (message == WM_USER) //Notification event sent by a layer    {      DebugAssert(pWnd);      if (wParam >= static_cast<UINT>(pWnd->m_nWindowDataSize)) //Index is within socket storage      {        return 0;      }      CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;      CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=(CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam;      if (!pMsg || !pSocket || pSocket->m_SocketData.hSocket != pMsg->hSocket)      {        delete pMsg;        return 0;      }      int nEvent=pMsg->lEvent&0xFFFF;      int nErrorCode=pMsg->lEvent>>16;      //Dispatch to layer      if (pMsg->pLayer)      {        pMsg->pLayer->CallEvent(nEvent, nErrorCode);      }      else      {        //Dispatch to CAsyncSocketEx instance        switch (nEvent)        {        case FD_READ:          if (pSocket->GetState() == connecting && !nErrorCode)          {            pSocket->m_nPendingEvents |= FD_READ;            break;          }          else if (pSocket->GetState() == attached && !nErrorCode)          {            pSocket->SetState(connected);          }          if (pSocket->GetState() != connected)            break;          if (pSocket->m_lEvent & FD_READ)          {            if (nErrorCode)            {              pSocket->SetState(aborted);            }            pSocket->OnReceive(nErrorCode);          }          break;        case FD_FORCEREAD: //Forceread does not check if there's data waiting          if (pSocket->GetState() == connecting && !nErrorCode)          {            pSocket->m_nPendingEvents |= FD_FORCEREAD;            break;          }          else if (pSocket->GetState() == attached && !nErrorCode)          {            pSocket->SetState(connected);          }          if (pSocket->GetState() != connected)            break;          if (pSocket->m_lEvent & FD_READ)          {            if (nErrorCode)            {              pSocket->SetState(aborted);            }            pSocket->OnReceive(nErrorCode);          }          break;        case FD_WRITE:          if (pSocket->GetState() == connecting && !nErrorCode)          {            pSocket->m_nPendingEvents |= FD_WRITE;            break;          }          else if (pSocket->GetState() == attached && !nErrorCode)          {            pSocket->SetState(connected);          }          if (pSocket->GetState() != connected)            break;          if (pSocket->m_lEvent & FD_WRITE)          {            if (nErrorCode)            {              pSocket->SetState(aborted);            }            pSocket->OnSend(nErrorCode);          }          break;        case FD_CONNECT:          if (pSocket->GetState() == connecting)          {            pSocket->SetState(connected);          }          else if (pSocket->GetState() == attached && !nErrorCode)          {            pSocket->SetState(connected);          }          if (pSocket->m_lEvent & FD_CONNECT)            pSocket->OnConnect(nErrorCode);          if (!nErrorCode)          {            if (((pSocket->m_nPendingEvents&FD_READ) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_READ))              pSocket->OnReceive(0);            if (((pSocket->m_nPendingEvents&FD_FORCEREAD) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_READ))              pSocket->OnReceive(0);            if (((pSocket->m_nPendingEvents&FD_WRITE) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_WRITE))              pSocket->OnSend(0);          }          pSocket->m_nPendingEvents = 0;          break;        case FD_ACCEPT:          if ((pSocket->GetState() == listening || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_ACCEPT))          {            pSocket->OnAccept(nErrorCode);          }          break;        case FD_CLOSE:          if ((pSocket->GetState() == connected || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_CLOSE))          {            pSocket->SetState(nErrorCode?aborted:closed);            pSocket->OnClose(nErrorCode);          }          break;        }      }      delete pMsg;      return 0;    }    else if (message == WM_USER+1)    {      DebugAssert(pWnd);      // WSAAsyncGetHostByName reply      // Verify parameters      DebugAssert(hWnd);      CAsyncSocketExHelperWindow *pWnd = (CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWL_USERDATA);      DebugAssert(pWnd);      CAsyncSocketEx *pSocket = NULL;      for (int i = 0; i < pWnd->m_nWindowDataSize; i++)      {        pSocket = pWnd->m_pAsyncSocketExWindowData[i].m_pSocket;        if (pSocket && pSocket->m_hAsyncGetHostByNameHandle &&          pSocket->m_hAsyncGetHostByNameHandle == (HANDLE)wParam)          break;      }      if (!pSocket)        return 0;      int nErrorCode = lParam >> 16;      if (nErrorCode)      {        pSocket->OnConnect(nErrorCode);        return 0;      }      SOCKADDR_IN sockAddr;      memset(&sockAddr,0,sizeof(sockAddr));      sockAddr.sin_family=AF_INET;      sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr;      sockAddr.sin_port = htons(pSocket->m_nAsyncGetHostByNamePort);      BOOL res = pSocket->Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));      delete [] pSocket->m_pAsyncGetHostByNameBuffer;      pSocket->m_pAsyncGetHostByNameBuffer=0;      pSocket->m_hAsyncGetHostByNameHandle=0;      if (!res)        if (GetLastError()!=WSAEWOULDBLOCK)          pSocket->OnConnect(GetLastError());      return 0;    }    else if (message == WM_USER + 2)    {      DebugAssert(pWnd);      if (wParam >= static_cast<UINT>(pWnd->m_nWindowDataSize)) //Index is within socket storage        return 0;      CAsyncSocketEx *pSocket = pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;      if (!pSocket)        return 0;      // Process pending callbacks      std::list<t_callbackMsg> tmp;      tmp.swap(pSocket->m_pendingCallbacks);      pSocket->OnLayerCallback(tmp);    }    else if (message == WM_TIMER)    {      DebugAssert(pWnd);      if (wParam != 1)        return 0;      if (pWnd->m_pThreadData->layerCloseNotify.empty())      {        KillTimer(hWnd, 1);        return 0;      }      CAsyncSocketEx* socket = pWnd->m_pThreadData->layerCloseNotify.front();      pWnd->m_pThreadData->layerCloseNotify.pop_front();      if (pWnd->m_pThreadData->layerCloseNotify.empty())        KillTimer(hWnd, 1);      PostMessage(hWnd, socket->m_SocketData.nSocketIndex + WM_SOCKETEX_NOTIFY, socket->m_SocketData.hSocket, FD_CLOSE);      return 0;    }    return DefWindowProc(hWnd, message, wParam, lParam);  }  HWND GetHwnd()  {    return m_hWnd;  }private:  HWND m_hWnd;  struct t_AsyncSocketExWindowData  {    CAsyncSocketEx *m_pSocket;  } *m_pAsyncSocketExWindowData;  int m_nWindowDataSize;  int m_nWindowDataPos;  int m_nSocketCount;  CAsyncSocketEx::t_AsyncSocketExThreadData* m_pThreadData;};//////////////////////////////////////////////////////////////////////// Konstruktion/Destruktion//////////////////////////////////////////////////////////////////////CAsyncSocketEx::CAsyncSocketEx(){  m_SocketData.hSocket = INVALID_SOCKET;  m_SocketData.nSocketIndex = -1;  m_SocketData.nFamily = AF_UNSPEC;  m_SocketData.onCloseCalled = false;  m_pLocalAsyncSocketExThreadData = 0;  m_nPendingEvents = 0;  m_nState = notsock;  m_pFirstLayer = 0;  m_pLastLayer = 0;  m_lEvent = 0;  m_pAsyncGetHostByNameBuffer = NULL;  m_hAsyncGetHostByNameHandle = NULL;  m_nAsyncGetHostByNamePort = 0;  m_nSocketPort = 0;  m_lpszSocketAddress = 0;  m_SocketData.addrInfo = 0;  m_SocketData.nextAddr = 0;}CAsyncSocketEx::~CAsyncSocketEx(){  Close();  FreeAsyncSocketExInstance();}BOOL CAsyncSocketEx::Create(UINT nSocketPort /*=0*/, int nSocketType /*=SOCK_STREAM*/, long lEvent /*=FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/, LPCTSTR lpszSocketAddress /*=NULL*/, int nFamily /*=AF_INET*/){  DebugAssert(GetSocketHandle() == INVALID_SOCKET);  //Close the socket, although this should not happen  if (GetSocketHandle() != INVALID_SOCKET)  {    WSASetLastError(WSAEALREADY);    return FALSE;  }  BOOL res = InitAsyncSocketExInstance();  DebugAssert(res);  if (!res)  {    WSASetLastError(WSANOTINITIALISED);    return FALSE;  }  m_SocketData.nFamily = nFamily;  if (m_pFirstLayer)  {    BOOL res = m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress, nFamily);    if (res)    {      SetState(unconnected);    }    return res;  }  else  {    if (m_SocketData.nFamily == AF_UNSPEC)    {      SetState(unconnected);      m_lEvent = lEvent;      m_nSocketPort = nSocketPort;      delete [] m_lpszSocketAddress;      if (lpszSocketAddress && *lpszSocketAddress)      {        m_lpszSocketAddress = new TCHAR[_tcslen(lpszSocketAddress) + 1];        _tcscpy(m_lpszSocketAddress, lpszSocketAddress);      }      else        m_lpszSocketAddress = 0;      return TRUE;    }    else    {      SOCKET hSocket = socket(m_SocketData.nFamily, nSocketType, 0);      if (hSocket == INVALID_SOCKET)        return FALSE;      m_SocketData.hSocket = hSocket;      AttachHandle(hSocket);      if (m_pFirstLayer)      {        m_lEvent = lEvent;        if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) )        {          Close();          return FALSE;        }      }      else      {        if (!AsyncSelect(lEvent))        {          Close();          return FALSE;        }      }      if (!Bind(nSocketPort, lpszSocketAddress))      {        Close();        return FALSE;      }      SetState(unconnected);      return TRUE;    }  }}void CAsyncSocketEx::OnReceive(int nErrorCode){}void CAsyncSocketEx::OnSend(int nErrorCode){}void CAsyncSocketEx::OnConnect(int nErrorCode){}void CAsyncSocketEx::OnAccept(int nErrorCode){}void CAsyncSocketEx::OnClose(int nErrorCode){}BOOL CAsyncSocketEx::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress){  delete [] m_lpszSocketAddress;  if (lpszSocketAddress && *lpszSocketAddress)  {    m_lpszSocketAddress = new TCHAR[_tcslen(lpszSocketAddress) + 1];    _tcscpy(m_lpszSocketAddress, lpszSocketAddress);  }  else    m_lpszSocketAddress = 0;  m_nSocketPort = nSocketPort;  if (m_SocketData.nFamily == AF_UNSPEC)    return TRUE;  USES_CONVERSION;  LPSTR lpszAscii = (lpszSocketAddress && *lpszSocketAddress) ? T2A((LPTSTR)lpszSocketAddress) : 0;  if ((m_SocketData.nFamily == AF_INET6 || m_SocketData.nFamily == AF_INET) && lpszAscii)  {    addrinfo hints, *res0, *res;    int error;    char port[10];    BOOL ret = FALSE;    memset(&hints, 0, sizeof(addrinfo));    hints.ai_family = m_SocketData.nFamily;    hints.ai_socktype = SOCK_STREAM;    _snprintf(port, 9, "%lu", nSocketPort);    error = getaddrinfo(lpszAscii, port, &hints, &res0);    if (error)      return FALSE;    for (res = res0; res; res = res->ai_next)      if (Bind(res->ai_addr, res->ai_addrlen))      {        ret = TRUE;        break;      }      else        continue ;      freeaddrinfo(res0);      return ret ;  }  else if (!lpszAscii && m_SocketData.nFamily == AF_INET6)  {    SOCKADDR_IN6 sockAddr6;    memset(&sockAddr6, 0, sizeof(sockAddr6));    sockAddr6.sin6_family = AF_INET6 ;    sockAddr6.sin6_addr = in6addr_any ;    sockAddr6.sin6_port = htons((u_short)nSocketPort);    return Bind((SOCKADDR*)&sockAddr6, sizeof(sockAddr6));  }  else if (!lpszAscii && m_SocketData.nFamily == AF_INET)  {    SOCKADDR_IN sockAddr;    memset(&sockAddr, 0, sizeof(sockAddr));    sockAddr.sin_family = AF_INET ;    sockAddr.sin_addr.s_addr = INADDR_ANY ;    sockAddr.sin_port = htons((u_short)nSocketPort);    return Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr));  }  else    return FALSE ;}BOOL CAsyncSocketEx::Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen){  if (!bind(m_SocketData.hSocket, lpSockAddr, nSockAddrLen))    return TRUE;  else    return FALSE;}void CAsyncSocketEx::AttachHandle(SOCKET hSocket){  DebugAssert(m_pLocalAsyncSocketExThreadData);  DebugCheck(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->AddSocket(this, m_SocketData.nSocketIndex));  SetState(attached);}void CAsyncSocketEx::DetachHandle(SOCKET hSocket){  DebugAssert(m_pLocalAsyncSocketExThreadData);  if (!m_pLocalAsyncSocketExThreadData)    return;  DebugAssert(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);  if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)    return;  DebugCheck(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->RemoveSocket(this, m_SocketData.nSocketIndex));  SetState(notsock);}void CAsyncSocketEx::Close(){  m_nPendingEvents = 0;  if (m_pFirstLayer)    m_pFirstLayer->Close();  if (m_SocketData.hSocket != INVALID_SOCKET)  {    DebugCheck((closesocket(m_SocketData.hSocket) != SOCKET_ERROR));    DetachHandle(m_SocketData.hSocket);    m_SocketData.hSocket = INVALID_SOCKET;  }  if (m_SocketData.addrInfo)  {    freeaddrinfo(m_SocketData.addrInfo);    m_SocketData.addrInfo = 0;    m_SocketData.nextAddr = 0;  }  m_SocketData.nFamily = AF_UNSPEC;  delete [] m_lpszSocketAddress;  m_lpszSocketAddress = 0;  m_nSocketPort = 0;  RemoveAllLayers();  delete [] m_pAsyncGetHostByNameBuffer;  m_pAsyncGetHostByNameBuffer = NULL;  if (m_hAsyncGetHostByNameHandle)    WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle);  m_hAsyncGetHostByNameHandle = NULL;  m_SocketData.onCloseCalled = false;}BOOL CAsyncSocketEx::InitAsyncSocketExInstance(){  //Check if already initialized  if (m_pLocalAsyncSocketExThreadData)    return TRUE;  DWORD id=GetCurrentThreadId();  m_sGlobalCriticalSection.Lock();  //Get thread specific data  if (m_spAsyncSocketExThreadDataList)  {    t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;    while (pList)    {      DebugAssert(pList->pThreadData);      DebugAssert(pList->pThreadData->nInstanceCount>0);      if (pList->pThreadData->nThreadId==id)      {        m_pLocalAsyncSocketExThreadData=pList->pThreadData;        m_pLocalAsyncSocketExThreadData->nInstanceCount++;        break;      }      pList=pList->pNext;    }    //Current thread yet has no sockets    if (!pList)    {      //Initialize data for current thread      pList=new t_AsyncSocketExThreadDataList;      pList->pNext=m_spAsyncSocketExThreadDataList;      m_spAsyncSocketExThreadDataList=pList;      m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;      m_pLocalAsyncSocketExThreadData->nInstanceCount=1;      m_pLocalAsyncSocketExThreadData->nThreadId=id;      m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow(m_pLocalAsyncSocketExThreadData);      m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;    }  }  else  {  //No thread has instances of CAsyncSocketEx; Initialize data    m_spAsyncSocketExThreadDataList=new t_AsyncSocketExThreadDataList;    m_spAsyncSocketExThreadDataList->pNext=0;    m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;    m_pLocalAsyncSocketExThreadData->nInstanceCount=1;    m_pLocalAsyncSocketExThreadData->nThreadId=id;    m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow(m_pLocalAsyncSocketExThreadData);    m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;  }  m_sGlobalCriticalSection.Unlock();  return TRUE;}void CAsyncSocketEx::FreeAsyncSocketExInstance(){  //Check if already freed  if (!m_pLocalAsyncSocketExThreadData)    return;  for (std::list<CAsyncSocketEx*>::iterator iter = m_pLocalAsyncSocketExThreadData->layerCloseNotify.begin(); iter != m_pLocalAsyncSocketExThreadData->layerCloseNotify.end(); iter++)  {    if (*iter != this)      continue;    m_pLocalAsyncSocketExThreadData->layerCloseNotify.erase(iter);    if (m_pLocalAsyncSocketExThreadData->layerCloseNotify.empty())      KillTimer(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->GetHwnd(), 1);    break;  }  DWORD id=m_pLocalAsyncSocketExThreadData->nThreadId;  m_sGlobalCriticalSection.Lock();  DebugAssert(m_spAsyncSocketExThreadDataList);  t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;  t_AsyncSocketExThreadDataList *pPrev=0;  //Serach for data for current thread and decrease instance count  while (pList)  {    DebugAssert(pList->pThreadData);    DebugAssert(pList->pThreadData->nInstanceCount>0);    if (pList->pThreadData->nThreadId==id)    {      DebugAssert(m_pLocalAsyncSocketExThreadData==pList->pThreadData);      m_pLocalAsyncSocketExThreadData->nInstanceCount--;      //Freeing last instance?      //If so, destroy helper window      if (!m_pLocalAsyncSocketExThreadData->nInstanceCount)      {        delete m_pLocalAsyncSocketExThreadData->m_pHelperWindow;        delete m_pLocalAsyncSocketExThreadData;        if (pPrev)          pPrev->pNext=pList->pNext;        else          m_spAsyncSocketExThreadDataList=pList->pNext;        delete pList;        break;      }      break;    }    pPrev=pList;    pList=pList->pNext;    DebugAssert(pList);  }  m_sGlobalCriticalSection.Unlock();}int CAsyncSocketEx::Receive(void* lpBuf, int nBufLen, int nFlags /*=0*/){  if (m_pFirstLayer)    return m_pFirstLayer->Receive(lpBuf, nBufLen, nFlags);  else    return recv(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags);}int CAsyncSocketEx::Send(const void* lpBuf, int nBufLen, int nFlags /*=0*/){  if (m_pFirstLayer)  {    return m_pFirstLayer->Send(lpBuf, nBufLen, nFlags);  }  else  {    return send(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags);  }}BOOL CAsyncSocketEx::Connect(LPCTSTR lpszHostAddress, UINT nHostPort){  if (m_pFirstLayer)  {    BOOL res = m_pFirstLayer->Connect(lpszHostAddress, nHostPort);    if (res || GetLastError()==WSAEWOULDBLOCK)    {      SetState(connecting);    }    return res;  } else  if (m_SocketData.nFamily == AF_INET)  {    USES_CONVERSION;    DebugAssert(lpszHostAddress != NULL);    SOCKADDR_IN sockAddr;    memset(&sockAddr,0,sizeof(sockAddr));    LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);    sockAddr.sin_family = AF_INET;    sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);    if (sockAddr.sin_addr.s_addr == INADDR_NONE)    {      if (m_pAsyncGetHostByNameBuffer)        delete [] m_pAsyncGetHostByNameBuffer;      m_pAsyncGetHostByNameBuffer=new char[MAXGETHOSTSTRUCT];      m_nAsyncGetHostByNamePort=nHostPort;      m_hAsyncGetHostByNameHandle=WSAAsyncGetHostByName(GetHelperWindowHandle(), WM_USER+1, lpszAscii, m_pAsyncGetHostByNameBuffer, MAXGETHOSTSTRUCT);      if (!m_hAsyncGetHostByNameHandle)        return FALSE;      WSASetLastError(WSAEWOULDBLOCK);      SetState(connecting);      return FALSE;    }    sockAddr.sin_port = htons((u_short)nHostPort);    return CAsyncSocketEx::Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));  }  else  {    USES_CONVERSION;    DebugAssert( lpszHostAddress != NULL );    if (m_SocketData.addrInfo)    {      freeaddrinfo(m_SocketData.addrInfo);      m_SocketData.addrInfo = 0;      m_SocketData.nextAddr = 0;    }    addrinfo hints;    int error;    BOOL ret;    char port[10];    memset(&hints, 0, sizeof(addrinfo));    hints.ai_family = m_SocketData.nFamily;    hints.ai_socktype = SOCK_STREAM;    _snprintf(port, 9, "%lu", nHostPort);    error = getaddrinfo(T2CA(lpszHostAddress), port, &hints, &m_SocketData.addrInfo);    if (error)      return FALSE;    for (m_SocketData.nextAddr = m_SocketData.addrInfo; m_SocketData.nextAddr; m_SocketData.nextAddr = m_SocketData.nextAddr->ai_next)    {      bool newSocket = false;      if (m_SocketData.nFamily == AF_UNSPEC)      {        newSocket = true;        m_SocketData.hSocket = socket(m_SocketData.nextAddr->ai_family, m_SocketData.nextAddr->ai_socktype, m_SocketData.nextAddr->ai_protocol);        if (m_SocketData.hSocket == INVALID_SOCKET)          continue;        m_SocketData.nFamily = m_SocketData.nextAddr->ai_family;        AttachHandle(m_SocketData.hSocket);        if (!AsyncSelect(m_lEvent))        {          if (newSocket)          {            DetachHandle(m_SocketData.hSocket);            closesocket(m_SocketData.hSocket);            m_SocketData.hSocket = INVALID_SOCKET;          }          continue;        }      }      else if (m_SocketData.hSocket == INVALID_SOCKET)        continue;      if (m_pFirstLayer)      {        if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE))        {          if (newSocket)          {            m_SocketData.nFamily = AF_UNSPEC;            DetachHandle(m_SocketData.hSocket);            closesocket(m_SocketData.hSocket);            m_SocketData.hSocket = INVALID_SOCKET;          }          continue;        }      }      if (newSocket)      {        m_SocketData.nFamily = m_SocketData.nextAddr->ai_family;        if (!Bind(m_nSocketPort, m_lpszSocketAddress))        {          m_SocketData.nFamily = AF_UNSPEC;          DetachHandle(m_SocketData.hSocket);          closesocket(m_SocketData.hSocket);          m_SocketData.hSocket = INVALID_SOCKET;          continue;        }      }      if (!(ret = CAsyncSocketEx::Connect(m_SocketData.nextAddr->ai_addr, m_SocketData.nextAddr->ai_addrlen)) && GetLastError() != WSAEWOULDBLOCK)      {        if (newSocket)        {          m_SocketData.nFamily = AF_UNSPEC;          DetachHandle(m_SocketData.hSocket);          closesocket(m_SocketData.hSocket);          m_SocketData.hSocket = INVALID_SOCKET;        }        continue;      }      break;    }    if (m_SocketData.nextAddr)      m_SocketData.nextAddr = m_SocketData.nextAddr->ai_next;    if (!m_SocketData.nextAddr)    {      freeaddrinfo(m_SocketData.addrInfo);      m_SocketData.nextAddr = 0;      m_SocketData.addrInfo = 0;    }    if (m_SocketData.hSocket == INVALID_SOCKET || !ret)      return FALSE;    else      return TRUE;  }}BOOL CAsyncSocketEx::Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen){  BOOL res;  if (m_pFirstLayer)    res = SOCKET_ERROR!=m_pFirstLayer->Connect(lpSockAddr, nSockAddrLen);  else  {    ConfigureSocket();    res = SOCKET_ERROR!=connect(m_SocketData.hSocket, lpSockAddr, nSockAddrLen);  }  if (res || GetLastError()==WSAEWOULDBLOCK)  {    SetState(connecting);  }  return res;}BOOL CAsyncSocketEx::GetPeerName( CString& rPeerAddress, UINT& rPeerPort ){  if (m_pFirstLayer)    return m_pFirstLayer->GetPeerName(rPeerAddress, rPeerPort);  SOCKADDR* sockAddr;  int nSockAddrLen;  if (m_SocketData.nFamily == AF_INET6)  {    sockAddr = (SOCKADDR*)new SOCKADDR_IN6;    nSockAddrLen = sizeof(SOCKADDR_IN6);  }  else if (m_SocketData.nFamily == AF_INET)  {    sockAddr = (SOCKADDR*)new SOCKADDR_IN;    nSockAddrLen = sizeof(SOCKADDR_IN);  }  memset(sockAddr, 0, nSockAddrLen);  BOOL bResult = GetPeerName(sockAddr, &nSockAddrLen);  if (bResult)  {    if (m_SocketData.nFamily == AF_INET6)    {      rPeerPort = ntohs(((SOCKADDR_IN6*)sockAddr)->sin6_port);      LPTSTR buf = Inet6AddrToString(((SOCKADDR_IN6*)sockAddr)->sin6_addr);      rPeerAddress = buf;      delete [] buf;    }    else if (m_SocketData.nFamily == AF_INET)    {      rPeerPort = ntohs(((SOCKADDR_IN*)sockAddr)->sin_port);      rPeerAddress = inet_ntoa(((SOCKADDR_IN*)sockAddr)->sin_addr);    }    else    {      delete sockAddr;      return FALSE;    }  }  delete sockAddr;  return bResult;}BOOL CAsyncSocketEx::GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ){  if (m_pFirstLayer)    return m_pFirstLayer->GetPeerName(lpSockAddr, lpSockAddrLen);  if (!getpeername(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen))  {    return TRUE;  }  else  {    return FALSE;  }}BOOL CAsyncSocketEx::GetSockName(CString& rSocketAddress, UINT& rSocketPort){  SOCKADDR* sockAddr;  int nSockAddrLen;  if (m_SocketData.nFamily == AF_INET6)  {    sockAddr = (SOCKADDR*)new SOCKADDR_IN6;    nSockAddrLen = sizeof(SOCKADDR_IN6);  }  else if (m_SocketData.nFamily == AF_INET)  {    sockAddr = (SOCKADDR*)new SOCKADDR_IN;    nSockAddrLen = sizeof(SOCKADDR_IN);  }  memset(sockAddr, 0, nSockAddrLen);  BOOL bResult = GetSockName(sockAddr, &nSockAddrLen);  if (bResult)  {    if (m_SocketData.nFamily == AF_INET6)    {      rSocketPort = ntohs(((SOCKADDR_IN6*)sockAddr)->sin6_port);      LPTSTR buf = Inet6AddrToString(((SOCKADDR_IN6*)sockAddr)->sin6_addr);      rSocketAddress = buf;      delete [] buf;    }    else if (m_SocketData.nFamily == AF_INET)    {      rSocketPort = ntohs(((SOCKADDR_IN*)sockAddr)->sin_port);      rSocketAddress = inet_ntoa(((SOCKADDR_IN*)sockAddr)->sin_addr);    }    else    {      delete sockAddr;      return FALSE;    }  }  delete sockAddr;  return bResult;}BOOL CAsyncSocketEx::GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ){  if ( !getsockname(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) )    return TRUE;  else    return FALSE;}BOOL CAsyncSocketEx::ShutDown(int nHow /*=sends*/){  if (m_pFirstLayer)  {    return m_pFirstLayer->ShutDown();  }  else  {    if (!shutdown(m_SocketData.hSocket, nHow))      return TRUE;    else      return FALSE;  }}SOCKET CAsyncSocketEx::Detach(){  SOCKET socket = m_SocketData.hSocket;  DetachHandle(socket);  m_SocketData.hSocket = INVALID_SOCKET;  m_SocketData.nFamily = AF_UNSPEC;  return socket;}BOOL CAsyncSocketEx::Attach(SOCKET hSocket, long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/){  if (hSocket==INVALID_SOCKET || !hSocket)    return FALSE;  DebugCheck(InitAsyncSocketExInstance());  m_SocketData.hSocket=hSocket;  AttachHandle(hSocket);  if (m_pFirstLayer)  {    m_lEvent = lEvent;    return !WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);  }  else  {    return AsyncSelect(lEvent);  }}BOOL CAsyncSocketEx::AsyncSelect( long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ ){  DebugAssert(m_pLocalAsyncSocketExThreadData);  m_lEvent = lEvent;  if (m_pFirstLayer)    return TRUE;  else  {    if (m_SocketData.hSocket == INVALID_SOCKET && m_SocketData.nFamily == AF_UNSPEC)      return true;    if ( !WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, lEvent) )      return TRUE;    else      return FALSE;  }  return TRUE;}BOOL CAsyncSocketEx::Listen( int nConnectionBacklog /*=5*/ ){  if (m_pFirstLayer)    return m_pFirstLayer->Listen(nConnectionBacklog);  if (!listen(m_SocketData.hSocket, nConnectionBacklog))  {    SetState(listening);    return TRUE;  }  else    return FALSE;}BOOL CAsyncSocketEx::Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr /*=NULL*/, int* lpSockAddrLen /*=NULL*/ ){  DebugAssert(rConnectedSocket.m_SocketData.hSocket == INVALID_SOCKET);  if (m_pFirstLayer)  {    return m_pFirstLayer->Accept(rConnectedSocket, lpSockAddr, lpSockAddrLen);  }  else  {    SOCKET hTemp = accept(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen);    if (hTemp == INVALID_SOCKET)      return FALSE;    DebugCheck(rConnectedSocket.InitAsyncSocketExInstance());    rConnectedSocket.m_SocketData.hSocket=hTemp;    rConnectedSocket.AttachHandle(hTemp);    rConnectedSocket.SetFamily(GetFamily());    rConnectedSocket.SetState(connected);  }  return TRUE;}BOOL CAsyncSocketEx::IOCtl( long lCommand, DWORD* lpArgument ){  return ioctlsocket(m_SocketData.hSocket, lCommand, lpArgument) != SOCKET_ERROR;}int CAsyncSocketEx::GetLastError(){  return WSAGetLastError();}BOOL CAsyncSocketEx::TriggerEvent(long lEvent){  if (m_SocketData.hSocket==INVALID_SOCKET)    return FALSE;  DebugAssert(m_pLocalAsyncSocketExThreadData);  DebugAssert(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);  DebugAssert(m_SocketData.nSocketIndex!=-1);  if (m_pFirstLayer)  {    CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg = new CAsyncSocketExLayer::t_LayerNotifyMsg;    pMsg->hSocket = m_SocketData.hSocket;    pMsg->lEvent=lEvent%0xFFFF;    pMsg->pLayer=0;    BOOL res=PostMessage(GetHelperWindowHandle(), WM_USER, (WPARAM)m_SocketData.nSocketIndex, (LPARAM)pMsg);    if (!res)      delete pMsg;    return res;  }  else  {    return PostMessage(GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, m_SocketData.hSocket, lEvent%0xFFFF);  }}SOCKET CAsyncSocketEx::GetSocketHandle(){  return m_SocketData.hSocket;}HWND CAsyncSocketEx::GetHelperWindowHandle(){  if (!m_pLocalAsyncSocketExThreadData)    return 0;  if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)    return 0;  return m_pLocalAsyncSocketExThreadData->m_pHelperWindow->GetHwnd();}BOOL CAsyncSocketEx::AddLayer(CAsyncSocketExLayer *pLayer){  DebugAssert(pLayer);  if (m_pFirstLayer)  {    DebugAssert(m_pLastLayer);    m_pLastLayer=m_pLastLayer->AddLayer(pLayer, this);    return m_pLastLayer?TRUE:FALSE;  }  else  {    DebugAssert(!m_pLastLayer);    pLayer->Init(0, this);    m_pFirstLayer=pLayer;    m_pLastLayer=m_pFirstLayer;    if (m_SocketData.hSocket != INVALID_SOCKET)      if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE))        return FALSE;  }  return TRUE;}void CAsyncSocketEx::RemoveAllLayers(){  for (std::list<t_callbackMsg>::iterator iter = m_pendingCallbacks.begin(); iter != m_pendingCallbacks.end(); iter++)    delete [] iter->str;  m_pendingCallbacks.clear();  m_pFirstLayer = 0;  m_pLastLayer = 0;  if (!m_pLocalAsyncSocketExThreadData)    return;  if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)    return;  m_pLocalAsyncSocketExThreadData->m_pHelperWindow->RemoveLayers(this);}int CAsyncSocketEx::OnLayerCallback(std::list<t_callbackMsg>& callbacks){  for (std::list<t_callbackMsg>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++)  {    delete [] iter->str;  }  return 0;}BOOL CAsyncSocketEx::IsLayerAttached() const{  return m_pFirstLayer ? TRUE : FALSE;}BOOL CAsyncSocketEx::GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel /*=SOL_SOCKET*/){  return (SOCKET_ERROR != getsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen));}BOOL CAsyncSocketEx::SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel /*=SOL_SOCKET*/){  return (SOCKET_ERROR != setsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, nOptionLen));}int CAsyncSocketEx::GetState() const{  return m_nState;}void CAsyncSocketEx::SetState(int nState){  m_nState = nState;}const TCHAR * CAsyncSocketEx::GetStateDesc(int nState){  switch (nState)  {    case notsock:      return L"none";    case unconnected:      return L"unconnected";    case connecting:      return L"connecting";    case listening:      return L"listening";    case connected:      return L"connected";    case closed:      return L"closed";    case aborted:      return L"aborted";    case attached:      return L"attached";    default:      return L"unknown";  }}bool CAsyncSocketEx::LogStateChange(int nState1, int nState2){    return (nState2 != notsock) || (nState1 != unconnected);}int CAsyncSocketEx::GetFamily() const{  return m_SocketData.nFamily;}bool CAsyncSocketEx::SetFamily(int nFamily){  if (m_SocketData.nFamily != AF_UNSPEC)    return false;  m_SocketData.nFamily = nFamily;  return true;}bool CAsyncSocketEx::TryNextProtocol(){  DetachHandle(m_SocketData.hSocket);  closesocket(m_SocketData.hSocket);  m_SocketData.hSocket = INVALID_SOCKET;  BOOL ret = FALSE;  for (; m_SocketData.nextAddr; m_SocketData.nextAddr = m_SocketData.nextAddr->ai_next)  {    m_SocketData.hSocket = socket(m_SocketData.nextAddr->ai_family, m_SocketData.nextAddr->ai_socktype, m_SocketData.nextAddr->ai_protocol);    if (m_SocketData.hSocket == INVALID_SOCKET)      continue;    AttachHandle(m_SocketData.hSocket);    m_SocketData.nFamily = m_SocketData.nextAddr->ai_family;    if (!AsyncSelect(m_lEvent))    {      DetachHandle(m_SocketData.hSocket);      closesocket(m_SocketData.hSocket);      m_SocketData.hSocket = INVALID_SOCKET;      continue;    }    if (m_pFirstLayer)    {      if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE))      {        DetachHandle(m_SocketData.hSocket);        closesocket(m_SocketData.hSocket);        m_SocketData.hSocket = INVALID_SOCKET;        continue;      }    }    if (!Bind(m_nSocketPort, m_lpszSocketAddress))    {      DetachHandle(m_SocketData.hSocket);      closesocket(m_SocketData.hSocket);      m_SocketData.hSocket = INVALID_SOCKET;      continue;    }    ret = CAsyncSocketEx::Connect(m_SocketData.nextAddr->ai_addr, m_SocketData.nextAddr->ai_addrlen);    if (!ret && GetLastError() != WSAEWOULDBLOCK)    {      DetachHandle(m_SocketData.hSocket);      closesocket(m_SocketData.hSocket);      m_SocketData.hSocket = INVALID_SOCKET;      continue;    }    ret = true;    break;  }  if (m_SocketData.nextAddr)    m_SocketData.nextAddr = m_SocketData.nextAddr->ai_next;  if (!m_SocketData.nextAddr)  {    freeaddrinfo(m_SocketData.addrInfo);    m_SocketData.nextAddr = 0;    m_SocketData.addrInfo = 0;  }  if (m_SocketData.hSocket == INVALID_SOCKET || !ret)    return FALSE;  else    return TRUE;}void CAsyncSocketEx::AddCallbackNotification(const t_callbackMsg& msg){  m_pendingCallbacks.push_back(msg);  if(m_pendingCallbacks.size() == 1 && m_SocketData.nSocketIndex != -1)  {    PostMessage(GetHelperWindowHandle(), WM_USER + 2, (WPARAM)m_SocketData.nSocketIndex, 0);  }}void CAsyncSocketEx::ResendCloseNotify(){  for (std::list<CAsyncSocketEx*>::iterator iter = m_pLocalAsyncSocketExThreadData->layerCloseNotify.begin(); iter != m_pLocalAsyncSocketExThreadData->layerCloseNotify.end(); iter++)  {    if (*iter == this)      return;  }  m_pLocalAsyncSocketExThreadData->layerCloseNotify.push_back(this);  if (m_pLocalAsyncSocketExThreadData->layerCloseNotify.size() == 1)  {    SetTimer(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->GetHwnd(), 1, 10, 0);  }}
 |