OSDN Git Service

Add support for IPv6 (not tested).
[ffftp/ffftp.git] / socket.c
1 /*=============================================================================\r
2 *\r
3 *                                                                       ソケット\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 #define STRICT\r
31 // IPv6対応\r
32 #include <ws2tcpip.h>\r
33 #include <windows.h>\r
34 #include <stdio.h>\r
35 #include <stdlib.h>\r
36 #include <string.h>\r
37 #include <time.h>\r
38 #include <windowsx.h>\r
39 #include <commctrl.h>\r
40 \r
41 #include "common.h"\r
42 #include "resource.h"\r
43 // UTF-8対応\r
44 #include "punycode.h"\r
45 \r
46 #define USE_THIS        1\r
47 #define DBG_MSG         0\r
48 \r
49 \r
50 \r
51 \r
52 // Winsock2で定義される定数と名前が重複し値が異なるため使用不可\r
53 //#define FD_CONNECT_BIT                0x0001\r
54 //#define FD_CLOSE_BIT          0x0002\r
55 //#define FD_ACCEPT_BIT         0x0004\r
56 //#define FD_READ_BIT                   0x0008\r
57 //#define FD_WRITE_BIT          0x0010\r
58 \r
59 \r
60 \r
61 \r
62 \r
63 typedef struct {\r
64         SOCKET Socket;\r
65         int FdConnect;\r
66         int FdClose;\r
67         int FdAccept;\r
68         int FdRead;\r
69         int FdWrite;\r
70         int Error;\r
71 } ASYNCSIGNAL;\r
72 \r
73 \r
74 typedef struct {\r
75         HANDLE Async;\r
76         int Done;\r
77         int ErrorDb;\r
78 } ASYNCSIGNALDATABASE;\r
79 \r
80 \r
81 // スレッド衝突のバグ修正\r
82 // 念のためテーブルを増量\r
83 //#define MAX_SIGNAL_ENTRY              10\r
84 //#define MAX_SIGNAL_ENTRY_DBASE        5\r
85 #define MAX_SIGNAL_ENTRY                16\r
86 #define MAX_SIGNAL_ENTRY_DBASE  16\r
87 \r
88 \r
89 \r
90 \r
91 /*===== プロトタイプ =====*/\r
92 \r
93 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);\r
94 static int AskAsyncDone(SOCKET s, int *Error, int Mask);\r
95 static int AskAsyncDoneDbase(HANDLE Async, int *Error);\r
96 static int RegistAsyncTable(SOCKET s);\r
97 static int RegistAsyncTableDbase(HANDLE Async);\r
98 static int UnRegistAsyncTable(SOCKET s);\r
99 static int UnRegistAsyncTableDbase(HANDLE Async);\r
100 // UTF-8対応\r
101 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen);\r
102 // IPv6対応\r
103 static HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family);\r
104 \r
105 \r
106 /*===== 外部参照 =====*/\r
107 \r
108 extern int TimeOut;\r
109 \r
110 \r
111 /*===== ローカルなワーク =====*/\r
112 \r
113 static const char SocketWndClass[] = "FFFTPSocketWnd";\r
114 static HWND hWndSocket;\r
115 \r
116 static ASYNCSIGNAL Signal[MAX_SIGNAL_ENTRY];\r
117 static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];\r
118 \r
119 //static HANDLE hAsyncTblAccMutex;\r
120 // スレッド衝突のバグ修正\r
121 static HANDLE hAsyncTblAccMutex;\r
122 \r
123 \r
124 \r
125 \r
126 \r
127 /*----- \r
128 *\r
129 *       Parameter\r
130 *\r
131 *       Return Value\r
132 *               int ステータス\r
133 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
134 *----------------------------------------------------------------------------*/\r
135 \r
136 int MakeSocketWin(HWND hWnd, HINSTANCE hInst)\r
137 {\r
138         int i;\r
139         int Sts;\r
140         WNDCLASSEX wClass;\r
141 \r
142         wClass.cbSize        = sizeof(WNDCLASSEX);\r
143         wClass.style         = 0;\r
144         wClass.lpfnWndProc   = SocketWndProc;\r
145         wClass.cbClsExtra    = 0;\r
146         wClass.cbWndExtra    = 0;\r
147         wClass.hInstance     = hInst;\r
148         wClass.hIcon         = NULL;\r
149         wClass.hCursor       = NULL;\r
150         wClass.hbrBackground = (HBRUSH)CreateSolidBrush(GetSysColor(COLOR_INFOBK));\r
151         wClass.lpszMenuName  = NULL;\r
152         wClass.lpszClassName = SocketWndClass;\r
153         wClass.hIconSm       = NULL;\r
154         RegisterClassEx(&wClass);\r
155 \r
156         Sts = FFFTP_FAIL;\r
157         hWndSocket = CreateWindowEx(0, SocketWndClass, NULL,\r
158                         WS_BORDER | WS_POPUP,\r
159                         0, 0, 0, 0,\r
160                         hWnd, NULL, hInst, NULL);\r
161 \r
162         if(hWndSocket != NULL)\r
163         {\r
164 //              hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL);\r
165 \r
166                 // スレッド衝突のバグ修正\r
167 //              for(i = 0; i < MAX_SIGNAL_ENTRY; i++)\r
168 //                      Signal[i].Socket = INVALID_SOCKET;\r
169 //              for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)\r
170 //                      SignalDbase[i].Async = 0;\r
171                 if(hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL))\r
172                 {\r
173                         for(i = 0; i < MAX_SIGNAL_ENTRY; i++)\r
174                                 Signal[i].Socket = INVALID_SOCKET;\r
175                         for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)\r
176                                 SignalDbase[i].Async = 0;\r
177                 }\r
178                 Sts = FFFTP_SUCCESS;\r
179         }\r
180         return(Sts);\r
181 }\r
182 \r
183 \r
184 /*----- \r
185 *\r
186 *       Parameter\r
187 *               なし\r
188 *\r
189 *       Return Value\r
190 *               なし\r
191 *----------------------------------------------------------------------------*/\r
192 \r
193 void DeleteSocketWin(void)\r
194 {\r
195 //      CloseHandle(hAsyncTblAccMutex);\r
196         // スレッド衝突のバグ修正\r
197         CloseHandle(hAsyncTblAccMutex);\r
198         hAsyncTblAccMutex = NULL;\r
199 \r
200         if(hWndSocket != NULL)\r
201                 DestroyWindow(hWndSocket);\r
202         return;\r
203 }\r
204 \r
205 \r
206 /*----- \r
207 *\r
208 *       Parameter\r
209 *               HWND hWnd : ウインドウハンドル\r
210 *               UINT message : メッセージ番号\r
211 *               WPARAM wParam : メッセージの WPARAM 引数\r
212 *               LPARAM lParam : メッセージの LPARAM 引数\r
213 *\r
214 *       Return Value\r
215 *               BOOL TRUE/FALSE\r
216 *----------------------------------------------------------------------------*/\r
217 \r
218 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
219 {\r
220         int Pos;\r
221 \r
222         switch(message)\r
223         {\r
224                 case WM_ASYNC_SOCKET :\r
225                         // スレッド衝突のバグ修正\r
226                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
227                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
228                         {\r
229                                 if(Signal[Pos].Socket == (SOCKET)wParam)\r
230                                 {\r
231                                         Signal[Pos].Error = WSAGETSELECTERROR(lParam);\r
232 #if DBG_MSG\r
233                                         if(WSAGETSELECTERROR(lParam) != 0)\r
234                                                 DoPrintf("####### Signal: error (%d)", WSAGETSELECTERROR(lParam));\r
235 #endif\r
236 \r
237                                         switch(WSAGETSELECTEVENT(lParam))\r
238                                         {\r
239                                                 case FD_CONNECT :\r
240                                                         Signal[Pos].FdConnect = 1;\r
241 #if DBG_MSG\r
242                                                         DoPrintf("####### Signal: connect (S=%x)", Signal[Pos].Socket);\r
243 #endif\r
244                                                         break;\r
245 \r
246                                                 case FD_CLOSE :\r
247                                                         Signal[Pos].FdClose = 1;\r
248 #if DBG_MSG\r
249                                                         DoPrintf("####### Signal: close (S=%x)", Signal[Pos].Socket);\r
250 #endif\r
251 //SetTaskMsg("####### Signal: close (%d) (S=%x)", Pos, Signal[Pos].Socket);\r
252                                                         break;\r
253 \r
254                                                 case FD_ACCEPT :\r
255                                                         Signal[Pos].FdAccept = 1;\r
256 #if DBG_MSG\r
257                                                         DoPrintf("####### Signal: accept (S=%x)", Signal[Pos].Socket);\r
258 #endif\r
259                                                         break;\r
260 \r
261                                                 case FD_READ :\r
262                                                         Signal[Pos].FdRead = 1;\r
263 #if DBG_MSG\r
264                                                         DoPrintf("####### Signal: read (S=%x)", Signal[Pos].Socket);\r
265 #endif\r
266                                                         break;\r
267 \r
268                                                 case FD_WRITE :\r
269                                                         Signal[Pos].FdWrite = 1;\r
270 #if DBG_MSG\r
271                                                         DoPrintf("####### Signal: write (S=%x)", Signal[Pos].Socket);\r
272 #endif\r
273                                                         break;\r
274                                         }\r
275                                         break;\r
276                                 }\r
277                         }\r
278                         // スレッド衝突のバグ修正\r
279                         ReleaseMutex(hAsyncTblAccMutex);\r
280                         break;\r
281 \r
282                 case WM_ASYNC_DBASE :\r
283                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
284                         RegistAsyncTableDbase((HANDLE)wParam);\r
285                         // スレッド衝突のバグ修正\r
286                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
287                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
288                         {\r
289                                 if(SignalDbase[Pos].Async == (HANDLE)wParam)\r
290                                 {\r
291                                         if(HIWORD(lParam) != 0)\r
292                                         {\r
293                                                 SignalDbase[Pos].ErrorDb = 1;\r
294 #if DBG_MSG\r
295                                                 DoPrintf("##### SignalDatabase: error");\r
296 #endif\r
297                                         }\r
298                                         SignalDbase[Pos].Done = 1;\r
299 #if DBG_MSG\r
300                                         DoPrintf("##### SignalDatabase: Done");\r
301 #endif\r
302                                         break;\r
303                                 }\r
304                         }\r
305                         // スレッド衝突のバグ修正\r
306                         ReleaseMutex(hAsyncTblAccMutex);\r
307                         break;\r
308 \r
309                 default :\r
310                         return(DefWindowProc(hWnd, message, wParam, lParam));\r
311         }\r
312     return(0);\r
313 }\r
314 \r
315 \r
316 \r
317 \r
318 /*----- \r
319 *\r
320 *       Parameter\r
321 *               \r
322 *\r
323 *       Return Value\r
324 *               \r
325 *----------------------------------------------------------------------------*/\r
326 \r
327 static int AskAsyncDone(SOCKET s, int *Error, int Mask)\r
328 {\r
329         int Sts;\r
330         int Pos;\r
331 \r
332         // スレッド衝突のバグ修正\r
333         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
334         Sts = NO;\r
335         *Error = 0;\r
336         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
337         {\r
338                 if(Signal[Pos].Socket == s)\r
339                 {\r
340                         *Error = Signal[Pos].Error;\r
341                         if(Signal[Pos].Error != 0)\r
342                                 Sts = YES;\r
343                         if((Mask & FD_CONNECT) && (Signal[Pos].FdConnect != 0))\r
344                         {\r
345                                 Sts = YES;\r
346 #if DBG_MSG\r
347                                 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);\r
348 #endif\r
349                         }\r
350                         if((Mask & FD_CLOSE) && (Signal[Pos].FdClose != 0))\r
351 //                      if(Mask & FD_CLOSE)\r
352                         {\r
353                                 Sts = YES;\r
354 #if DBG_MSG\r
355                                 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);\r
356 #endif\r
357                         }\r
358                         if((Mask & FD_ACCEPT) && (Signal[Pos].FdAccept != 0))\r
359                         {\r
360                                 Signal[Pos].FdAccept = 0;\r
361                                 Sts = YES;\r
362 #if DBG_MSG\r
363                                 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);\r
364 #endif\r
365                         }\r
366                         if((Mask & FD_READ) && (Signal[Pos].FdRead != 0))\r
367                         {\r
368                                 Signal[Pos].FdRead = 0;\r
369                                 Sts = YES;\r
370 #if DBG_MSG\r
371                                 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);\r
372 #endif\r
373                         }\r
374                         if((Mask & FD_WRITE) && (Signal[Pos].FdWrite != 0))\r
375                         {\r
376                                 Signal[Pos].FdWrite = 0;\r
377                                 Sts = YES;\r
378 #if DBG_MSG\r
379                                 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);\r
380 #endif\r
381                         }\r
382                         break;\r
383                 }\r
384         }\r
385         // スレッド衝突のバグ修正\r
386         ReleaseMutex(hAsyncTblAccMutex);\r
387 \r
388         if(Pos == MAX_SIGNAL_ENTRY)\r
389         {\r
390                 if(Mask & FD_CLOSE)\r
391                 {\r
392                                 Sts = YES;\r
393                 }\r
394                 else\r
395                 {\r
396                         MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);\r
397                         exit(1);\r
398                 }\r
399         }\r
400         return(Sts);\r
401 }\r
402 \r
403 \r
404 /*----- \r
405 *\r
406 *       Parameter\r
407 *               \r
408 *\r
409 *       Return Value\r
410 *               \r
411 *----------------------------------------------------------------------------*/\r
412 \r
413 static int AskAsyncDoneDbase(HANDLE Async, int *Error)\r
414 {\r
415         int Sts;\r
416         int Pos;\r
417 \r
418         // スレッド衝突のバグ修正\r
419         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
420         Sts = NO;\r
421         *Error = 0;\r
422         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
423         {\r
424                 if(SignalDbase[Pos].Async == Async)\r
425                 {\r
426                         if(SignalDbase[Pos].Done != 0)\r
427                         {\r
428                                 *Error = SignalDbase[Pos].ErrorDb;\r
429                                 Sts = YES;\r
430 #if DBG_MSG\r
431                                 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);\r
432 #endif\r
433                         }\r
434                         break;\r
435                 }\r
436         }\r
437         // スレッド衝突のバグ修正\r
438         ReleaseMutex(hAsyncTblAccMutex);\r
439 \r
440         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
441         {\r
442                 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);\r
443                 exit(1);\r
444         }\r
445         return(Sts);\r
446 }\r
447 \r
448 \r
449 \r
450 /*----- \r
451 *\r
452 *       Parameter\r
453 *               \r
454 *\r
455 *       Return Value\r
456 *               \r
457 *----------------------------------------------------------------------------*/\r
458 \r
459 static int RegistAsyncTable(SOCKET s)\r
460 {\r
461         int Sts;\r
462         int Pos;\r
463 \r
464         // スレッド衝突のバグ修正\r
465         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
466         Sts = NO;\r
467         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
468         {\r
469                 if(Signal[Pos].Socket == s)\r
470                 {\r
471                         // 強制的に閉じられたソケットがあると重複する可能性あり\r
472 //                      MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);\r
473 //                      break;\r
474                         Signal[Pos].Socket = INVALID_SOCKET;\r
475                 }\r
476         }\r
477         // スレッド衝突のバグ修正\r
478         ReleaseMutex(hAsyncTblAccMutex);\r
479 \r
480         if(Pos == MAX_SIGNAL_ENTRY)\r
481         {\r
482                 // スレッド衝突のバグ修正\r
483                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
484                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
485                 {\r
486                         if(Signal[Pos].Socket == INVALID_SOCKET)\r
487                         {\r
488 \r
489 //SetTaskMsg("############### Regist socket (%d)", Pos);\r
490 \r
491                                 Signal[Pos].Socket = s;\r
492                                 Signal[Pos].Error = 0;\r
493                                 Signal[Pos].FdConnect = 0;\r
494                                 Signal[Pos].FdClose = 0;\r
495                                 Signal[Pos].FdAccept = 0;\r
496                                 Signal[Pos].FdRead = 0;\r
497                                 Signal[Pos].FdWrite = 0;\r
498                                 Sts = YES;\r
499                                 break;\r
500                         }\r
501                 }\r
502                 // スレッド衝突のバグ修正\r
503                 ReleaseMutex(hAsyncTblAccMutex);\r
504 \r
505                 if(Pos == MAX_SIGNAL_ENTRY)\r
506                 {\r
507                         MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);\r
508                         exit(1);\r
509                 }\r
510         }\r
511 \r
512         return(Sts);\r
513 }\r
514 \r
515 \r
516 /*----- \r
517 *\r
518 *       Parameter\r
519 *               \r
520 *\r
521 *       Return Value\r
522 *               \r
523 *----------------------------------------------------------------------------*/\r
524 \r
525 static int RegistAsyncTableDbase(HANDLE Async)\r
526 {\r
527         int Sts;\r
528         int Pos;\r
529 \r
530         // スレッド衝突のバグ修正\r
531         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
532         Sts = NO;\r
533         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
534         {\r
535                 if(SignalDbase[Pos].Async == Async)\r
536                 {\r
537                         // 強制的に閉じられたハンドルがあると重複する可能性あり\r
538 //                      MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);\r
539                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
540                         break;\r
541                 }\r
542         }\r
543         // スレッド衝突のバグ修正\r
544         ReleaseMutex(hAsyncTblAccMutex);\r
545 \r
546         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
547         {\r
548                 // スレッド衝突のバグ修正\r
549                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
550                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
551                 {\r
552                         if(SignalDbase[Pos].Async == 0)\r
553                         {\r
554 \r
555 //SetTaskMsg("############### Regist dbase (%d)", Pos);\r
556 \r
557                                 SignalDbase[Pos].Async = Async;\r
558                                 SignalDbase[Pos].Done = 0;\r
559                                 SignalDbase[Pos].ErrorDb = 0;\r
560                                 Sts = YES;\r
561                                 break;\r
562                         }\r
563                 }\r
564                 // スレッド衝突のバグ修正\r
565                 ReleaseMutex(hAsyncTblAccMutex);\r
566 \r
567                 if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
568                 {\r
569                         MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);\r
570                         exit(1);\r
571                 }\r
572         }\r
573 \r
574         return(Sts);\r
575 }\r
576 \r
577 \r
578 /*----- \r
579 *\r
580 *       Parameter\r
581 *               \r
582 *\r
583 *       Return Value\r
584 *               \r
585 *----------------------------------------------------------------------------*/\r
586 \r
587 static int UnRegistAsyncTable(SOCKET s)\r
588 {\r
589         int Sts;\r
590         int Pos;\r
591 \r
592         // スレッド衝突のバグ修正\r
593         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
594         Sts = NO;\r
595         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
596         {\r
597                 if(Signal[Pos].Socket == s)\r
598                 {\r
599 \r
600 //SetTaskMsg("############### UnRegist socket (%d)", Pos);\r
601 \r
602                         Signal[Pos].Socket = INVALID_SOCKET;\r
603                         Sts = YES;\r
604                         break;\r
605                 }\r
606         }\r
607         // スレッド衝突のバグ修正\r
608         ReleaseMutex(hAsyncTblAccMutex);\r
609         return(Sts);\r
610 }\r
611 \r
612 \r
613 /*----- \r
614 *\r
615 *       Parameter\r
616 *               \r
617 *\r
618 *       Return Value\r
619 *               \r
620 *----------------------------------------------------------------------------*/\r
621 \r
622 static int UnRegistAsyncTableDbase(HANDLE Async)\r
623 {\r
624         int Sts;\r
625         int Pos;\r
626 \r
627         // スレッド衝突のバグ修正\r
628         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
629         Sts = NO;\r
630         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
631         {\r
632                 if(SignalDbase[Pos].Async == Async)\r
633                 {\r
634 \r
635 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);\r
636 \r
637                         SignalDbase[Pos].Async = 0;\r
638                         Sts = YES;\r
639                         break;\r
640                 }\r
641         }\r
642         // スレッド衝突のバグ修正\r
643         ReleaseMutex(hAsyncTblAccMutex);\r
644         return(Sts);\r
645 }\r
646 \r
647 \r
648 \r
649 \r
650 \r
651 \r
652 \r
653 \r
654 // IPv6対応\r
655 //struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
656 struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
657 {\r
658 #if USE_THIS\r
659         struct hostent *Ret;\r
660         HANDLE hAsync;\r
661         int Error;\r
662 \r
663 #if DBG_MSG\r
664         DoPrintf("# Start gethostbyname");\r
665 #endif\r
666         Ret = NULL;\r
667         // 同時接続対応\r
668 //      *CancelCheckWork = NO;\r
669 \r
670         // UTF-8対応\r
671 //      hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
672         hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
673         if(hAsync != NULL)\r
674         {\r
675                 RegistAsyncTableDbase(hAsync);\r
676                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
677                 {\r
678                         Sleep(1);\r
679                         if(BackgrndMessageProc() == YES)\r
680                                 *CancelCheckWork = YES;\r
681                 }\r
682 \r
683                 if(*CancelCheckWork == YES)\r
684                 {\r
685                         WSACancelAsyncRequest(hAsync);\r
686                 }\r
687                 else if(Error == 0)\r
688                 {\r
689                         Ret = (struct hostent *)Buf;\r
690                 }\r
691                 UnRegistAsyncTableDbase(hAsync);\r
692         }\r
693         return(Ret);\r
694 #else\r
695         return(gethostbyname(Name));\r
696 #endif\r
697 }\r
698 \r
699 \r
700 struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
701 {\r
702 #if USE_THIS\r
703         struct hostent *Ret;\r
704         HANDLE hAsync;\r
705         int Error;\r
706 \r
707 #if DBG_MSG\r
708         DoPrintf("# Start gethostbyname");\r
709 #endif\r
710         Ret = NULL;\r
711         // 同時接続対応\r
712 //      *CancelCheckWork = NO;\r
713 \r
714         // UTF-8対応\r
715 //      hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
716         hAsync = WSAAsyncGetHostByNameIPv6M(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len, AF_INET6);\r
717         if(hAsync != NULL)\r
718         {\r
719                 RegistAsyncTableDbase(hAsync);\r
720                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
721                 {\r
722                         Sleep(1);\r
723                         if(BackgrndMessageProc() == YES)\r
724                                 *CancelCheckWork = YES;\r
725                 }\r
726 \r
727                 if(*CancelCheckWork == YES)\r
728                 {\r
729                         WSACancelAsyncRequest(hAsync);\r
730                 }\r
731                 else if(Error == 0)\r
732                 {\r
733                         Ret = (struct hostent *)Buf;\r
734                 }\r
735                 UnRegistAsyncTableDbase(hAsync);\r
736         }\r
737         return(Ret);\r
738 #else\r
739         return(gethostbyname(Name));\r
740 #endif\r
741 }\r
742 \r
743 \r
744 \r
745 \r
746 \r
747 SOCKET do_socket(int af, int type, int protocol)\r
748 {\r
749         SOCKET Ret;\r
750 \r
751         Ret = socket(af, type, protocol);\r
752         if(Ret != INVALID_SOCKET)\r
753         {\r
754                 RegistAsyncTable(Ret);\r
755         }\r
756 #if DBG_MSG\r
757         DoPrintf("# do_socket (S=%x)", Ret);\r
758 #endif\r
759         return(Ret);\r
760 }\r
761 \r
762 \r
763 \r
764 int do_closesocket(SOCKET s)\r
765 {\r
766 #if USE_THIS\r
767         int Ret;\r
768         int Error;\r
769         int CancelCheckWork;\r
770 \r
771 #if DBG_MSG\r
772         DoPrintf("# Start close (S=%x)", s);\r
773 #endif\r
774         CancelCheckWork = NO;\r
775 \r
776         // スレッド衝突のバグ修正\r
777         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
778         UnRegistAsyncTable(s);\r
779         // FTPS対応\r
780 //      Ret = closesocket(s);\r
781         Ret = closesocketS(s);\r
782         if(Ret == SOCKET_ERROR)\r
783         {\r
784                 Error = 0;\r
785                 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE) != YES))\r
786                 {\r
787                         Sleep(1);\r
788                         if(BackgrndMessageProc() == YES)\r
789                                 CancelCheckWork = YES;\r
790                 }\r
791 \r
792                 if((CancelCheckWork == NO) && (Error == 0))\r
793                         Ret = 0;\r
794         }\r
795 \r
796         // スレッド衝突のバグ修正\r
797 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
798         if(BackgrndMessageProc() == YES)\r
799                 CancelCheckWork = YES;\r
800         // スレッド衝突のバグ修正\r
801 //      UnRegistAsyncTable(s);\r
802 \r
803 #if DBG_MSG\r
804         DoPrintf("# Exit close");\r
805 #endif\r
806         return(Ret);\r
807 #else\r
808         return(closesocket(s));\r
809 #endif\r
810 }\r
811 \r
812 \r
813 \r
814 \r
815 \r
816 \r
817 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)\r
818 {\r
819 #if USE_THIS\r
820         int Ret;\r
821         int Error;\r
822 \r
823 #if DBG_MSG\r
824         DoPrintf("# Start connect (S=%x)", s);\r
825 #endif\r
826         // 同時接続対応\r
827 //      *CancelCheckWork = NO;\r
828 \r
829 #if DBG_MSG\r
830         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
831 #endif\r
832         // 高速化のためFD_READとFD_WRITEを使用しない\r
833 //      Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
834         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT);\r
835         if(Ret != SOCKET_ERROR)\r
836         {\r
837                 Ret = connect(s, name, namelen);\r
838                 if(Ret == SOCKET_ERROR)\r
839                 {\r
840                         do\r
841                         {\r
842                                 Error = 0;\r
843                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT) != YES))\r
844                                 {\r
845                                         Sleep(1);\r
846                                         if(BackgrndMessageProc() == YES)\r
847                                                 *CancelCheckWork = YES;\r
848                                 }\r
849 \r
850                                 if(*CancelCheckWork == YES)\r
851                                         break;\r
852                                 if(Error == 0)\r
853                                         Ret = 0;\r
854                                 else\r
855                                 {\r
856 //                                      Error = WSAGetLastError();\r
857                                         DoPrintf("#### Connect: Error=%d", Error);\r
858                                 }\r
859                         }\r
860                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
861                 }\r
862         }\r
863         else\r
864                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
865 \r
866 #if DBG_MSG\r
867         DoPrintf("# Exit connect (%d)", Ret);\r
868 #endif\r
869         return(Ret);\r
870 #else\r
871         return(connect(s, name, namelen));\r
872 #endif\r
873 }\r
874 \r
875 \r
876 \r
877 \r
878 \r
879 int do_listen(SOCKET s, int backlog)\r
880 {\r
881         int Ret;\r
882 \r
883         Ret = 1;\r
884 #if DBG_MSG\r
885         DoPrintf("# Start listen (S=%x)", s);\r
886         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
887 #endif\r
888 \r
889         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
890         if(Ret != SOCKET_ERROR)\r
891                 Ret = listen(s, backlog);\r
892 \r
893 #if DBG_MSG\r
894         DoPrintf("# Exit listen (%d)", Ret);\r
895 #endif\r
896         return(Ret);\r
897 }\r
898 \r
899 \r
900 \r
901 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
902 {\r
903 #if USE_THIS\r
904         SOCKET Ret2;\r
905         int CancelCheckWork;\r
906         int Error;\r
907 \r
908 #if DBG_MSG\r
909         DoPrintf("# Start accept (S=%x)", s);\r
910 #endif\r
911         CancelCheckWork = NO;\r
912         Ret2 = INVALID_SOCKET;\r
913         Error = 0;\r
914 \r
915         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT) != YES))\r
916         {\r
917                 if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
918                 {\r
919                         Error = 1;\r
920                         break;\r
921                 }\r
922                 Sleep(1);\r
923                 if(BackgrndMessageProc() == YES)\r
924                         CancelCheckWork = YES;\r
925         }\r
926 \r
927         if((CancelCheckWork == NO) && (Error == 0))\r
928         {\r
929                 do\r
930                 {\r
931                         Ret2 = accept(s, addr, addrlen);\r
932                         if(Ret2 != INVALID_SOCKET)\r
933                         {\r
934 #if DBG_MSG\r
935                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
936                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
937 #endif\r
938                                 RegistAsyncTable(Ret2);\r
939                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
940                                 {\r
941                                         do_closesocket(Ret2);\r
942                                         Ret2 = INVALID_SOCKET;\r
943                                 }\r
944                                 break;\r
945                         }\r
946                         Error = WSAGetLastError();\r
947                         Sleep(1);\r
948                         if(BackgrndMessageProc() == YES)\r
949                                 break;\r
950                 }\r
951                 while(Error == WSAEWOULDBLOCK);\r
952         }\r
953 \r
954 #if DBG_MSG\r
955         DoPrintf("# Exit accept");\r
956 #endif\r
957         return(Ret2);\r
958 #else\r
959         return(accept(s, addr, addrlen));\r
960 #endif\r
961 }\r
962 \r
963 \r
964 \r
965 \r
966 /*----- recv相当の関数 --------------------------------------------------------\r
967 *\r
968 *       Parameter\r
969 *               SOCKET s : ソケット\r
970 *               char *buf : データを読み込むバッファ\r
971 *               int len : 長さ\r
972 *               int flags : recvに与えるフラグ\r
973 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
974 *\r
975 *       Return Value\r
976 *               int : recvの戻り値と同じ\r
977 *\r
978 *       Note\r
979 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
980 *----------------------------------------------------------------------------*/\r
981 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
982 {\r
983 #if USE_THIS\r
984         int Ret;\r
985         time_t StartTime;\r
986         time_t ElapseTime;\r
987         int Error;\r
988 \r
989 #if DBG_MSG\r
990         DoPrintf("# Start recv (S=%x)", s);\r
991 #endif\r
992         *TimeOutErr = NO;\r
993         // 同時接続対応\r
994 //      *CancelCheckWork = NO;\r
995         Ret = SOCKET_ERROR;\r
996         Error = 0;\r
997 \r
998         if(TimeOut != 0)\r
999                 time(&StartTime);\r
1000 \r
1001         // FTPS対応\r
1002         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
1003 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))\r
1004         // 短時間にFD_READが2回以上通知される対策\r
1005 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))\r
1006 //      {\r
1007 //              if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
1008 //              {\r
1009 //                      Ret = 0;\r
1010 //                      break;\r
1011 //              }\r
1012 //              Sleep(1);\r
1013 //              if(BackgrndMessageProc() == YES)\r
1014 //                      *CancelCheckWork = YES;\r
1015 //              else if(TimeOut != 0)\r
1016 //              {\r
1017 //                      time(&ElapseTime);\r
1018 //                      ElapseTime -= StartTime;\r
1019 //                      if(ElapseTime >= TimeOut)\r
1020 //                      {\r
1021 //                              DoPrintf("do_recv timed out");\r
1022 //                              *TimeOutErr = YES;\r
1023 //                              *CancelCheckWork = YES;\r
1024 //                      }\r
1025 //              }\r
1026 //      }\r
1027 \r
1028         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1029         {\r
1030                 do\r
1031                 {\r
1032 #if DBG_MSG\r
1033                         DoPrintf("## recv()");\r
1034 #endif\r
1035 \r
1036                         // FTPS対応\r
1037 //                      Ret = recv(s, buf, len, flags);\r
1038                         Ret = recvS(s, buf, len, flags);\r
1039                         if(Ret != SOCKET_ERROR)\r
1040                                 break;\r
1041                         Error = WSAGetLastError();\r
1042                         Sleep(1);\r
1043                         if(BackgrndMessageProc() == YES)\r
1044                                 break;\r
1045                         // FTPS対応\r
1046                         // 受信確認をバイパスしたためここでタイムアウトの確認\r
1047                         if(BackgrndMessageProc() == YES)\r
1048                                 *CancelCheckWork = YES;\r
1049                         else if(TimeOut != 0)\r
1050                         {\r
1051                                 time(&ElapseTime);\r
1052                                 ElapseTime -= StartTime;\r
1053                                 if(ElapseTime >= TimeOut)\r
1054                                 {\r
1055                                         DoPrintf("do_recv timed out");\r
1056                                         *TimeOutErr = YES;\r
1057                                         *CancelCheckWork = YES;\r
1058                                 }\r
1059                         }\r
1060                         if(*CancelCheckWork == YES)\r
1061                                 break;\r
1062                 }\r
1063                 while(Error == WSAEWOULDBLOCK);\r
1064         }\r
1065 \r
1066         if(BackgrndMessageProc() == YES)\r
1067                 Ret = SOCKET_ERROR;\r
1068 \r
1069 #if DBG_MSG\r
1070         DoPrintf("# Exit recv (%d)", Ret);\r
1071 #endif\r
1072         return(Ret);\r
1073 #else\r
1074         return(recv(s, buf, len, flags));\r
1075 #endif\r
1076 }\r
1077 \r
1078 \r
1079 \r
1080 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
1081 {\r
1082 #if USE_THIS\r
1083         int Ret;\r
1084         time_t StartTime;\r
1085         time_t ElapseTime;\r
1086         int Error;\r
1087 \r
1088 #if DBG_MSG\r
1089         DoPrintf("# Start send (S=%x)", s);\r
1090 #endif\r
1091         *TimeOutErr = NO;\r
1092         // 同時接続対応\r
1093 //      *CancelCheckWork = NO;\r
1094         Ret = SOCKET_ERROR;\r
1095         Error = 0;\r
1096 \r
1097         if(TimeOut != 0)\r
1098                 time(&StartTime);\r
1099 \r
1100 #if DBG_MSG\r
1101         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1102 #endif\r
1103         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1104         // 毎回通知されたのはNT 4.0までのバグであり仕様ではない\r
1105         // XP以降は互換性のためか毎回通知される\r
1106 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1107         if(BackgrndMessageProc() == YES)\r
1108                 *CancelCheckWork = YES;\r
1109 \r
1110         // FTPS対応\r
1111         // 送信バッファの空き確認には影響しないが念のため\r
1112 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))\r
1113         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1114 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))\r
1115 //      {\r
1116 //              if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
1117 //              {\r
1118 //                      Error = 1;\r
1119 //                      break;\r
1120 //              }\r
1121 //\r
1122 //              Sleep(1);\r
1123 //              if(BackgrndMessageProc() == YES)\r
1124 //                      *CancelCheckWork = YES;\r
1125 //              else if(TimeOut != 0)\r
1126 //              {\r
1127 //                      time(&ElapseTime);\r
1128 //                      ElapseTime -= StartTime;\r
1129 //                      if(ElapseTime >= TimeOut)\r
1130 //                      {\r
1131 //                              DoPrintf("do_write timed out");\r
1132 //                              *TimeOutErr = YES;\r
1133 //                              *CancelCheckWork = YES;\r
1134 //                      }\r
1135 //              }\r
1136 //      }\r
1137 \r
1138         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1139         {\r
1140                 do\r
1141                 {\r
1142 #if DBG_MSG\r
1143                         DoPrintf("## send()");\r
1144 #endif\r
1145 \r
1146                         // FTPS対応\r
1147 //                      Ret = send(s, buf, len, flags);\r
1148                         Ret = sendS(s, buf, len, flags);\r
1149                         if(Ret != SOCKET_ERROR)\r
1150                         {\r
1151 #if DBG_MSG\r
1152                                 DoPrintf("## send() OK");\r
1153 #endif\r
1154                                 break;\r
1155                         }\r
1156                         Error = WSAGetLastError();\r
1157                         Sleep(1);\r
1158                         if(BackgrndMessageProc() == YES)\r
1159                                 break;\r
1160                         // FTPS対応\r
1161                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1162                         if(BackgrndMessageProc() == YES)\r
1163                                 *CancelCheckWork = YES;\r
1164                         else if(TimeOut != 0)\r
1165                         {\r
1166                                 time(&ElapseTime);\r
1167                                 ElapseTime -= StartTime;\r
1168                                 if(ElapseTime >= TimeOut)\r
1169                                 {\r
1170                                         DoPrintf("do_recv timed out");\r
1171                                         *TimeOutErr = YES;\r
1172                                         *CancelCheckWork = YES;\r
1173                                 }\r
1174                         }\r
1175                         if(*CancelCheckWork == YES)\r
1176                                 break;\r
1177                 }\r
1178                 while(Error == WSAEWOULDBLOCK);\r
1179         }\r
1180 \r
1181         if(BackgrndMessageProc() == YES)\r
1182                 Ret = SOCKET_ERROR;\r
1183 \r
1184 #if DBG_MSG\r
1185         DoPrintf("# Exit send (%d)", Ret);\r
1186 #endif\r
1187         return(Ret);\r
1188 #else\r
1189         return(send(s, buf, len, flags));\r
1190 #endif\r
1191 }\r
1192 \r
1193 \r
1194 // 同時接続対応\r
1195 void RemoveReceivedData(SOCKET s)\r
1196 {\r
1197         char buf[1024];\r
1198         int len;\r
1199         int Error;\r
1200         while((len = recvS(s, buf, sizeof(buf), MSG_PEEK)) >= 0)\r
1201         {\r
1202                 AskAsyncDone(s, &Error, FD_READ);\r
1203                 recvS(s, buf, len, 0);\r
1204         }\r
1205 }\r
1206 \r
1207 \r
1208 /*----- \r
1209 *\r
1210 *       Parameter\r
1211 *\r
1212 *       Return Value\r
1213 *               int ステータス\r
1214 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1215 *----------------------------------------------------------------------------*/\r
1216 \r
1217 int CheckClosedAndReconnect(void)\r
1218 {\r
1219         int Error;\r
1220         int Sts;\r
1221 \r
1222 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1223 \r
1224         Sts = FFFTP_SUCCESS;\r
1225         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE) == YES)\r
1226         {\r
1227                 Sts = ReConnectCmdSkt();\r
1228         }\r
1229         return(Sts);\r
1230 }\r
1231 \r
1232 \r
1233 \r
1234 // IPv6対応\r
1235 \r
1236 typedef struct\r
1237 {\r
1238         HANDLE h;\r
1239         HWND hWnd;\r
1240         u_int wMsg;\r
1241         char * name;\r
1242         char * buf;\r
1243         int buflen;\r
1244         short Family;\r
1245 } GETHOSTBYNAMEDATA;\r
1246 \r
1247 static DWORD WINAPI WSAAsyncGetHostByNameIPv6ThreadProc(LPVOID lpParameter)\r
1248 {\r
1249         GETHOSTBYNAMEDATA* pData;\r
1250         struct hostent* pHost;\r
1251         struct addrinfo* pAddr;\r
1252         struct addrinfo* p;\r
1253         pHost = NULL;\r
1254         pData = (GETHOSTBYNAMEDATA*)lpParameter;\r
1255         if(getaddrinfo(pData->name, NULL, NULL, &pAddr) == 0)\r
1256         {\r
1257                 p = pAddr;\r
1258                 while(p)\r
1259                 {\r
1260                         if(p->ai_family == pData->Family)\r
1261                         {\r
1262                                 switch(p->ai_family)\r
1263                                 {\r
1264                                 case AF_INET:\r
1265                                         pHost = (struct hostent*)pData->buf;\r
1266                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)\r
1267                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in))\r
1268                                         {\r
1269                                                 pHost->h_name = NULL;\r
1270                                                 pHost->h_aliases = NULL;\r
1271                                                 pHost->h_addrtype = p->ai_family;\r
1272                                                 pHost->h_length = sizeof(struct in_addr);\r
1273                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
1274                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
1275                                                 pHost->h_addr_list[1] = NULL;\r
1276                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in*)p->ai_addr)->sin_addr, sizeof(struct in_addr));\r
1277                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + p->ai_addrlen));\r
1278                                         }\r
1279                                         else\r
1280                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
1281                                         break;\r
1282                                 case AF_INET6:\r
1283                                         pHost = (struct hostent*)pData->buf;\r
1284                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)\r
1285                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in6))\r
1286                                         {\r
1287                                                 pHost->h_name = NULL;\r
1288                                                 pHost->h_aliases = NULL;\r
1289                                                 pHost->h_addrtype = p->ai_family;\r
1290                                                 pHost->h_length = sizeof(struct in6_addr);\r
1291                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
1292                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
1293                                                 pHost->h_addr_list[1] = NULL;\r
1294                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in6*)p->ai_addr)->sin6_addr, sizeof(struct in6_addr));\r
1295                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + p->ai_addrlen));\r
1296                                         }\r
1297                                         else\r
1298                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
1299                                         break;\r
1300                                 }\r
1301                         }\r
1302                         if(pHost)\r
1303                                 break;\r
1304                         p = p->ai_next;\r
1305                 }\r
1306                 if(!p)\r
1307                         PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
1308                 freeaddrinfo(pAddr);\r
1309         }\r
1310         else\r
1311                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
1312         free(pData->name);\r
1313         free(pData);\r
1314         // CreateThreadが返すハンドルが重複するのを回避\r
1315         Sleep(10000);\r
1316         return 0;\r
1317 }\r
1318 \r
1319 // IPv6対応のWSAAsyncGetHostByName相当の関数\r
1320 // FamilyにはAF_INETまたはAF_INET6を指定可能\r
1321 // ただしANSI用\r
1322 static HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1323 {\r
1324         HANDLE hResult;\r
1325         GETHOSTBYNAMEDATA* pData;\r
1326         hResult = NULL;\r
1327         if(pData = malloc(sizeof(GETHOSTBYNAMEDATA)))\r
1328         {\r
1329                 pData->hWnd = hWnd;\r
1330                 pData->wMsg = wMsg;\r
1331                 if(pData->name = malloc(sizeof(char) * (strlen(name) + 1)))\r
1332                 {\r
1333                         strcpy(pData->name, name);\r
1334                         pData->buf = buf;\r
1335                         pData->buflen = buflen;\r
1336                         pData->Family = Family;\r
1337                         if(pData->h = CreateThread(NULL, 0, WSAAsyncGetHostByNameIPv6ThreadProc, pData, CREATE_SUSPENDED, NULL))\r
1338                         {\r
1339                                 ResumeThread(pData->h);\r
1340                                 hResult = pData->h;\r
1341                         }\r
1342                 }\r
1343         }\r
1344         if(!hResult)\r
1345         {\r
1346                 if(pData)\r
1347                 {\r
1348                         if(pData->name)\r
1349                                 free(pData->name);\r
1350                         free(pData);\r
1351                 }\r
1352         }\r
1353         return hResult;\r
1354 }\r
1355 \r
1356 // WSAAsyncGetHostByNameIPv6用のWSACancelAsyncRequest相当の関数\r
1357 int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)\r
1358 {\r
1359         int Result;\r
1360         Result = SOCKET_ERROR;\r
1361         if(TerminateThread(hAsyncTaskHandle, 0))\r
1362                 Result = 0;\r
1363         return Result;\r
1364 }\r
1365 \r
1366 char* AddressToStringIPv6(char* str, void* in6)\r
1367 {\r
1368         char* pResult;\r
1369         unsigned char* p;\r
1370         int MaxZero;\r
1371         int MaxZeroLen;\r
1372         int i;\r
1373         int j;\r
1374         char Tmp[5];\r
1375         pResult = str;\r
1376         p = (unsigned char*)in6;\r
1377         MaxZero = 8;\r
1378         MaxZeroLen = 1;\r
1379         for(i = 0; i < 8; i++)\r
1380         {\r
1381                 for(j = i; j < 8; j++)\r
1382                 {\r
1383                         if(p[j * 2] != 0 || p[j * 2 + 1] != 0)\r
1384                                 break;\r
1385                 }\r
1386                 if(j - i > MaxZeroLen)\r
1387                 {\r
1388                         MaxZero = i;\r
1389                         MaxZeroLen = j - i;\r
1390                 }\r
1391         }\r
1392         strcpy(str, "");\r
1393         for(i = 0; i < 8; i++)\r
1394         {\r
1395                 if(i == MaxZero)\r
1396                 {\r
1397                         if(i == 0)\r
1398                                 strcat(str, ":");\r
1399                         strcat(str, ":");\r
1400                 }\r
1401                 else if(i < MaxZero || i >= MaxZero + MaxZeroLen)\r
1402                 {\r
1403                         sprintf(Tmp, "%x", (((int)p[i * 2] & 0xff) << 8) | ((int)p[i * 2 + 1] & 0xff));\r
1404                         strcat(str, Tmp);\r
1405                         if(i < 7)\r
1406                                 strcat(str, ":");\r
1407                 }\r
1408         }\r
1409         return pResult;\r
1410 }\r
1411 \r
1412 // IPv6対応のinet_ntoa相当の関数\r
1413 // ただしANSI用\r
1414 char* inet6_ntoa(struct in6_addr in6)\r
1415 {\r
1416         char* pResult;\r
1417         static char Adrs[40];\r
1418         pResult = NULL;\r
1419         memset(Adrs, 0, sizeof(Adrs));\r
1420         pResult = AddressToStringIPv6(Adrs, &in6);\r
1421         return pResult;\r
1422 }\r
1423 \r
1424 // IPv6対応のinet_addr相当の関数\r
1425 // ただしANSI用\r
1426 struct in6_addr inet6_addr(const char* cp)\r
1427 {\r
1428         struct in6_addr Result;\r
1429         int AfterZero;\r
1430         int i;\r
1431         char* p;\r
1432         memset(&Result, 0, sizeof(Result));\r
1433         AfterZero = 0;\r
1434         for(i = 0; i < 8; i++)\r
1435         {\r
1436                 if(!cp)\r
1437                 {\r
1438                         memset(&Result, 0xff, sizeof(Result));\r
1439                         break;\r
1440                 }\r
1441                 if(i >= AfterZero)\r
1442                 {\r
1443                         if(strncmp(cp, ":", 1) == 0)\r
1444                         {\r
1445                                 cp = cp + 1;\r
1446                                 if(i == 0 && strncmp(cp, ":", 1) == 0)\r
1447                                         cp = cp + 1;\r
1448                                 p = (char*)cp;\r
1449                                 AfterZero = 7;\r
1450                                 while(p = strstr(p, ":"))\r
1451                                 {\r
1452                                         p = p + 1;\r
1453                                         AfterZero--;\r
1454                                 }\r
1455                         }\r
1456                         else\r
1457                         {\r
1458                                 Result.u.Word[i] = (USHORT)strtol(cp, &p, 16);\r
1459                                 Result.u.Word[i] = ((Result.u.Word[i] & 0xff00) >> 8) | ((Result.u.Word[i] & 0x00ff) << 8);\r
1460                                 if(strncmp(p, ":", 1) != 0 && strlen(p) > 0)\r
1461                                 {\r
1462                                         memset(&Result, 0xff, sizeof(Result));\r
1463                                         break;\r
1464                                 }\r
1465                                 if(cp = strstr(cp, ":"))\r
1466                                         cp = cp + 1;\r
1467                         }\r
1468                 }\r
1469         }\r
1470         return Result;\r
1471 }\r
1472 \r
1473 // UTF-8対応\r
1474 \r
1475 static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1476 {\r
1477         BOOL bResult;\r
1478         punycode_uint* pUnicode;\r
1479         punycode_uint* p;\r
1480         BOOL bNeeded;\r
1481         LPCSTR InputString;\r
1482         punycode_uint Length;\r
1483         punycode_uint OutputLength;\r
1484         bResult = FALSE;\r
1485         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1486         {\r
1487                 p = pUnicode;\r
1488                 bNeeded = FALSE;\r
1489                 InputString = Input;\r
1490                 Length = 0;\r
1491                 while(*InputString != '\0')\r
1492                 {\r
1493                         *p = (punycode_uint)GetNextCharM(InputString, &InputString);\r
1494                         if(*p >= 0x80)\r
1495                                 bNeeded = TRUE;\r
1496                         p++;\r
1497                         Length++;\r
1498                 }\r
1499                 if(bNeeded)\r
1500                 {\r
1501                         if(Count >= strlen("xn--") + 1)\r
1502                         {\r
1503                                 strcpy(Output, "xn--");\r
1504                                 OutputLength = Count - strlen("xn--");\r
1505                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1506                                 {\r
1507                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1508                                         bResult = TRUE;\r
1509                                 }\r
1510                         }\r
1511                 }\r
1512                 free(pUnicode);\r
1513         }\r
1514         if(!bResult)\r
1515         {\r
1516                 if(Count >= strlen(Input) + 1)\r
1517                 {\r
1518                         strcpy(Output, Input);\r
1519                         bResult = TRUE;\r
1520                 }\r
1521         }\r
1522         return bResult;\r
1523 }\r
1524 \r
1525 static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1526 {\r
1527         BOOL bResult;\r
1528         DWORD Length;\r
1529         char* pm0;\r
1530         char* pm1;\r
1531         char* p;\r
1532         char* pNext;\r
1533         bResult = FALSE;\r
1534         Length = strlen(Input);\r
1535         if(pm0 = AllocateStringM(Length + 1))\r
1536         {\r
1537                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1538                 {\r
1539                         strcpy(pm0, Input);\r
1540                         p = pm0;\r
1541                         while(p)\r
1542                         {\r
1543                                 if(pNext = strchr(p, '.'))\r
1544                                 {\r
1545                                         *pNext = '\0';\r
1546                                         pNext++;\r
1547                                 }\r
1548                                 if(ConvertStringToPunycode(pm1, Length * 4, p))\r
1549                                         strcat(Output, pm1);\r
1550                                 if(pNext)\r
1551                                         strcat(Output, ".");\r
1552                                 p = pNext;\r
1553                         }\r
1554                         bResult = TRUE;\r
1555                         FreeDuplicatedString(pm1);\r
1556                 }\r
1557                 FreeDuplicatedString(pm0);\r
1558         }\r
1559         return bResult;\r
1560 }\r
1561 \r
1562 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1563 {\r
1564         HANDLE r = NULL;\r
1565         char* pa0 = NULL;\r
1566         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1567         {\r
1568                 if(ConvertNameToPunycode(pa0, name))\r
1569                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1570         }\r
1571         FreeDuplicatedString(pa0);\r
1572         return r;\r
1573 }\r
1574 \r
1575 static HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1576 {\r
1577         HANDLE r = NULL;\r
1578         char* pa0 = NULL;\r
1579         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1580         {\r
1581                 if(ConvertNameToPunycode(pa0, name))\r
1582                         r = WSAAsyncGetHostByNameIPv6(hWnd, wMsg, pa0, buf, buflen, Family);\r
1583         }\r
1584         FreeDuplicatedString(pa0);\r
1585         return r;\r
1586 }\r
1587 \r