OSDN Git Service

classify : fix DB id undefined.
[rec10/rec10-git.git] / b25-remote / SmartSock.cpp
1 // SmartSock.cpp: CSmartSock クラスのインプリメンテーション
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #include "SmartSock.h"
6 #include <stdio.h>
7 #include <sys/time.h>
8
9 #ifdef _DEBUG
10 #define new DEBUG_NEW
11 #endif
12
13 //#pragma warning(disable: 4101) // warning C4101: "ローカル変数は 1 度も使われていません。"
14 //#pragma warning(disable: 4996) // warning C4996: "This function or variable may be unsafe. Consider using _wsplitpath_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details"
15
16
17 //#pragma comment(lib, "WS2_32")
18
19
20 //////////////////////////////////////////////////////////////////////
21 // マクロ定義
22 //////////////////////////////////////////////////////////////////////
23
24 #define CHECK_FREESOCK(R)       if(m_Socket != INVALID_SOCKET){m_dwLastError = EC_SOCKINVALID; return (R);}
25 #define CHECK_TCPSOCK(R)        if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_TCP)){m_dwLastError = EC_SOCKINVALID; return (R);}
26 #define CHECK_UDPSOCK(R)        if((m_Socket == INVALID_SOCKET) || (m_bSockType != SOCKTYPE_UDP)){m_dwLastError = EC_SOCKINVALID; return (R);}
27
28
29 //////////////////////////////////////////////////////////////////////
30 // 構築/消滅
31 //////////////////////////////////////////////////////////////////////
32
33 DWORD CSmartSock::dwInstanceNum = 0UL;
34
35 CSmartSock::CSmartSock()
36         : m_Socket(INVALID_SOCKET)
37         , m_bSockType(SOCKTYPE_NON)
38         , m_dwLastError(EC_NOERROR)
39 {
40         // WinSock2初期化
41         if(!(dwInstanceNum++))InitWinSock2();
42 }
43
44 CSmartSock::~CSmartSock()
45 {
46         Close();
47
48         // WinSock2開放
49         if(!(--dwInstanceNum))FreeWinSock2();
50 }
51
52 const BOOL CSmartSock::Connect(LPCTSTR lpszHost, const WORD wPort, const DWORD dwTimeOut)
53 {
54         CHECK_FREESOCK(FALSE);
55
56         if(!lpszHost){
57                 m_dwLastError = EC_PARAMINVALID;
58                 return FALSE;
59                 }
60                 
61         // アドレス名からIPアドレス取得
62         const DWORD dwIP = HostToIP(lpszHost);
63
64         if(dwIP == INADDR_NONE){
65                 m_dwLastError = EC_SOCKERROR;
66                 return FALSE;           
67                 }
68         
69         return Connect(dwIP, wPort, dwTimeOut);
70 }
71
72 const BOOL CSmartSock::Connect(const DWORD dwIP, const WORD wPort, const DWORD dwTimeOut)
73 {
74         CHECK_FREESOCK(FALSE);
75
76         // ソケット作成
77         if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
78                 m_dwLastError = EC_SOCKERROR;
79                 return FALSE;           
80                 }
81
82         // アドレス設定
83         SOCKADDR_IN SockAddr;
84         SockAddr.sin_family = AF_INET;
85         SockAddr.sin_port = htons(wPort);
86         SockAddr.sin_addr.s_addr = htonl(dwIP);
87
88         // 同期コネクト
89         if(!dwTimeOut){
90                 if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr))){
91                         Close();
92                         m_dwLastError = EC_SOCKERROR;
93                         return FALSE;           
94                         }
95         
96                 m_dwLastError = EC_NOERROR;
97                 return TRUE;
98         }
99
100         // 非同期コネクト
101         u_long nArg;
102         fd_set FdSet;
103         struct timeval TimeVal;
104         TimeVal.tv_sec = 10UL;
105         TimeVal.tv_usec = 0UL;
106         nArg = fcntl(m_Socket, F_GETFL, 0);
107         FD_ZERO(&FdSet);
108         FD_SET(m_Socket, &FdSet);
109
110         try{
111                 // 非同期に切り替え
112                 if(::fcntl(m_Socket, F_SETFL, nArg | O_NONBLOCK) == SOCKET_ERROR)throw (const DWORD)__LINE__;
113
114                 // コネクト
115                 if(::connect(m_Socket, (PSOCKADDR)&SockAddr, sizeof(sockaddr)) != SOCKET_ERROR)throw (const DWORD)__LINE__;
116
117                 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS)throw (const DWORD)__LINE__;
118
119                 // 接続完了待ち
120                 if(!::select(32, NULL, &FdSet, NULL, &TimeVal))throw (const DWORD)__LINE__;
121
122                 // タイムアウト判定
123                 if(!FD_ISSET(m_Socket, &FdSet)){
124                         Close();
125                         m_dwLastError = EC_TIMEOUT;
126                         return FALSE;
127                         }
128
129                 // 同期に切り替え
130                 if(::fcntl(m_Socket, F_SETFL, nArg) == SOCKET_ERROR)throw (const DWORD)__LINE__;
131                 }
132         catch(const DWORD dwLine){
133                 // エラー発生
134                 Close();
135                 m_dwLastError = EC_SOCKERROR;
136                 return FALSE;
137                 }
138
139         m_bSockType = SOCKTYPE_TCP;
140         m_dwLastError = EC_NOERROR;
141
142         return TRUE;
143 }
144
145 const BOOL CSmartSock::Listen(const WORD wPort)
146 {
147         CHECK_FREESOCK(FALSE);
148
149         // ソケット作成
150         if((m_Socket = ::socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
151                 m_dwLastError = EC_SOCKERROR;
152                 return FALSE;           
153                 }
154
155         // アドレス設定
156         SOCKADDR_IN SockAddr;
157         SockAddr.sin_family = AF_INET;
158         SockAddr.sin_port = htons(wPort);
159         SockAddr.sin_addr.s_addr = INADDR_ANY;
160
161         try{
162                 // 「アドレス使用中」エラーを回避
163                 int on = 1;
164                 setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
165
166                 // バインド
167                 if(::bind(m_Socket, (PSOCKADDR)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR)throw (const DWORD)__LINE__;
168
169                 // 接続受け入れ
170                 if(::listen(m_Socket, 5) == SOCKET_ERROR)throw (const DWORD)__LINE__;
171                 }
172         catch(const DWORD dwLine){
173                 // エラー発生
174                 Close();
175                 m_dwLastError = EC_SOCKERROR;
176                 return FALSE;
177                 }
178
179         m_bSockType = SOCKTYPE_TCP;
180         m_dwLastError = EC_NOERROR;
181
182         return TRUE;
183 }
184
185 CSmartSock * CSmartSock::Accept(void)
186 {
187         CHECK_TCPSOCK(FALSE);
188         
189         SOCKADDR_IN AddrIn;
190         memset(&AddrIn, 0, sizeof(AddrIn));
191         socklen_t iAddrLen = sizeof(AddrIn);
192
193         // コネクト受け入れ
194         SOCKET SockIn = ::accept(m_Socket, (sockaddr *)&AddrIn, &iAddrLen);
195
196         if(SockIn == INVALID_SOCKET){
197                 Close();
198                 m_dwLastError = EC_SOCKERROR;
199                 return NULL;
200                 }
201
202         CSmartSock *pNewSock = new CSmartSock;
203         pNewSock->m_Socket = SockIn;
204         pNewSock->m_bSockType = SOCKTYPE_TCP;
205
206         m_dwLastError = EC_NOERROR;
207
208         return pNewSock;
209 }
210
211 const BOOL CSmartSock::Send(const BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)
212 {
213         CHECK_TCPSOCK(FALSE);
214
215         if(!pBuff || !dwLen){
216                 m_dwLastError = EC_PARAMINVALID;
217                 return FALSE;
218                 }
219
220         // 指定サイズ送信
221         DWORD dwRef = 0UL, dwSend = 0UL;
222
223         do{
224                 dwRef = SendOnce(pBuff + dwSend, dwLen - dwSend, dwTimeOut);
225                 if(!dwRef) return FALSE;
226         }
227         while((dwSend += dwRef) < dwLen);
228
229         return TRUE;
230 }
231
232 const BOOL CSmartSock::Recv(BYTE *pBuff, const DWORD dwLen, const DWORD dwTimeOut)
233 {
234         CHECK_TCPSOCK(FALSE);
235
236         if(!pBuff || !dwLen){
237                 m_dwLastError = EC_PARAMINVALID;
238                 return FALSE;
239         }
240
241         // 指定サイズ受信
242         DWORD dwRef = 0UL, dwRecv = 0UL;
243
244         do{
245                 if(!(dwRef = RecvOnce(pBuff + dwRecv, dwLen - dwRecv, dwTimeOut)))return FALSE;
246         }
247         while((dwRecv += dwRef) < dwLen);
248
249         return TRUE;
250 }
251
252 const DWORD CSmartSock::SendOnce(const BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)
253 {
254         CHECK_TCPSOCK(0UL);
255
256         if(!pBuff || !dwMaxLen){
257                 m_dwLastError = EC_PARAMINVALID;
258                 return FALSE;
259                 }
260         
261         // タイムアウト設定
262         struct timeval stTimeOut;
263
264         stTimeOut.tv_sec = 10UL;
265         stTimeOut.tv_usec = 0UL;
266         if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){
267                 Close();
268                 m_dwLastError = EC_SOCKERROR;
269                 return 0UL;
270         }
271
272         // 送信
273         const int iRef = ::send(m_Socket, (const char *)pBuff, dwMaxLen, 0);
274
275         if((iRef == SOCKET_ERROR) || !iRef){
276                 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
277                         m_dwLastError = EC_TIMEOUT;
278                         return 0UL;
279                         }
280                 else{
281                         Close();
282                         m_dwLastError = EC_SOCKERROR;
283                         return 0UL;
284                         }
285                 }
286                 
287         m_dwLastError = EC_NOERROR;
288                 
289         return (DWORD)iRef;
290 }
291
292 const DWORD CSmartSock::RecvOnce(BYTE *pBuff, const DWORD dwMaxLen, const DWORD dwTimeOut)
293 {
294         CHECK_TCPSOCK(0UL);
295         
296         if(!pBuff || !dwMaxLen){
297                 m_dwLastError = EC_PARAMINVALID;
298                 return FALSE;
299                 }
300
301         // タイムアウト値設定
302         struct timeval stTimeOut;
303
304         stTimeOut.tv_sec = 10UL;
305         stTimeOut.tv_usec = 0UL;
306         if(::setsockopt(m_Socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&stTimeOut, sizeof(struct timeval))){
307                 Close();
308                 m_dwLastError = EC_SOCKERROR;
309                 return 0UL;
310         }
311         
312         // 受信
313         int iRef = ::recv(m_Socket, (char *)pBuff, dwMaxLen, 0);
314
315         if ( !iRef ) {
316                 Close();
317                 m_dwLastError = EC_SOCKERROR;
318                 return 0UL;
319         }
320
321         if( iRef == SOCKET_ERROR ){
322                 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS){
323                         m_dwLastError = EC_TIMEOUT;
324                         return 0UL;
325                         }
326                 else{
327                         Close();
328                         m_dwLastError = EC_SOCKERROR;
329                         return 0UL;
330                         }
331                 }
332
333         m_dwLastError = EC_NOERROR;
334                 
335         return (DWORD)iRef;
336 }
337
338 const BOOL CSmartSock::GetLocalAddr(DWORD *pdwIP, WORD *pwPort)
339 {
340         CHECK_TCPSOCK(FALSE);
341
342         struct sockaddr_in LocalAddr;
343         socklen_t AddrLen = sizeof(LocalAddr);
344         
345         // ローカルアドレス取得
346         if(::getsockname(m_Socket, (struct sockaddr *)&LocalAddr, &AddrLen) == SOCKET_ERROR){
347                 m_dwLastError = EC_SOCKERROR;
348                 return FALSE;
349                 }
350
351         if(pdwIP)*pdwIP = htonl(LocalAddr.sin_addr.s_addr);
352         if(pwPort)*pwPort = ntohs(LocalAddr.sin_port);
353
354         m_dwLastError = EC_NOERROR;
355
356         return TRUE;
357 }
358
359 const BOOL CSmartSock::GetPeerAddr(DWORD *pIP, WORD *pPort)
360 {
361         CHECK_TCPSOCK(FALSE);
362
363         struct sockaddr_in PeerAddr;
364         socklen_t AddrLen = sizeof(PeerAddr);
365         
366         // ピアアドレス取得
367         if(::getpeername(m_Socket, (struct sockaddr *)&PeerAddr, &AddrLen) == SOCKET_ERROR){
368                 m_dwLastError = EC_SOCKERROR;
369                 return FALSE;
370                 }
371
372         if(pIP)*pIP = htonl(PeerAddr.sin_addr.s_addr);
373         if(pPort)*pPort = ntohs(PeerAddr.sin_port);
374
375         m_dwLastError = EC_NOERROR;
376
377         return TRUE;
378 }
379
380 const BOOL CSmartSock::Bind()
381 {
382         CHECK_FREESOCK(FALSE);
383
384         // UDPソケット作成
385         if((m_Socket = ::socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET){
386                 m_dwLastError = EC_SOCKERROR;
387                 return FALSE;
388                 }
389
390         // アドレス設定
391         SOCKADDR_IN SockAddr;
392         SockAddr.sin_family = AF_INET;
393         SockAddr.sin_port = 0U;
394         SockAddr.sin_addr.s_addr = INADDR_ANY;
395
396         // バインド
397         if(::bind(m_Socket, (struct sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR){
398                 Close();
399                 m_dwLastError = EC_SOCKERROR;
400                 return FALSE;
401                 }
402
403         m_dwLastError = EC_NOERROR;
404         m_bSockType = SOCKTYPE_UDP;
405         
406         return TRUE;
407 }
408
409 const DWORD CSmartSock::SendTo(const DWORD dwIP, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)
410 {
411         CHECK_UDPSOCK(0UL);
412
413         if(!pBuff || !dwLen){
414                 m_dwLastError = EC_PARAMINVALID;
415                 return 0UL;
416                 }
417
418         // アドレス設定
419         SOCKADDR_IN SockAddr;
420         SockAddr.sin_family = AF_INET;
421         SockAddr.sin_port = htons(wPort);
422         SockAddr.sin_addr.s_addr = htonl(dwIP);
423
424         // 送信
425         int iSend = sendto(m_Socket, (const char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, sizeof(SockAddr));
426         
427         if(iSend == SOCKET_ERROR){
428                 m_dwLastError = EC_SOCKERROR;
429                 return 0UL;
430                 }
431
432         m_dwLastError = EC_NOERROR;
433
434         return (DWORD)iSend;
435 }
436
437 const DWORD CSmartSock::SendTo(LPCTSTR lpszHost, const WORD wPort, const BYTE *pBuff, const DWORD dwLen)
438 {
439         CHECK_UDPSOCK(0UL);
440
441         if(!lpszHost || !pBuff || !dwLen){
442                 m_dwLastError = EC_PARAMINVALID;
443                 return 0UL;
444                 }
445                 
446         // アドレス名からIPアドレス取得
447         const DWORD dwIP = HostToIP(lpszHost);
448
449         if(dwIP == INADDR_NONE){
450                 m_dwLastError = EC_SOCKERROR;
451                 return 0UL;             
452                 }
453         
454         return SendTo(dwIP, wPort, pBuff, dwLen);
455 }
456
457 const DWORD CSmartSock::RecvFrom(BYTE *pBuff, const DWORD dwLen, DWORD *pdwIP, WORD *pwPort)
458 {
459         CHECK_UDPSOCK(0UL);
460
461         if(!pBuff || !dwLen){
462                 m_dwLastError = EC_PARAMINVALID;
463                 return 0UL;
464                 }
465
466         // アドレス設定
467         socklen_t iSockSize = sizeof(SOCKADDR_IN);
468         SOCKADDR_IN SockAddr;
469         SockAddr.sin_family = AF_INET;
470         SockAddr.sin_port = 0U;
471         SockAddr.sin_addr.s_addr = 0UL;
472
473         // 受信
474         const int iRecv = ::recvfrom(m_Socket, (char *)pBuff, dwLen, 0, (struct sockaddr *)&SockAddr, &iSockSize);
475
476         if(iRecv == SOCKET_ERROR){
477                 m_dwLastError = EC_SOCKERROR;
478                 return 0UL;
479                 }
480
481         if(pdwIP)*pdwIP = SockAddr.sin_addr.s_addr;
482         if(pwPort)*pwPort = ntohs(SockAddr.sin_port);
483
484         m_dwLastError = EC_NOERROR;
485
486         return (DWORD)iRecv;
487 }
488
489 const BOOL CSmartSock::Close()
490 {
491         // ソケットクローズ
492         if(m_Socket != INVALID_SOCKET){
493                 if(m_bSockType == SOCKTYPE_TCP){
494                         char byData;
495                         ::shutdown(m_Socket, SD_BOTH);
496                         while(::recv(m_Socket, &byData, 1, 0) == 1);
497                         }
498
499                 ::close(m_Socket);
500                 m_Socket = INVALID_SOCKET;
501                 }
502         
503         m_bSockType = SOCKTYPE_NON;
504         m_dwLastError = EC_NOERROR;
505         
506         return TRUE;
507 }
508
509 const DWORD CSmartSock::HostToIP(LPCTSTR lpszHost)
510 {
511 #ifdef _UNICODE
512         char szHost[1024] = {"\0"};
513         ::wcstombs(szHost, lpszHost, sizeof(szHost) - 1);
514 #else
515         LPCSTR szHost = lpszHost;
516 #endif
517
518         // ホスト名からIPアドレス取得
519         const DWORD dwIP = ::inet_addr(szHost);
520
521         if(dwIP == INADDR_NONE){
522                 struct hostent *pHost = ::gethostbyname(szHost);
523                 if(!pHost){             
524                         return INADDR_NONE;
525                         }
526                 else return *((DWORD *)pHost->h_addr_list[0]);
527                 }
528         else return htonl(dwIP);
529 }
530
531 const DWORD CSmartSock::IPToHost(LPTSTR lpszHost, const DWORD dwIP)
532 {
533         if(!lpszHost)return FALSE;
534
535         // IPアドレスからホスト名取得
536         const DWORD dwNetIP = htonl(dwIP);
537         struct hostent *pHost = ::gethostbyaddr((const char *)&dwNetIP, sizeof(dwNetIP), AF_INET);
538         if(!pHost)return FALSE;
539
540 #ifdef _UNICODE
541         ::mbstowcs(lpszHost, pHost->h_name, ::lstrlenA(pHost->h_name));
542 #else
543         ::strcpy(lpszHost, pHost->h_name);
544 #endif
545
546         return ::strlen(lpszHost);
547 }
548
549 const DWORD CSmartSock::GetLastError() const
550 {
551         // 最後に発生したエラーを返す
552         return m_dwLastError;
553 }
554
555 const BOOL CSmartSock::InitWinSock2(void)
556 {
557 #ifdef _UNICODE
558         ::setlocale(LC_ALL, "japanese");
559 #endif
560 /*
561         WSADATA WsaData;
562
563         // WinSock2初期化
564         if(::WSAStartup(MAKEWORD(2, 2), &WsaData))return FALSE;
565
566         if((LOBYTE(WsaData.wVersion) != 2U) || (HIBYTE(WsaData.wVersion) != 2U))return FALSE;
567 */
568         return TRUE;
569 }
570
571 const BOOL CSmartSock::FreeWinSock2(void)
572 {
573 /*
574         // WinSock2開放
575         return (::WSACleanup())? TRUE : FALSE;
576 */
577         return TRUE;
578 }