1 | /*CAsyncSocketEx by Tim Kosse (Tim.Kosse@gmx.de)
|
---|
2 | Version 1.3 (2003-04-26)
|
---|
3 | --------------------------------------------------------
|
---|
4 |
|
---|
5 | Introduction:
|
---|
6 | -------------
|
---|
7 |
|
---|
8 | CAsyncSocketEx is a replacement for the MFC class CAsyncSocket.
|
---|
9 | This class was written because CAsyncSocket is not the fastest WinSock
|
---|
10 | wrapper and it's very hard to add new functionality to CAsyncSocket
|
---|
11 | derived classes. This class offers the same functionality as CAsyncSocket.
|
---|
12 | Also, CAsyncSocketEx offers some enhancements which were not possible with
|
---|
13 | CAsyncSocket without some tricks.
|
---|
14 |
|
---|
15 | How do I use it?
|
---|
16 | ----------------
|
---|
17 | Basically exactly like CAsyncSocket.
|
---|
18 | To use CAsyncSocketEx, just replace all occurrences of CAsyncSocket in your
|
---|
19 | code with CAsyncSocketEx, if you did not enhance CAsyncSocket yourself in
|
---|
20 | any way, you won't have to change anything else in your code.
|
---|
21 |
|
---|
22 | Why is CAsyncSocketEx faster?
|
---|
23 | -----------------------------
|
---|
24 |
|
---|
25 | CAsyncSocketEx is slightly faster when dispatching notification event messages.
|
---|
26 | First have a look at the way CAsyncSocket works. For each thread that uses
|
---|
27 | CAsyncSocket, a window is created. CAsyncSocket calls WSAAsyncSelect with
|
---|
28 | the handle of that window. Until here, CAsyncSocketEx works the same way.
|
---|
29 | But CAsyncSocket uses only one window message (WM_SOCKET_NOTIFY) for all
|
---|
30 | sockets within one thread. When the window recieve WM_SOCKET_NOTIFY, wParam
|
---|
31 | contains the socket handle and the window looks up an CAsyncSocket instance
|
---|
32 | using a map. CAsyncSocketEx works differently. It's helper window uses a
|
---|
33 | wide range of different window messages (WM_USER through 0xBFFF) and passes
|
---|
34 | a different message to WSAAsyncSelect for each socket. When a message in
|
---|
35 | the specified range is received, CAsyncSocketEx looks up the pointer to a
|
---|
36 | CAsyncSocketEx instance in an Array using the index of message - WM_USER.
|
---|
37 | As you can see, CAsyncSocketEx uses the helper window in a more efficient
|
---|
38 | way, as it don't have to use the slow maps to lookup it's own instance.
|
---|
39 | Still, speed increase is not very much, but it may be noticeable when using
|
---|
40 | a lot of sockets at the same time.
|
---|
41 | Please note that the changes do not affect the raw data throughput rate,
|
---|
42 | CAsyncSocketEx only dispatches the notification messages faster.
|
---|
43 |
|
---|
44 | What else does CAsyncSocketEx offer?
|
---|
45 | ------------------------------------
|
---|
46 |
|
---|
47 | CAsyncSocketEx offers a flexible layer system. One example is the proxy layer.
|
---|
48 | Just create an instance of the proxy layer, configure it and add it to the layer
|
---|
49 | chain of your CAsyncSocketEx instance. After that, you can connect through
|
---|
50 | proxies.
|
---|
51 | Benefit: You don't have to change much to use the layer system.
|
---|
52 | Another layer that is currently in development is the SSL layer to establish
|
---|
53 | SSL encrypted connections.
|
---|
54 |
|
---|
55 | License
|
---|
56 | -------
|
---|
57 |
|
---|
58 | Feel free to use this class, as long as you don't claim that you wrote it
|
---|
59 | and this copyright notice stays intact in the source files.
|
---|
60 | If you use this class in commercial applications, please send a short message
|
---|
61 | to 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
|
---|
76 | static char THIS_FILE[]=__FILE__;
|
---|
77 | #endif
|
---|
78 |
|
---|
79 | #ifndef CCRITICALSECTIONWRAPPERINCLUDED
|
---|
80 | class CCriticalSectionWrapper
|
---|
81 | {
|
---|
82 | public:
|
---|
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 | }
|
---|
106 | protected:
|
---|
107 | CRITICAL_SECTION m_criticalSection;
|
---|
108 | BOOL m_bInitialized;
|
---|
109 | };
|
---|
110 | #define CCRITICALSECTIONWRAPPERINCLUDED
|
---|
111 | #endif
|
---|
112 |
|
---|
113 | CCriticalSectionWrapper CAsyncSocketEx::m_sGlobalCriticalSection;
|
---|
114 | CAsyncSocketEx::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 |
|
---|
130 | class CAsyncSocketExHelperWindow
|
---|
131 | {
|
---|
132 | public:
|
---|
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 |
|
---|
605 | private:
|
---|
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 |
|
---|
620 | CAsyncSocketEx::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 |
|
---|
639 | CAsyncSocketEx::~CAsyncSocketEx()
|
---|
640 | {
|
---|
641 | Close();
|
---|
642 | FreeAsyncSocketExInstance();
|
---|
643 | }
|
---|
644 |
|
---|
645 | 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*/ )
|
---|
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 |
|
---|
719 | void CAsyncSocketEx::OnReceive(int nErrorCode)
|
---|
720 | {
|
---|
721 | }
|
---|
722 |
|
---|
723 | void CAsyncSocketEx::OnSend(int nErrorCode)
|
---|
724 | {
|
---|
725 | }
|
---|
726 |
|
---|
727 | void CAsyncSocketEx::OnConnect(int nErrorCode)
|
---|
728 | {
|
---|
729 | }
|
---|
730 |
|
---|
731 | void CAsyncSocketEx::OnAccept(int nErrorCode)
|
---|
732 | {
|
---|
733 | }
|
---|
734 |
|
---|
735 | void CAsyncSocketEx::OnClose(int nErrorCode)
|
---|
736 | {
|
---|
737 | }
|
---|
738 |
|
---|
739 | BOOL 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 |
|
---|
767 | BOOL 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 |
|
---|
781 | void 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 |
|
---|
790 | void 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 |
|
---|
804 | void 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 |
|
---|
829 | BOOL 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 |
|
---|
884 | void 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 |
|
---|
932 | int 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 |
|
---|
943 | int 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 |
|
---|
953 | BOOL 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 |
|
---|
1002 | BOOL 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
|
---|
1021 | BOOL 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 |
|
---|
1042 | BOOL 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
|
---|
1056 | BOOL 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 |
|
---|
1072 | BOOL 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 |
|
---|
1080 | BOOL 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 |
|
---|
1097 | SOCKET CAsyncSocketEx::Detach( )
|
---|
1098 | {
|
---|
1099 | SOCKET socket=m_SocketData.hSocket;
|
---|
1100 | DetachHandle(socket);
|
---|
1101 | m_SocketData.hSocket=INVALID_SOCKET;
|
---|
1102 | return socket;
|
---|
1103 | }
|
---|
1104 |
|
---|
1105 | BOOL 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 |
|
---|
1127 | BOOL 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 |
|
---|
1145 | BOOL 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 |
|
---|
1163 | BOOL 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 |
|
---|
1188 | BOOL CAsyncSocketEx::IOCtl( long lCommand, DWORD* lpArgument )
|
---|
1189 | {
|
---|
1190 | return ioctlsocket(m_SocketData.hSocket, lCommand, lpArgument) != SOCKET_ERROR;
|
---|
1191 | }
|
---|
1192 |
|
---|
1193 | int CAsyncSocketEx::GetLastError()
|
---|
1194 | {
|
---|
1195 | return WSAGetLastError();
|
---|
1196 | }
|
---|
1197 |
|
---|
1198 | BOOL 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 |
|
---|
1225 | SOCKET CAsyncSocketEx::GetSocketHandle()
|
---|
1226 | {
|
---|
1227 | return m_SocketData.hSocket;
|
---|
1228 | }
|
---|
1229 |
|
---|
1230 | HWND 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
|
---|
1240 | BOOL 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 |
|
---|
1264 | void CAsyncSocketEx::RemoveAllLayers()
|
---|
1265 | {
|
---|
1266 | m_pFirstLayer=0;
|
---|
1267 | m_pLastLayer=0;
|
---|
1268 | }
|
---|
1269 |
|
---|
1270 | int CAsyncSocketEx::OnLayerCallback(const CAsyncSocketExLayer *pLayer, int nType, int nParam1, int nParam2)
|
---|
1271 | {
|
---|
1272 | ASSERT(pLayer);
|
---|
1273 | return 1;
|
---|
1274 | }
|
---|
1275 |
|
---|
1276 | BOOL CAsyncSocketEx::IsLayerAttached() const
|
---|
1277 | {
|
---|
1278 | return m_pFirstLayer ? TRUE : FALSE;
|
---|
1279 | }
|
---|
1280 | #endif //NOLAYERS
|
---|
1281 |
|
---|
1282 | BOOL 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 |
|
---|
1287 | BOOL 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 |
|
---|
1294 | int CAsyncSocketEx::GetState() const
|
---|
1295 | {
|
---|
1296 | return m_nState;
|
---|
1297 | }
|
---|
1298 |
|
---|
1299 | void CAsyncSocketEx::SetState(int nState)
|
---|
1300 | {
|
---|
1301 | m_nState=nState;
|
---|
1302 | }
|
---|
1303 |
|
---|
1304 | #endif //NOSOCKETSTATES
|
---|
1305 |
|
---|
1306 |
|
---|