OSDN Git Service

509ba07f97d2cef155cf9a7b5e6b03eeebe5ccba
[peercast-im/PeerCastIM.git] / c: / Git / PeerCast.root / PeerCast / core / win32 / wsocket.cpp
1 // ------------------------------------------------
2 // File : wsocket.cpp
3 // Date: 4-apr-2002
4 // Author: giles
5 // Desc: 
6 //              Windows version of ClientSocket. Handles the nitty gritty of actually
7 //              reading and writing TCP
8 //              
9 // (c) 2002 peercast.org
10 // ------------------------------------------------
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 // ------------------------------------------------
21
22 // TODO: fix socket closing
23
24
25 //#include "stdafx.h"
26 #include "winsock2.h"
27 #include <windows.h>
28 #include <stdio.h>
29 #include "wsocket.h"
30 #include "..\common\stats.h"
31 #ifdef _DEBUG
32 #include "chkMemoryLeak.h"
33 #define DEBUG_NEW new(__FILE__, __LINE__)
34 #define new DEBUG_NEW
35 #endif
36
37
38 // --------------------------------------------------
39 void WSAClientSocket::init()
40 {
41         WORD wVersionRequested;
42         WSADATA wsaData;
43         int err;
44     
45         wVersionRequested = MAKEWORD( 2, 0 );
46         err = WSAStartup( wVersionRequested, &wsaData );
47         if ( err != 0 )
48                 throw SockException("Unable to init sockets");
49
50     //LOG4("WSAStartup:  OK");
51
52 }
53 // --------------------------------------------------
54 bool ClientSocket::getHostname(char *str,size_t size,unsigned int ip) //JP-MOD
55 {
56         if(size == 0)
57                 return false;
58
59         HOSTENT *he;
60
61         ip = htonl(ip);
62
63         he = gethostbyaddr((char *)&ip,sizeof(ip),AF_INET);
64
65         if (he)
66         {
67                 LOG_DEBUG("getHostname: %d.%d.%d.%d -> %s", ((BYTE*)&ip)[0], ((BYTE*)&ip)[1], ((BYTE*)&ip)[2], ((BYTE*)&ip)[3], he->h_name);
68                 strncpy(str,he->h_name,size-1);
69                 str[size-1] = '\0';
70                 return true;
71         }else
72                 return false;
73 }
74
75 unsigned int cache_ip = 0;
76 unsigned int cache_time = 0;
77
78 // --------------------------------------------------
79 unsigned int ClientSocket::getIP(char *name)
80 {
81         unsigned int ctime = sys->getTime();
82         bool null_flg = (name == NULL);
83
84         if (null_flg){
85                 if ((cache_time != 0) && (cache_time + 60 > ctime)){
86                         return cache_ip;
87                 } else {
88                         cache_time = 0;
89                         cache_ip = 0;
90                 }
91         }
92
93         char szHostName[256];
94
95         if (!name)
96         {
97                 if (gethostname(szHostName, sizeof(szHostName))==0)
98                         name = szHostName;
99                 else
100                         return 0;
101         }
102
103         HOSTENT *he = WSAClientSocket::resolveHost(name);
104
105         if (!he)
106                 return 0;
107
108
109         LPSTR lpAddr = he->h_addr_list[0];
110         if (lpAddr)
111         {
112                 unsigned int ret;
113                 struct in_addr  inAddr;
114                 memmove (&inAddr, lpAddr, 4);
115
116                 ret =  inAddr.S_un.S_un_b.s_b1<<24 |
117                            inAddr.S_un.S_un_b.s_b2<<16 |
118                            inAddr.S_un.S_un_b.s_b3<<8 |
119                            inAddr.S_un.S_un_b.s_b4;
120
121                 if (null_flg){
122                         cache_ip = ret;
123                         cache_time = ctime;
124                 }
125                 return ret;
126         }
127         return 0;
128 }
129 // --------------------------------------------------
130 void WSAClientSocket::setLinger(int sec)
131 {
132         linger linger;
133         linger.l_onoff = (sec>0)?1:0;
134     linger.l_linger = sec;
135
136         if (setsockopt(sockNum, SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof (linger)) == -1) 
137                 throw SockException("Unable to set LINGER");
138 }
139
140 // --------------------------------------------------
141 void WSAClientSocket::setBlocking(bool yes)
142 {
143         unsigned long op = yes ? 0 : 1;
144         if (ioctlsocket(sockNum, FIONBIO, &op) == SOCKET_ERROR)
145                 throw SockException("Can`t set blocking");
146 }
147 // --------------------------------------------------
148 void WSAClientSocket::setNagle(bool on)
149 {
150     int nodelay = (on==false);
151         if (setsockopt(sockNum, SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof nodelay) == -1) 
152                 throw SockException("Unable to set NODELAY");
153
154 }
155
156 // --------------------------------------------------
157 void WSAClientSocket::setReuse(bool yes)
158 {
159         unsigned long op = yes ? 1 : 0;
160         if (setsockopt(sockNum,SOL_SOCKET,SO_REUSEADDR,(char *)&op,sizeof(unsigned long)) == -1) 
161                 throw SockException("Unable to set REUSE");
162 }
163
164 // --------------------------------------------------
165 void WSAClientSocket::setBufSize(int size)
166 {
167         int oldop;
168         int op = size;
169         int len = sizeof(op);
170         if (getsockopt(sockNum,SOL_SOCKET,SO_RCVBUF,(char *)&oldop,&len) == -1) {
171                 LOG_DEBUG("Unable to get RCVBUF");
172         } else if (oldop < size) {
173                 if (setsockopt(sockNum,SOL_SOCKET,SO_RCVBUF,(char *)&op,len) == -1) 
174                         LOG_DEBUG("Unable to set RCVBUF");
175                 //else
176                 //      LOG_DEBUG("*** recvbufsize:%d -> %d", oldop, op);
177         }
178
179         if (getsockopt(sockNum,SOL_SOCKET,SO_SNDBUF,(char *)&oldop,&len) == -1) {
180                 LOG_DEBUG("Unable to get SNDBUF");
181         } else if (oldop < size) {
182                 if (setsockopt(sockNum,SOL_SOCKET,SO_SNDBUF,(char *)&op,len) == -1) 
183                         LOG_DEBUG("Unable to set SNDBUF");
184                 //else
185                 //      LOG_DEBUG("*** sendbufsize: %d -> %d", oldop, op);
186         }
187 }
188
189 // --------------------------------------------------
190 HOSTENT *WSAClientSocket::resolveHost(const char *hostName)
191 {
192         HOSTENT *he;
193
194         if ((he = gethostbyname(hostName)) == NULL)
195         {
196                 // if failed, try using gethostbyaddr instead
197
198                 unsigned long ip = inet_addr(hostName);
199                 
200                 if (ip == INADDR_NONE)
201                         return NULL;
202
203                 if ((he = gethostbyaddr((char *)&ip,sizeof(ip),AF_INET)) == NULL)
204                         return NULL;    
205         }
206         return he;
207 }
208
209 // --------------------------------------------------
210 void WSAClientSocket::open(Host &rh)
211 {
212         sockNum = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
213
214         if (sockNum == INVALID_SOCKET)
215                 throw SockException("Can`t open socket");
216
217         setBlocking(false);
218 #ifdef DISABLE_NAGLE
219         setNagle(false);
220 #endif
221         setBufSize(65535);
222
223         host = rh;
224
225         memset(&remoteAddr,0,sizeof(remoteAddr));
226
227         remoteAddr.sin_family = AF_INET;
228         remoteAddr.sin_port = htons(host.port);
229         remoteAddr.sin_addr.S_un.S_addr = htonl(host.ip);
230
231 }
232 // --------------------------------------------------
233 void WSAClientSocket::checkTimeout(bool r, bool w)
234 {
235     int err = WSAGetLastError();
236     if (err == WSAEWOULDBLOCK)
237     {
238
239                 timeval timeout;
240                 fd_set read_fds;
241                 fd_set write_fds;
242
243                 timeout.tv_sec = 0;
244                 timeout.tv_usec = 0;
245
246         FD_ZERO (&write_fds);
247                 if (w)
248                 {
249                         timeout.tv_sec = (int)this->writeTimeout/1000;
250                         FD_SET (sockNum, &write_fds);
251                 }
252
253         FD_ZERO (&read_fds);
254                 if (r)
255                 {
256                         timeout.tv_sec = (int)this->readTimeout/1000;
257                 FD_SET (sockNum, &read_fds);
258                 }
259
260                 timeval *tp;
261                 if (timeout.tv_sec)
262                         tp = &timeout;
263                 else
264                         tp = NULL;
265
266
267                 int r=select (NULL, &read_fds, &write_fds, NULL, tp);
268
269         if (r == 0)
270                         throw TimeoutException();
271                 else if (r == SOCKET_ERROR)
272                         throw SockException("select failed.");
273
274         }else{
275                 char str[32];
276                 sprintf(str,"%d",err);
277                 throw SockException(str);
278         }
279 }
280
281 // --------------------------------------------------
282 void WSAClientSocket::checkTimeout2(bool r, bool w)
283 {
284     {
285
286                 timeval timeout;
287                 fd_set read_fds;
288                 fd_set write_fds;
289
290                 timeout.tv_sec = 0;
291                 timeout.tv_usec = 0;
292
293         FD_ZERO (&write_fds);
294                 if (w)
295                 {
296                         timeout.tv_sec = (int)this->writeTimeout/1000;
297                         FD_SET (sockNum, &write_fds);
298                 }
299
300         FD_ZERO (&read_fds);
301                 if (r)
302                 {
303                         timeout.tv_sec = (int)this->readTimeout/1000;
304                 FD_SET (sockNum, &read_fds);
305                 }
306
307                 timeval *tp;
308                 if (timeout.tv_sec)
309                         tp = &timeout;
310                 else
311                         tp = NULL;
312
313
314                 int r=select (NULL, &read_fds, &write_fds, NULL, tp);
315
316         if (r == 0)
317                         throw TimeoutException();
318                 else if (r == SOCKET_ERROR)
319                         throw SockException("select failed.");
320         }
321 }
322
323 // --------------------------------------------------
324 Host WSAClientSocket::getLocalHost()
325 {
326         struct sockaddr_in localAddr;
327
328         int len = sizeof(localAddr);
329     if (getsockname(sockNum, (sockaddr *)&localAddr, &len) == 0)
330                 return Host(SWAP4(localAddr.sin_addr.s_addr),0);
331         else
332                 return Host(0,0);
333 }
334
335 // --------------------------------------------------
336 void WSAClientSocket::connect()
337 {
338         if (::connect(sockNum,(struct sockaddr *)&remoteAddr,sizeof(remoteAddr)) == SOCKET_ERROR)
339                 checkTimeout(false,true);
340
341 }
342 // --------------------------------------------------
343 int WSAClientSocket::read(void *p, int l)
344 {
345         int bytesRead=0;
346
347         while (l)
348         {
349                 if (rbDataSize >= l) {
350                         memcpy(p, &apReadBuf[rbPos], l);
351                         rbPos += l;
352                         rbDataSize -= l;
353                         return l;
354                 } else if (rbDataSize > 0) {
355                         memcpy(p, &apReadBuf[rbPos], rbDataSize);
356                         p = (char *) p + rbDataSize;
357                         l -= rbDataSize;
358                         bytesRead += rbDataSize;
359                 }
360
361                 rbPos = 0;
362                 rbDataSize = 0;
363                 //int r = recv(sockNum, (char *)p, l, 0);
364                 int r = recv(sockNum, apReadBuf, RBSIZE, 0);
365                 if (r == SOCKET_ERROR)
366                 {
367                         // non-blocking sockets always fall through to here
368                         checkTimeout(true,false);
369
370                 }else if (r == 0)
371                 {
372                         throw EOFException("Closed on read");
373
374                 }else
375                 {
376                         stats.add(Stats::BYTESIN,r);
377                         if (host.localIP())
378                                 stats.add(Stats::LOCALBYTESIN,r);
379                         updateTotals(r,0);
380                         //bytesRead += r;
381                         //l -= r;
382                         //p = (char *)p+r;
383
384                         rbDataSize += r;
385                 }
386         }
387         return bytesRead;
388 }
389 // --------------------------------------------------
390 int WSAClientSocket::readUpto(void *p, int l)
391 {
392         int bytesRead=0;
393         while (l)
394         {
395                 int r = recv(sockNum, (char *)p, l, 0);
396                 if (r == SOCKET_ERROR)
397                 {
398                         // non-blocking sockets always fall through to here
399                         //checkTimeout(true,false);
400                         return r;
401
402                 }else if (r == 0)
403                 {
404                         break;
405                 }else
406                 {
407                         stats.add(Stats::BYTESIN,r);
408                         if (host.localIP())
409                                 stats.add(Stats::LOCALBYTESIN,r);
410                         updateTotals(r,0);
411                         bytesRead += r;
412                         l -= r;
413                         p = (char *)p+r;
414                 }
415                 if (bytesRead) break;
416         }
417         return bytesRead;
418 }
419
420
421 // --------------------------------------------------
422 void WSAClientSocket::write(const void *p, int l)
423 {
424         while (l)
425         {
426                 int r = send(sockNum, (char *)p, l, 0);
427                 if (r == SOCKET_ERROR)
428                 {
429                         checkTimeout(false,true);       
430                 }
431                 else if (r == 0)
432                 {
433                         throw SockException("Closed on write");
434                 }
435                 else
436                 if (r > 0)
437                 {
438                         stats.add(Stats::BYTESOUT,r);
439                         if (host.localIP())
440                                 stats.add(Stats::LOCALBYTESOUT,r);
441
442                         updateTotals(0,r);
443                         l -= r;
444                         p = (char *)p+r;
445                 }
446         }
447 }
448
449 // --------------------------------------------------
450 void WSAClientSocket::bufferingWrite(const void *p, int l)
451 {
452         if (bufList.isNull() && p != NULL){
453                 while(l){
454                         int r = send(sockNum, (char *)p, l, 0);
455                         if (r == SOCKET_ERROR){
456                                 int err = WSAGetLastError();
457                                 if (err == WSAEWOULDBLOCK){
458                                         bufList.add(p, l);
459 //                                      LOG_DEBUG("normal add");
460                                         break;
461                                 } else {
462                                         char str[32];
463                                         sprintf(str,"%d",err);
464                                         throw SockException(str);
465                                 }
466                         } else if (r == 0) {
467                                 throw SockException("Closed on write");
468                         } else if (r > 0){
469                                 stats.add(Stats::BYTESOUT,r);
470                                 if (host.localIP())
471                                         stats.add(Stats::LOCALBYTESOUT,r);
472
473                                 updateTotals(0,r);
474                                 l -= r;
475                                 p = (char *)p+r;
476                         }
477                 }
478         } else {
479 //              LOG_DEBUG("***************BufferingWrite");
480                 if (p)
481                         bufList.add(p,l);
482
483                 bool flg = true;
484
485                 while(flg){
486                         SocketBuffer *tmp;
487                         tmp = bufList.getTop();
488
489                         if (tmp){
490 //                              LOG_DEBUG("tmp->pos = %d, tmp->len = %d, %d", tmp->pos, tmp->len, tmp);
491                                 while(tmp->pos < tmp->len){
492                                         int r = send(sockNum, (char*)(tmp->buf + tmp->pos), tmp->len - tmp->pos, 0);
493 //                                      LOG_DEBUG("send = %d", r);
494                                         if (r == SOCKET_ERROR){
495                                                 int err = WSAGetLastError();
496                                                 if (err == WSAEWOULDBLOCK){
497                                                         flg = false;
498                                                         break;
499                                                 } else {
500                                                         bufList.clear();
501                                                         char str[32];
502                                                         sprintf(str,"%d",err);
503                                                         throw SockException(str);
504                                                 }
505                                         } else if (r == 0){
506                                                 bufList.clear();
507                                                 throw SockException("Closed on write");
508                                         } else if (r > 0){
509                                                 stats.add(Stats::BYTESOUT,r);
510                                                 if (host.localIP())
511                                                         stats.add(Stats::LOCALBYTESOUT,r);
512
513                                                 updateTotals(0,r);
514
515                                                 tmp->pos += r;
516                                                 if (tmp->pos >= tmp->len){
517 //                                                      LOG_DEBUG("deleteTop");
518                                                         bufList.deleteTop();
519                                                         break;
520                                                 }
521                                         }
522                                 }
523                         } else {
524                                 flg = false;
525                         }
526                 }
527 //              LOG_DEBUG("bufferingWrite end");
528         }
529 }
530
531 // --------------------------------------------------
532 void WSAClientSocket::checkBuffering(bool r, bool w)
533 {
534     int err = WSAGetLastError();
535     if (err == WSAEWOULDBLOCK)
536     {
537
538                 timeval timeout;
539                 fd_set read_fds;
540                 fd_set write_fds;
541
542                 timeout.tv_sec = 0;
543                 timeout.tv_usec = 0;
544
545         FD_ZERO (&write_fds);
546                 if (w)
547                 {
548                         timeout.tv_sec = (int)this->writeTimeout/1000;
549                         FD_SET (sockNum, &write_fds);
550                 }
551
552         FD_ZERO (&read_fds);
553                 if (r)
554                 {
555                         timeout.tv_sec = (int)this->readTimeout/1000;
556                 FD_SET (sockNum, &read_fds);
557                 }
558
559                 timeval *tp;
560                 if (timeout.tv_sec)
561                         tp = &timeout;
562                 else
563                         tp = NULL;
564
565
566                 int r=select (NULL, &read_fds, &write_fds, NULL, tp);
567
568         if (r == 0)
569                         throw TimeoutException();
570                 else if (r == SOCKET_ERROR)
571                         throw SockException("select failed.");
572
573         }else{
574                 char str[32];
575                 sprintf(str,"%d",err);
576                 throw SockException(str);
577         }
578 }
579
580 // --------------------------------------------------
581 void WSAClientSocket::bind(Host &h)
582 {
583         struct sockaddr_in localAddr;
584
585         if ((sockNum = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
586                 throw SockException("Can`t open socket");
587
588         setBlocking(false);
589         setReuse(true);
590
591         memset(&localAddr,0,sizeof(localAddr));
592         localAddr.sin_family = AF_INET;
593         localAddr.sin_port = htons(h.port);
594         localAddr.sin_addr.s_addr = INADDR_ANY;
595
596         if( ::bind (sockNum, (sockaddr *)&localAddr, sizeof(localAddr)) == -1)
597                 throw SockException("Can`t bind socket");
598
599         if (::listen(sockNum,SOMAXCONN))
600                 throw SockException("Can`t listen",WSAGetLastError());
601
602         host = h;
603 }
604 // --------------------------------------------------
605 ClientSocket *WSAClientSocket::accept()
606 {
607
608         int fromSize = sizeof(sockaddr_in);
609         sockaddr_in from;
610
611         SOCKET conSock = ::accept(sockNum,(sockaddr *)&from,&fromSize);
612
613
614         if (conSock ==  INVALID_SOCKET)
615                 return NULL;
616
617         
618     WSAClientSocket *cs = new WSAClientSocket();
619         cs->sockNum = conSock;
620
621         cs->host.port = (from.sin_port & 0xff) << 8 | ((from.sin_port >> 8) & 0xff);
622         cs->host.ip = from.sin_addr.S_un.S_un_b.s_b1<<24 |
623                                   from.sin_addr.S_un.S_un_b.s_b2<<16 |
624                                   from.sin_addr.S_un.S_un_b.s_b3<<8 |
625                                   from.sin_addr.S_un.S_un_b.s_b4;
626
627
628         cs->setBlocking(false);
629 #ifdef DISABLE_NAGLE
630         cs->setNagle(false);
631 #endif
632         cs->setBufSize(65535);
633
634         return cs;
635 }
636
637 // --------------------------------------------------
638 void WSAClientSocket::close()
639 {
640         sockLock.on();
641         if (sockNum)
642         {
643                 shutdown(sockNum,SD_SEND); // fix from rev5
644
645                 setReadTimeout(2000);
646                 unsigned int stime = sys->getTime();
647                 try
648                 {
649                         char c[1024];
650                         while (read(&c, sizeof(c)) > 0)
651                                 if (sys->getTime() - stime > 5)
652                                         break;
653                 }catch(StreamException &) {}
654
655                 if (closesocket (sockNum))
656                         LOG_ERROR("closesocket() error");
657
658
659                 sockNum=0;
660         }
661         sockLock.off();
662 }
663
664 // --------------------------------------------------
665 bool    WSAClientSocket::readReady()
666 {
667         if (rbDataSize) return true;
668
669         timeval timeout;
670         fd_set read_fds;
671
672         timeout.tv_sec = 0;
673         timeout.tv_usec = 0;
674
675     FD_ZERO (&read_fds);
676     FD_SET (sockNum, &read_fds);
677
678         return select (sockNum+1, &read_fds, NULL, NULL, &timeout) == 1;
679 }
680