Ticket #813: AsyncSocketEx.cpp

File AsyncSocketEx.cpp, 34.2 KB (added by binum, 19 years ago)
Line 
1/*CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de)
2 Version 1.3 (2003-04-26)
3--------------------------------------------------------
4
5Introduction:
6-------------
7
8CAsyncSocketEx is a replacement for the MFC class CAsyncSocket.
9This class was written because CAsyncSocket is not the fastest WinSock
10wrapper and it's very hard to add new functionality to CAsyncSocket
11derived classes. This class offers the same functionality as CAsyncSocket.
12Also, CAsyncSocketEx offers some enhancements which were not possible with
13CAsyncSocket without some tricks.
14
15How do I use it?
16----------------
17Basically exactly like CAsyncSocket.
18To use CAsyncSocketEx, just replace all occurrences of CAsyncSocket in your
19code with CAsyncSocketEx, if you did not enhance CAsyncSocket yourself in
20any way, you won't have to change anything else in your code.
21
22Why is CAsyncSocketEx faster?
23-----------------------------
24
25CAsyncSocketEx is slightly faster when dispatching notification event messages.
26First have a look at the way CAsyncSocket works. For each thread that uses
27CAsyncSocket, a window is created. CAsyncSocket calls WSAAsyncSelect with
28the handle of that window. Until here, CAsyncSocketEx works the same way.
29But CAsyncSocket uses only one window message (WM_SOCKET_NOTIFY) for all
30sockets within one thread. When the window recieve WM_SOCKET_NOTIFY, wParam
31contains the socket handle and the window looks up an CAsyncSocket instance
32using a map. CAsyncSocketEx works differently. It's helper window uses a
33wide range of different window messages (WM_USER through 0xBFFF) and passes
34a different message to WSAAsyncSelect for each socket. When a message in
35the specified range is received, CAsyncSocketEx looks up the pointer to a
36CAsyncSocketEx instance in an Array using the index of message - WM_USER.
37As you can see, CAsyncSocketEx uses the helper window in a more efficient
38way, as it don't have to use the slow maps to lookup it's own instance.
39Still, speed increase is not very much, but it may be noticeable when using
40a lot of sockets at the same time.
41Please note that the changes do not affect the raw data throughput rate,
42CAsyncSocketEx only dispatches the notification messages faster.
43
44What else does CAsyncSocketEx offer?
45------------------------------------
46
47CAsyncSocketEx offers a flexible layer system. One example is the proxy layer.
48Just create an instance of the proxy layer, configure it and add it to the layer
49chain of your CAsyncSocketEx instance. After that, you can connect through
50proxies.
51Benefit: You don't have to change much to use the layer system.
52Another layer that is currently in development is the SSL layer to establish
53SSL encrypted connections.
54
55License
56-------
57
58Feel free to use this class, as long as you don't claim that you wrote it
59and this copyright notice stays intact in the source files.
60If you use this class in commercial applications, please send a short message
61to tim.kosse@gmx.de
62*/
63
64#include "stdafx.h"
65#include "AsyncSocketEx.h"
66#include "wtypes.h"
67#include "oleauto.h"
68#include "atlconv.h"
69
70#ifndef NOLAYERS
71#include "AsyncSocketExLayer.h"
72#endif //NOLAYERS
73
74#ifdef _DEBUG
75#undef THIS_FILE
76static char THIS_FILE[]=__FILE__;
77#endif
78
79#ifndef CCRITICALSECTIONWRAPPERINCLUDED
80class CCriticalSectionWrapper
81{
82public:
83 CCriticalSectionWrapper()
84 {
85 m_bInitialized = TRUE;
86 InitializeCriticalSection(&m_criticalSection);
87 }
88
89 ~CCriticalSectionWrapper()
90 {
91 if (m_bInitialized)
92 DeleteCriticalSection(&m_criticalSection);
93 m_bInitialized = FALSE;
94 }
95
96 void Lock()
97 {
98 if (m_bInitialized)
99 EnterCriticalSection(&m_criticalSection);
100 }
101 void Unlock()
102 {
103 if (m_bInitialized)
104 LeaveCriticalSection(&m_criticalSection);
105 }
106protected:
107 CRITICAL_SECTION m_criticalSection;
108 BOOL m_bInitialized;
109};
110#define CCRITICALSECTIONWRAPPERINCLUDED
111#endif
112
113CCriticalSectionWrapper CAsyncSocketEx::m_sGlobalCriticalSection;
114CAsyncSocketEx::t_AsyncSocketExThreadDataList *CAsyncSocketEx::m_spAsyncSocketExThreadDataList=0;
115
116#ifndef _AFX
117#ifndef VERIFY
118#define VERIFY(x) (void(x))
119#endif //VERIFY
120#ifndef ASSERT
121#define ASSERT(x)
122#endif //ASSERT
123#endif //_AFX
124
125/////////////////////////////
126//Helper Window class
127#define WM_SOCKETEX_NOTIFY (WM_USER+2)
128#define MAX_SOCKETS (0xBFFF-WM_SOCKETEX_NOTIFY+1)
129
130class CAsyncSocketExHelperWindow
131{
132public:
133 CAsyncSocketExHelperWindow()
134 {
135 //Initialize data
136 m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets
137 memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));
138 m_nWindowDataSize=512;
139 m_nSocketCount=0;
140 m_nWindowDataPos=0;
141
142 //Create window
143 WNDCLASSEX wndclass;
144 wndclass.cbSize=sizeof wndclass;
145 wndclass.style=0;
146 wndclass.lpfnWndProc=WindowProc;
147 wndclass.cbClsExtra=0;
148 wndclass.cbWndExtra=0;
149 wndclass.hInstance=GetModuleHandle(0);
150 wndclass.hIcon=0;
151 wndclass.hCursor=0;
152 wndclass.hbrBackground=0;
153 wndclass.lpszMenuName=0;
154 wndclass.lpszClassName=_T("CAsyncSocketEx Helper Window");
155 wndclass.hIconSm=0;
156
157 RegisterClassEx(&wndclass);
158
159 m_hWnd=CreateWindow(_T("CAsyncSocketEx Helper Window"), _T("CAsyncSocketEx Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
160 ASSERT(m_hWnd);
161 SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);
162 };
163
164 virtual ~CAsyncSocketExHelperWindow()
165 {
166 //Clean up socket storage
167 delete [] m_pAsyncSocketExWindowData;
168 m_pAsyncSocketExWindowData=0;
169 m_nWindowDataSize=0;
170 m_nSocketCount=0;
171
172 //Destroy window
173 if (m_hWnd)
174 {
175 DestroyWindow(m_hWnd);
176 m_hWnd=0;
177 }
178 }
179
180 //Adds a socket to the list of attached sockets
181 BOOL AddSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
182 {
183 ASSERT(pSocket);
184 if (!m_nWindowDataSize)
185 {
186 ASSERT(!m_nSocketCount);
187 m_nWindowDataSize=512;
188 m_pAsyncSocketExWindowData=new t_AsyncSocketExWindowData[512]; //Reserve space for 512 active sockets
189 memset(m_pAsyncSocketExWindowData, 0, 512*sizeof(t_AsyncSocketExWindowData));
190 }
191
192 if (nSocketIndex!=-1)
193 {
194 ASSERT(m_pAsyncSocketExWindowData);
195 ASSERT(m_nWindowDataSize>nSocketIndex);
196 ASSERT(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket);
197 ASSERT(m_nSocketCount);
198 return TRUE;
199 }
200
201 //Increase socket storage if too small
202 if (m_nSocketCount>=(m_nWindowDataSize-10))
203 {
204 int nOldWindowDataSize=m_nWindowDataSize;
205 ASSERT(m_nWindowDataSize<MAX_SOCKETS);
206 m_nWindowDataSize+=512;
207 if (m_nWindowDataSize>MAX_SOCKETS)
208 m_nWindowDataSize=MAX_SOCKETS;
209 t_AsyncSocketExWindowData *tmp=m_pAsyncSocketExWindowData;
210 m_pAsyncSocketExWindowData = new t_AsyncSocketExWindowData[m_nWindowDataSize];
211 memcpy(m_pAsyncSocketExWindowData, tmp, nOldWindowDataSize * sizeof(t_AsyncSocketExWindowData));
212 memset(m_pAsyncSocketExWindowData+nOldWindowDataSize, 0, (m_nWindowDataSize-nOldWindowDataSize)*sizeof(t_AsyncSocketExWindowData));
213 delete [] tmp;
214 }
215
216 //Search for free slot
217 for (int i=m_nWindowDataPos;i<(m_nWindowDataSize+m_nWindowDataPos);i++)
218 {
219 if (!m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket)
220 {
221 m_pAsyncSocketExWindowData[i%m_nWindowDataSize].m_pSocket=pSocket;
222 nSocketIndex=i%m_nWindowDataSize;
223 m_nWindowDataPos=(i+1)%m_nWindowDataSize;
224 m_nSocketCount++;
225 return TRUE;
226 }
227 }
228
229 //No slot found, maybe there are too much sockets!
230 return FALSE;
231 }
232
233 //Removes a socket from the socket storage
234 BOOL RemoveSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
235 {
236 ASSERT(pSocket);
237 if (nSocketIndex==-1)
238 return TRUE;
239
240 ASSERT(m_pAsyncSocketExWindowData);
241 ASSERT(m_nWindowDataSize>0);
242 ASSERT(m_nSocketCount>0);
243 ASSERT(m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket==pSocket);
244 m_pAsyncSocketExWindowData[nSocketIndex].m_pSocket=0;
245 nSocketIndex=-1;
246 m_nSocketCount--;
247
248 return TRUE;
249 }
250
251 //Processes event notifications sent by the sockets or the layers
252 static LRESULT CALLBACK WindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
253 {
254 if (message>=WM_SOCKETEX_NOTIFY)
255 {
256 //Verify parameters
257 ASSERT(hWnd);
258 CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
259 ASSERT(pWnd);
260
261 if (message<static_cast<UINT>(WM_SOCKETEX_NOTIFY+pWnd->m_nWindowDataSize)) //Index is within socket storage
262 {
263 //Lookup socket and verify if it's valid
264 CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[message-WM_SOCKETEX_NOTIFY].m_pSocket;
265 SOCKET hSocket=wParam;
266 if (!pSocket)
267 return 0;
268 if (hSocket==INVALID_SOCKET)
269 return 0;
270 if (pSocket->m_SocketData.hSocket!=hSocket)
271 return 0;
272
273 int nEvent=lParam&0xFFFF;
274 int nErrorCode=lParam>>16;
275
276 //Dispatch notification
277#ifndef NOLAYERS
278 if (!pSocket->m_pFirstLayer)
279 {
280#endif //NOLAYERS
281 //Dispatch to CAsyncSocketEx instance
282 switch (nEvent)
283 {
284 case FD_READ:
285#ifndef NOSOCKETSTATES
286 if (pSocket->GetState() == connecting && !nErrorCode)
287 {
288 pSocket->m_nPendingEvents |= FD_READ;
289 break;
290 }
291 else if (pSocket->GetState() == attached)
292 pSocket->SetState(connected);
293 if (pSocket->GetState() != connected)
294 break;
295#endif //NOSOCKETSTATES
296
297 if (pSocket->m_lEvent & FD_READ)
298 {
299 DWORD nBytes = 0;
300 if (!nErrorCode)
301 if (!pSocket->IOCtl(FIONREAD, &nBytes))
302 nErrorCode = WSAGetLastError();
303#ifndef NOSOCKETSTATES
304 if (nErrorCode)
305 pSocket->SetState(aborted);
306#endif //NOSOCKETSTATES
307 if (nBytes != 0 || nErrorCode != 0)
308 pSocket->OnReceive(nErrorCode);
309 }
310 break;
311 case FD_FORCEREAD: //Forceread does not check if there's data waiting
312#ifndef NOSOCKETSTATES
313 if (pSocket->GetState() == connecting && !nErrorCode)
314 {
315 pSocket->m_nPendingEvents |= FD_FORCEREAD;
316 break;
317 }
318 else if (pSocket->GetState() == attached)
319 pSocket->SetState(connected);
320 if (pSocket->GetState() != connected)
321 break;
322#endif //NOSOCKETSTATES
323 if (pSocket->m_lEvent & FD_READ)
324 {
325#ifndef NOSOCKETSTATES
326 if (nErrorCode)
327 pSocket->SetState(aborted);
328#endif //NOSOCKETSTATES
329 pSocket->OnReceive(nErrorCode);
330 }
331 break;
332 case FD_WRITE:
333#ifndef NOSOCKETSTATES
334 if (pSocket->GetState() == connecting && !nErrorCode)
335 {
336 pSocket->m_nPendingEvents |= FD_WRITE;
337 break;
338 }
339 else if (pSocket->GetState() == attached && !nErrorCode)
340 pSocket->SetState(connected);
341 if (pSocket->GetState() != connected)
342 break;
343#endif //NOSOCKETSTATES
344 if (pSocket->m_lEvent & FD_WRITE)
345 {
346#ifndef NOSOCKETSTATES
347 if (nErrorCode)
348 pSocket->SetState(aborted);
349#endif //NOSOCKETSTATES
350 pSocket->OnSend(nErrorCode);
351 }
352 break;
353 case FD_CONNECT:
354#ifndef NOSOCKETSTATES
355 if (pSocket->GetState() == connecting)
356 pSocket->SetState(connected);
357 else if (pSocket->GetState() == attached && !nErrorCode)
358 pSocket->SetState(connected);
359#endif //NOSOCKETSTATES
360 if (pSocket->m_lEvent & FD_CONNECT)
361 pSocket->OnConnect(nErrorCode);
362#ifndef NOSOCKETSTATES
363 if (!nErrorCode)
364 {
365 if ((pSocket->m_nPendingEvents&FD_READ) && pSocket->GetState() == connected)
366 pSocket->OnReceive(0);
367 if ((pSocket->m_nPendingEvents&FD_FORCEREAD) && pSocket->GetState() == connected)
368 pSocket->OnReceive(0);
369 if ((pSocket->m_nPendingEvents&FD_WRITE) && pSocket->GetState() == connected)
370 pSocket->OnSend(0);
371 }
372 pSocket->m_nPendingEvents = 0;
373#endif
374 break;
375 case FD_ACCEPT:
376#ifndef NOSOCKETSTATES
377 if (pSocket->GetState() != listening && pSocket->GetState() != attached)
378 break;
379#endif //NOSOCKETSTATES
380 if (pSocket->m_lEvent & FD_ACCEPT)
381 pSocket->OnAccept(nErrorCode);
382 break;
383 case FD_CLOSE:
384#ifndef NOSOCKETSTATES
385 if (pSocket->GetState() != connected && pSocket->GetState() != attached)
386 break;
387 pSocket->SetState(nErrorCode?aborted:closed);
388#endif //NOSOCKETSTATES
389 pSocket->OnClose(nErrorCode);
390 break;
391 }
392 }
393#ifndef NOLAYERS
394 else //Dispatch notification to the lowest layer
395 {
396 if (nEvent==FD_READ)
397 {
398 DWORD nBytes;
399 if (!pSocket->IOCtl(FIONREAD, &nBytes))
400 nErrorCode = WSAGetLastError();
401 if (nBytes != 0 || nErrorCode != 0)
402 pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
403 }
404 else
405 pSocket->m_pLastLayer->CallEvent(nEvent, nErrorCode);
406 }
407 }
408#endif //NOLAYERS
409 return 0;
410 }
411#ifndef NOLAYERS
412 else if (message==WM_USER) //Notification event sent by a layer
413 {
414 //Verify parameters, lookup socket and notification message
415 //Verify parameters
416 ASSERT(hWnd);
417 CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
418 ASSERT(pWnd);
419
420 if (wParam>=static_cast<UINT>(pWnd->m_nWindowDataSize)) //Index is within socket storage
421 {
422 return 0;
423 }
424
425 CAsyncSocketEx *pSocket=pWnd->m_pAsyncSocketExWindowData[wParam].m_pSocket;
426 CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg=(CAsyncSocketExLayer::t_LayerNotifyMsg *)lParam;
427 if (!pMsg || !pSocket || pSocket->m_SocketData.hSocket != pMsg->hSocket)
428 {
429 delete pMsg;
430 return 0;
431 }
432 int nEvent=pMsg->lEvent&0xFFFF;
433 int nErrorCode=pMsg->lEvent>>16;
434
435 //Dispatch to layer
436 if (pMsg->pLayer)
437 pMsg->pLayer->CallEvent(nEvent, nErrorCode);
438 else
439 {
440 //Dispatch to CAsyncSocketEx instance
441 switch (nEvent)
442 {
443 case FD_READ:
444#ifndef NOSOCKETSTATES
445 if (pSocket->GetState() == connecting && !nErrorCode)
446 {
447 pSocket->m_nPendingEvents |= FD_READ;
448 break;
449 }
450 else if (pSocket->GetState() == attached && !nErrorCode)
451 pSocket->SetState(connected);
452 if (pSocket->GetState() != connected)
453 break;
454#endif //NOSOCKETSTATES
455 if (pSocket->m_lEvent & FD_READ)
456 {
457#ifndef NOSOCKETSTATES
458 if (nErrorCode)
459 pSocket->SetState(aborted);
460#endif //NOSOCKETSTATES
461 pSocket->OnReceive(nErrorCode);
462 }
463 break;
464 case FD_FORCEREAD: //Forceread does not check if there's data waiting
465#ifndef NOSOCKETSTATES
466 if (pSocket->GetState() == connecting && !nErrorCode)
467 {
468 pSocket->m_nPendingEvents |= FD_FORCEREAD;
469 break;
470 }
471 else if (pSocket->GetState() == attached && !nErrorCode)
472 pSocket->SetState(connected);
473 if (pSocket->GetState() != connected)
474 break;
475#endif //NOSOCKETSTATES
476 if (pSocket->m_lEvent & FD_READ)
477 {
478#ifndef NOSOCKETSTATES
479 if (nErrorCode)
480 pSocket->SetState(aborted);
481#endif //NOSOCKETSTATES
482 pSocket->OnReceive(nErrorCode);
483 }
484 break;
485 case FD_WRITE:
486#ifndef NOSOCKETSTATES
487 if (pSocket->GetState() == connecting && !nErrorCode)
488 {
489 pSocket->m_nPendingEvents |= FD_WRITE;
490 break;
491 }
492 else if (pSocket->GetState() == attached && !nErrorCode)
493 pSocket->SetState(connected);
494 if (pSocket->GetState() != connected)
495 break;
496#endif //NOSOCKETSTATES
497 if (pSocket->m_lEvent & FD_WRITE)
498 {
499#ifndef NOSOCKETSTATES
500 if (nErrorCode)
501 pSocket->SetState(aborted);
502#endif //NOSOCKETSTATES
503 pSocket->OnSend(nErrorCode);
504 }
505 break;
506 case FD_CONNECT:
507#ifndef NOSOCKETSTATES
508 if (pSocket->GetState() == connecting)
509 pSocket->SetState(connected);
510 else if (pSocket->GetState() == attached && !nErrorCode)
511 pSocket->SetState(connected);
512#endif //NOSOCKETSTATES
513 if (pSocket->m_lEvent & FD_CONNECT)
514 pSocket->OnConnect(nErrorCode);
515#ifndef NOSOCKETSTATES
516 if (!nErrorCode)
517 {
518 if (((pSocket->m_nPendingEvents&FD_READ) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_READ))
519 pSocket->OnReceive(0);
520 if (((pSocket->m_nPendingEvents&FD_FORCEREAD) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_READ))
521 pSocket->OnReceive(0);
522 if (((pSocket->m_nPendingEvents&FD_WRITE) && pSocket->GetState() == connected) && (pSocket->m_lEvent & FD_WRITE))
523 pSocket->OnSend(0);
524 }
525 pSocket->m_nPendingEvents = 0;
526#endif //NOSOCKETSTATES
527 break;
528 case FD_ACCEPT:
529#ifndef NOSOCKETSTATES
530 if ((pSocket->GetState() == listening || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_ACCEPT))
531#endif //NOSOCKETSTATES
532 {
533 pSocket->OnAccept(nErrorCode);
534 }
535 break;
536 case FD_CLOSE:
537#ifndef NOSOCKETSTATES
538 if ((pSocket->GetState() == connected || pSocket->GetState() == attached) && (pSocket->m_lEvent & FD_CLOSE))
539 {
540 pSocket->SetState(nErrorCode?aborted:closed);
541#else
542 {
543#endif //NOSOCKETSTATES
544 pSocket->OnClose(nErrorCode);
545 }
546 break;
547 }
548 }
549 delete pMsg;
550 return 0;
551 }
552#endif //NOLAYERS
553 else if (message == WM_USER+1)
554 {
555 //WSAAsyncGetHostByName reply
556
557 //Verify parameters
558 ASSERT(hWnd);
559 CAsyncSocketExHelperWindow *pWnd=(CAsyncSocketExHelperWindow *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
560 ASSERT(pWnd);
561
562 CAsyncSocketEx *pSocket = NULL;
563 for (int i=0; i<pWnd->m_nWindowDataSize; i++)
564 {
565 pSocket = pWnd->m_pAsyncSocketExWindowData[i].m_pSocket;
566 if (pSocket && pSocket->m_hAsyncGetHostByNameHandle &&
567 pSocket->m_hAsyncGetHostByNameHandle == (HANDLE)wParam)
568 break;
569 }
570 if (!pSocket)
571 return 0;
572
573 int nErrorCode = lParam >> 16;
574 if (nErrorCode)
575 {
576 pSocket->OnConnect(nErrorCode);
577 return 0;
578 }
579
580 SOCKADDR_IN sockAddr;
581 memset(&sockAddr,0,sizeof(sockAddr));
582 sockAddr.sin_family=AF_INET;
583 sockAddr.sin_addr.s_addr = ((LPIN_ADDR)((LPHOSTENT)pSocket->m_pAsyncGetHostByNameBuffer)->h_addr)->s_addr;
584
585 sockAddr.sin_port = htons(pSocket->m_nAsyncGetHostByNamePort);
586
587 BOOL res = pSocket->Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
588 delete [] pSocket->m_pAsyncGetHostByNameBuffer;
589 pSocket->m_pAsyncGetHostByNameBuffer=0;
590 pSocket->m_hAsyncGetHostByNameHandle=0;
591
592 if (!res)
593 if (GetLastError()!=WSAEWOULDBLOCK)
594 pSocket->OnConnect(GetLastError());
595 return 0;
596 }
597 return DefWindowProc(hWnd, message, wParam, lParam);
598 }
599
600 HWND CAsyncSocketExHelperWindow::GetHwnd()
601 {
602 return m_hWnd;
603 }
604
605private:
606 HWND m_hWnd;
607 struct t_AsyncSocketExWindowData
608 {
609 CAsyncSocketEx *m_pSocket;
610 } *m_pAsyncSocketExWindowData;
611 int m_nWindowDataSize;
612 int m_nWindowDataPos;
613 int m_nSocketCount;
614};
615
616//////////////////////////////////////////////////////////////////////
617// Konstruktion/Destruktion
618//////////////////////////////////////////////////////////////////////
619
620CAsyncSocketEx::CAsyncSocketEx()
621{
622 m_SocketData.hSocket=INVALID_SOCKET;
623 m_SocketData.nSocketIndex=-1;
624 m_pLocalAsyncSocketExThreadData=0;
625
626#ifndef NOSOCKETSTATES
627 m_nPendingEvents = 0;
628 m_nState = notsock;
629#endif //NOSOCKETSTATES
630
631#ifndef NOLAYERS
632 m_pFirstLayer=0;
633 m_pLastLayer=0;
634#endif //NOLAYERS
635 m_pAsyncGetHostByNameBuffer = NULL;
636 m_hAsyncGetHostByNameHandle = NULL;
637}
638
639CAsyncSocketEx::~CAsyncSocketEx()
640{
641 Close();
642 FreeAsyncSocketExInstance();
643}
644
645BOOL 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*/ )
646{
647 ASSERT(GetSocketHandle()==INVALID_SOCKET);
648
649 //Close the socket, although this should not happen
650 if (GetSocketHandle() != INVALID_SOCKET)
651 {
652 WSASetLastError(WSAEALREADY);
653 return FALSE;
654 }
655
656 BOOL res=InitAsyncSocketExInstance();
657 ASSERT(res);
658 if (!res)
659 {
660 WSASetLastError(WSANOTINITIALISED);
661 return FALSE;
662 }
663
664#ifndef NOLAYERS
665 if (m_pFirstLayer)
666 {
667 BOOL res = m_pFirstLayer->Create(nSocketPort, nSocketType, lEvent, lpszSocketAddress);
668#ifndef NOSOCKETSTATES
669 if (res)
670 SetState(unconnected);
671#endif //NOSOCKETSTATES
672 return res;
673 }
674 else
675#endif //NOLAYERS
676 {
677 SOCKET hSocket=socket(AF_INET, nSocketType, 0);
678 if (hSocket==INVALID_SOCKET)
679 return FALSE;
680 m_SocketData.hSocket=hSocket;
681 AttachHandle(hSocket);
682
683#ifndef NOLAYERS
684 if (m_pFirstLayer)
685 {
686 m_lEvent = lEvent;
687 if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE) )
688 {
689 Close();
690 return FALSE;
691 }
692 }
693 else
694#endif //NOLAYERS
695 {
696 if (!AsyncSelect(lEvent))
697 {
698 Close();
699 return FALSE;
700 }
701 }
702
703 if (!Bind(nSocketPort, lpszSocketAddress))
704 {
705 Close();
706 return FALSE;
707 }
708
709#ifndef NOSOCKETSTATES
710 SetState(unconnected);
711#endif //NOSOCKETSTATES
712
713 return TRUE;
714 }
715}
716
717
718
719void CAsyncSocketEx::OnReceive(int nErrorCode)
720{
721}
722
723void CAsyncSocketEx::OnSend(int nErrorCode)
724{
725}
726
727void CAsyncSocketEx::OnConnect(int nErrorCode)
728{
729}
730
731void CAsyncSocketEx::OnAccept(int nErrorCode)
732{
733}
734
735void CAsyncSocketEx::OnClose(int nErrorCode)
736{
737}
738
739BOOL CAsyncSocketEx::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress)
740{
741 USES_CONVERSION;
742
743 SOCKADDR_IN sockAddr;
744 memset(&sockAddr,0,sizeof(sockAddr));
745
746 LPSTR lpszAscii = T2A((LPTSTR)lpszSocketAddress);
747 sockAddr.sin_family = AF_INET;
748
749 if (lpszAscii == NULL)
750 sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
751 else
752 {
753 DWORD lResult = inet_addr(lpszAscii);
754 if (lResult == INADDR_NONE)
755 {
756 WSASetLastError(WSAEINVAL);
757 return FALSE;
758 }
759 sockAddr.sin_addr.s_addr = lResult;
760 }
761
762 sockAddr.sin_port = htons((u_short)nSocketPort);
763
764 return Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr));
765}
766
767BOOL CAsyncSocketEx::Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen)
768{
769 int window_size = 128 * 1024; /* 128 kilobytes */
770
771 setsockopt(m_SocketData.hSocket, SOL_SOCKET, SO_SNDBUF, (char *) &window_size, sizeof(window_size));
772
773 setsockopt(m_SocketData.hSocket, SOL_SOCKET, SO_RCVBUF, (char *) &window_size, sizeof(window_size));
774
775 if (!bind(m_SocketData.hSocket, lpSockAddr, nSockAddrLen))
776 return TRUE;
777 else
778 return FALSE;
779}
780
781void CAsyncSocketEx::AttachHandle(SOCKET hSocket)
782{
783 ASSERT(m_pLocalAsyncSocketExThreadData);
784 VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->AddSocket(this, m_SocketData.nSocketIndex));
785#ifndef NOSOCKETSTATES
786 SetState(attached);
787#endif //NOSOCKETSTATES
788}
789
790void CAsyncSocketEx::DetachHandle(SOCKET hSocket)
791{
792 ASSERT(m_pLocalAsyncSocketExThreadData);
793 if (!m_pLocalAsyncSocketExThreadData)
794 return;
795 ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);
796 if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)
797 return;
798 VERIFY(m_pLocalAsyncSocketExThreadData->m_pHelperWindow->RemoveSocket(this, m_SocketData.nSocketIndex));
799#ifndef NOSOCKETSTATES
800 SetState(notsock);
801#endif //NOSOCKETSTATES
802}
803
804void CAsyncSocketEx::Close()
805{
806#ifndef NOSOCKETSTATES
807 m_nPendingEvents = 0;
808#endif //NOSOCKETSTATES
809#ifndef NOLAYERS
810 if (m_pFirstLayer)
811 m_pFirstLayer->Close();
812#endif //NOLAYERS
813 if (m_SocketData.hSocket != INVALID_SOCKET)
814 {
815 VERIFY(closesocket(m_SocketData.hSocket)!=SOCKET_ERROR);
816 DetachHandle(m_SocketData.hSocket);
817 m_SocketData.hSocket = INVALID_SOCKET;
818 }
819#ifndef NOLAYERS
820 RemoveAllLayers();
821#endif //NOLAYERS
822 delete [] m_pAsyncGetHostByNameBuffer;
823 m_pAsyncGetHostByNameBuffer = NULL;
824 if (m_hAsyncGetHostByNameHandle)
825 WSACancelAsyncRequest(m_hAsyncGetHostByNameHandle);
826 m_hAsyncGetHostByNameHandle = NULL;
827}
828
829BOOL CAsyncSocketEx::InitAsyncSocketExInstance()
830{
831 //Check if already initialized
832 if (m_pLocalAsyncSocketExThreadData)
833 return TRUE;
834
835 DWORD id=GetCurrentThreadId();
836
837 m_sGlobalCriticalSection.Lock();
838
839 //Get thread specific data
840 if (m_spAsyncSocketExThreadDataList)
841 {
842 t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;
843 while (pList)
844 {
845 ASSERT(pList->pThreadData);
846 ASSERT(pList->pThreadData->nInstanceCount>0);
847
848 if (pList->pThreadData->nThreadId==id)
849 {
850 m_pLocalAsyncSocketExThreadData=pList->pThreadData;
851 m_pLocalAsyncSocketExThreadData->nInstanceCount++;
852 break;
853 }
854 pList=pList->pNext;
855 }
856 //Current thread yet has no sockets
857 if (!pList)
858 {
859 //Initialize data for current thread
860 pList=new t_AsyncSocketExThreadDataList;
861 pList->pNext=m_spAsyncSocketExThreadDataList;
862 m_spAsyncSocketExThreadDataList=pList;
863 m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;
864 m_pLocalAsyncSocketExThreadData->nInstanceCount=1;
865 m_pLocalAsyncSocketExThreadData->nThreadId=id;
866 m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow;
867 m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;
868 }
869 }
870 else
871 { //No thread has instances of CAsyncSocketEx; Initialize data
872 m_spAsyncSocketExThreadDataList=new t_AsyncSocketExThreadDataList;
873 m_spAsyncSocketExThreadDataList->pNext=0;
874 m_pLocalAsyncSocketExThreadData=new t_AsyncSocketExThreadData;
875 m_pLocalAsyncSocketExThreadData->nInstanceCount=1;
876 m_pLocalAsyncSocketExThreadData->nThreadId=id;
877 m_pLocalAsyncSocketExThreadData->m_pHelperWindow=new CAsyncSocketExHelperWindow;
878 m_spAsyncSocketExThreadDataList->pThreadData=m_pLocalAsyncSocketExThreadData;
879 }
880 m_sGlobalCriticalSection.Unlock();
881 return TRUE;
882}
883
884void CAsyncSocketEx::FreeAsyncSocketExInstance()
885{
886 //Check if already freed
887 if (!m_pLocalAsyncSocketExThreadData)
888 return;
889
890 DWORD id=m_pLocalAsyncSocketExThreadData->nThreadId;
891 m_sGlobalCriticalSection.Lock();
892
893 ASSERT(m_spAsyncSocketExThreadDataList);
894 t_AsyncSocketExThreadDataList *pList=m_spAsyncSocketExThreadDataList;
895 t_AsyncSocketExThreadDataList *pPrev=0;
896
897 //Serach for data for current thread and decrease instance count
898 while (pList)
899 {
900 ASSERT(pList->pThreadData);
901 ASSERT(pList->pThreadData->nInstanceCount>0);
902
903 if (pList->pThreadData->nThreadId==id)
904 {
905 ASSERT(m_pLocalAsyncSocketExThreadData==pList->pThreadData);
906 m_pLocalAsyncSocketExThreadData->nInstanceCount--;
907
908 //Freeing last instance?
909 //If so, destroy helper window
910 if (!m_pLocalAsyncSocketExThreadData->nInstanceCount)
911 {
912 delete m_pLocalAsyncSocketExThreadData->m_pHelperWindow;
913 delete m_pLocalAsyncSocketExThreadData;
914 if (pPrev)
915 pPrev->pNext=pList->pNext;
916 else
917 m_spAsyncSocketExThreadDataList=pList->pNext;
918 delete pList;
919 break;
920 }
921
922 break;
923 }
924 pPrev=pList;
925 pList=pList->pNext;
926 ASSERT(pList);
927 }
928
929 m_sGlobalCriticalSection.Unlock();
930}
931
932int CAsyncSocketEx::Receive(void* lpBuf, int nBufLen, int nFlags /*=0*/)
933{
934#ifndef NOLAYERS
935 if (m_pFirstLayer)
936 return m_pFirstLayer->Receive(lpBuf, nBufLen, nFlags);
937 else
938#endif //NOLAYERS
939 return recv(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
940}
941
942
943int CAsyncSocketEx::Send(const void* lpBuf, int nBufLen, int nFlags /*=0*/)
944{
945#ifndef NOLAYERS
946 if (m_pFirstLayer)
947 return m_pFirstLayer->Send(lpBuf, nBufLen, nFlags);
948 else
949#endif //NOLAYERS
950 return send(m_SocketData.hSocket, (LPSTR)lpBuf, nBufLen, nFlags);
951}
952
953BOOL CAsyncSocketEx::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
954{
955#ifndef NOLAYERS
956 if (m_pFirstLayer)
957 {
958 BOOL res = m_pFirstLayer->Connect(lpszHostAddress, nHostPort);
959#ifndef NOSOCKETSTATES
960 if (res || GetLastError()==WSAEWOULDBLOCK)
961 SetState(connecting);
962#endif //NOSOCKETSTATES
963 return res;
964 }
965 else
966#endif //NOLAYERS
967 {
968 USES_CONVERSION;
969
970 ASSERT(lpszHostAddress != NULL);
971
972 SOCKADDR_IN sockAddr;
973 memset(&sockAddr,0,sizeof(sockAddr));
974
975 LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);
976 sockAddr.sin_family = AF_INET;
977 sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
978
979 if (sockAddr.sin_addr.s_addr == INADDR_NONE)
980 {
981 m_pAsyncGetHostByNameBuffer=new char[MAXGETHOSTSTRUCT];
982
983 m_nAsyncGetHostByNamePort=nHostPort;
984
985 m_hAsyncGetHostByNameHandle=WSAAsyncGetHostByName(GetHelperWindowHandle(), WM_USER+1, lpszAscii, m_pAsyncGetHostByNameBuffer, MAXGETHOSTSTRUCT);
986 if (!m_hAsyncGetHostByNameHandle)
987 return FALSE;
988
989 WSASetLastError(WSAEWOULDBLOCK);
990#ifndef NOSOCKETSTATES
991 SetState(connecting);
992#endif //NOSOCKETSTATES
993 return FALSE;
994 }
995
996 sockAddr.sin_port = htons((u_short)nHostPort);
997
998 return CAsyncSocketEx::Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
999 }
1000}
1001
1002BOOL CAsyncSocketEx::Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen )
1003{
1004 BOOL res;
1005#ifndef NOLAYERS
1006 if (m_pFirstLayer)
1007 res = SOCKET_ERROR!=m_pFirstLayer->Connect(lpSockAddr, nSockAddrLen);
1008 else
1009#endif //NOLAYERS
1010 res = SOCKET_ERROR!=connect(m_SocketData.hSocket, lpSockAddr, nSockAddrLen);
1011
1012#ifndef NOSOCKETSTATES
1013 if (res || GetLastError()==WSAEWOULDBLOCK)
1014 SetState(connecting);
1015#endif //NOSOCKETSTATES
1016 return res;
1017}
1018
1019
1020#ifdef _AFX
1021BOOL CAsyncSocketEx::GetPeerName( CString& rPeerAddress, UINT& rPeerPort ) const
1022{
1023#ifndef NOLAYERS
1024 if (m_pFirstLayer)
1025 return m_pFirstLayer->GetPeerName(rPeerAddress, rPeerPort);
1026#endif NOLAYERS
1027
1028 SOCKADDR_IN sockAddr;
1029 memset(&sockAddr, 0, sizeof(sockAddr));
1030
1031 int nSockAddrLen = sizeof(sockAddr);
1032 BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
1033 if (bResult)
1034 {
1035 rPeerPort = ntohs(sockAddr.sin_port);
1036 rPeerAddress = inet_ntoa(sockAddr.sin_addr);
1037 }
1038 return bResult;
1039}
1040#endif //_AFX
1041
1042BOOL CAsyncSocketEx::GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen ) const
1043{
1044#ifndef NOLAYERS
1045 if (m_pFirstLayer)
1046 return m_pFirstLayer->GetPeerName(lpSockAddr, lpSockAddrLen);
1047#endif //NOLAYERS
1048
1049 if ( !getpeername(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) )
1050 return TRUE;
1051 else
1052 return FALSE;
1053}
1054
1055#ifdef _AFX
1056BOOL CAsyncSocketEx::GetSockName(CString& rSocketAddress, UINT& rSocketPort)
1057{
1058 SOCKADDR_IN sockAddr;
1059 memset(&sockAddr, 0, sizeof(sockAddr));
1060
1061 int nSockAddrLen = sizeof(sockAddr);
1062 BOOL bResult = GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
1063 if (bResult)
1064 {
1065 rSocketPort = ntohs(sockAddr.sin_port);
1066 rSocketAddress = inet_ntoa(sockAddr.sin_addr);
1067 }
1068 return bResult;
1069}
1070#endif //_AFX
1071
1072BOOL CAsyncSocketEx::GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
1073{
1074 if ( !getsockname(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen) )
1075 return TRUE;
1076 else
1077 return FALSE;
1078}
1079
1080BOOL CAsyncSocketEx::ShutDown( int nHow /*=sends*/ )
1081{
1082#ifndef NOLAYERS
1083 if (m_pFirstLayer)
1084 {
1085 return m_pFirstLayer->ShutDown();
1086 }
1087 else
1088#endif //NOLAYERS
1089 {
1090 if ( !shutdown(m_SocketData.hSocket, nHow) )
1091 return TRUE;
1092 else
1093 return FALSE;
1094 }
1095}
1096
1097SOCKET CAsyncSocketEx::Detach( )
1098{
1099 SOCKET socket=m_SocketData.hSocket;
1100 DetachHandle(socket);
1101 m_SocketData.hSocket=INVALID_SOCKET;
1102 return socket;
1103}
1104
1105BOOL CAsyncSocketEx::Attach( SOCKET hSocket, long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ )
1106{
1107 if (hSocket==INVALID_SOCKET || !hSocket)
1108 return FALSE;
1109
1110 VERIFY(InitAsyncSocketExInstance());
1111 m_SocketData.hSocket=hSocket;
1112 AttachHandle(hSocket);
1113
1114#ifndef NOLAYERS
1115 if (m_pFirstLayer)
1116 {
1117 m_lEvent = lEvent;
1118 return !WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
1119 }
1120 else
1121#endif //NOLAYERS
1122 {
1123 return AsyncSelect(lEvent);
1124 }
1125}
1126
1127BOOL CAsyncSocketEx::AsyncSelect( long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/ )
1128{
1129 ASSERT(m_pLocalAsyncSocketExThreadData);
1130 m_lEvent = lEvent;
1131#ifndef NOLAYERS
1132 if (m_pFirstLayer)
1133 return TRUE;
1134 else
1135#endif //NOLAYERS
1136 {
1137 if ( !WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, lEvent) )
1138 return TRUE;
1139 else
1140 return FALSE;
1141 }
1142 return TRUE;
1143}
1144
1145BOOL CAsyncSocketEx::Listen( int nConnectionBacklog /*=5*/ )
1146{
1147#ifndef NOLAYERS
1148 if (m_pFirstLayer)
1149 return m_pFirstLayer->Listen(nConnectionBacklog);
1150#endif //NOLAYERS
1151
1152 if (!listen(m_SocketData.hSocket, nConnectionBacklog))
1153 {
1154#ifndef NOSOCKETSTATES
1155 SetState(listening);
1156#endif //NOSOCKETSTATES
1157 return TRUE;
1158 }
1159 else
1160 return FALSE;
1161}
1162
1163BOOL CAsyncSocketEx::Accept( CAsyncSocketEx& rConnectedSocket, SOCKADDR* lpSockAddr /*=NULL*/, int* lpSockAddrLen /*=NULL*/ )
1164{
1165 ASSERT(rConnectedSocket.m_SocketData.hSocket == INVALID_SOCKET);
1166#ifndef NOLAYERS
1167 if (m_pFirstLayer)
1168 {
1169 return m_pFirstLayer->Accept(rConnectedSocket, lpSockAddr, lpSockAddrLen);
1170 }
1171 else
1172#endif //NOLAYERS
1173 {
1174 SOCKET hTemp = accept(m_SocketData.hSocket, lpSockAddr, lpSockAddrLen);
1175
1176 if (hTemp == INVALID_SOCKET)
1177 return FALSE;
1178 VERIFY(rConnectedSocket.InitAsyncSocketExInstance());
1179 rConnectedSocket.m_SocketData.hSocket=hTemp;
1180 rConnectedSocket.AttachHandle(hTemp);
1181#ifndef NOSOCKETSTATES
1182 rConnectedSocket.SetState(connected);
1183#endif //NOSOCKETSTATES
1184 }
1185 return TRUE;
1186}
1187
1188BOOL CAsyncSocketEx::IOCtl( long lCommand, DWORD* lpArgument )
1189{
1190 return ioctlsocket(m_SocketData.hSocket, lCommand, lpArgument) != SOCKET_ERROR;
1191}
1192
1193int CAsyncSocketEx::GetLastError()
1194{
1195 return WSAGetLastError();
1196}
1197
1198BOOL CAsyncSocketEx::TriggerEvent(long lEvent)
1199{
1200 if (m_SocketData.hSocket==INVALID_SOCKET)
1201 return FALSE;
1202
1203 ASSERT(m_pLocalAsyncSocketExThreadData);
1204 ASSERT(m_pLocalAsyncSocketExThreadData->m_pHelperWindow);
1205 ASSERT(m_SocketData.nSocketIndex!=-1);
1206
1207#ifndef NOLAYERS
1208 if (m_pFirstLayer)
1209 {
1210 CAsyncSocketExLayer::t_LayerNotifyMsg *pMsg = new CAsyncSocketExLayer::t_LayerNotifyMsg;
1211 pMsg->hSocket = m_SocketData.hSocket;
1212 pMsg->lEvent=lEvent%0xFFFF;
1213 pMsg->pLayer=0;
1214 BOOL res=PostMessage(GetHelperWindowHandle(), WM_USER, (WPARAM)m_SocketData.nSocketIndex, (LPARAM)pMsg);
1215 if (!res)
1216 delete pMsg;
1217 return res;
1218 }
1219 else
1220#endif //NOLAYERS
1221 return PostMessage(GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, m_SocketData.hSocket, lEvent%0xFFFF);
1222
1223}
1224
1225SOCKET CAsyncSocketEx::GetSocketHandle()
1226{
1227 return m_SocketData.hSocket;
1228}
1229
1230HWND CAsyncSocketEx::GetHelperWindowHandle()
1231{
1232 if (!m_pLocalAsyncSocketExThreadData)
1233 return 0;
1234 if (!m_pLocalAsyncSocketExThreadData->m_pHelperWindow)
1235 return 0;
1236 return m_pLocalAsyncSocketExThreadData->m_pHelperWindow->GetHwnd();
1237}
1238
1239#ifndef NOLAYERS
1240BOOL CAsyncSocketEx::AddLayer(CAsyncSocketExLayer *pLayer)
1241{
1242 ASSERT(pLayer);
1243
1244 if (m_pFirstLayer)
1245 {
1246 ASSERT(m_pLastLayer);
1247 m_pLastLayer=m_pLastLayer->AddLayer(pLayer, this);
1248 return m_pLastLayer?TRUE:FALSE;
1249 }
1250 else
1251 {
1252 ASSERT(!m_pLastLayer);
1253 pLayer->Init(0, this);
1254 m_pFirstLayer=pLayer;
1255 m_pLastLayer=m_pFirstLayer;
1256 if (m_SocketData.hSocket != INVALID_SOCKET)
1257 if (WSAAsyncSelect(m_SocketData.hSocket, GetHelperWindowHandle(), m_SocketData.nSocketIndex+WM_SOCKETEX_NOTIFY, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE))
1258 return FALSE;
1259 }
1260
1261 return TRUE;
1262}
1263
1264void CAsyncSocketEx::RemoveAllLayers()
1265{
1266 m_pFirstLayer=0;
1267 m_pLastLayer=0;
1268}
1269
1270int CAsyncSocketEx::OnLayerCallback(const CAsyncSocketExLayer *pLayer, int nType, int nParam1, int nParam2)
1271{
1272 ASSERT(pLayer);
1273 return 1;
1274}
1275
1276BOOL CAsyncSocketEx::IsLayerAttached() const
1277{
1278 return m_pFirstLayer ? TRUE : FALSE;
1279}
1280#endif //NOLAYERS
1281
1282BOOL CAsyncSocketEx::GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel /*=SOL_SOCKET*/)
1283{
1284 return (SOCKET_ERROR != getsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen));
1285}
1286
1287BOOL CAsyncSocketEx::SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel /*=SOL_SOCKET*/)
1288{
1289 return (SOCKET_ERROR != setsockopt(m_SocketData.hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, nOptionLen));
1290}
1291
1292#ifndef NOSOCKETSTATES
1293
1294int CAsyncSocketEx::GetState() const
1295{
1296 return m_nState;
1297}
1298
1299void CAsyncSocketEx::SetState(int nState)
1300{
1301 m_nState=nState;
1302}
1303
1304#endif //NOSOCKETSTATES
1305
1306