diff options
Diffstat (limited to 'src/stable/tcpsocket.cpp')
-rw-r--r-- | src/stable/tcpsocket.cpp | 482 |
1 files changed, 0 insertions, 482 deletions
diff --git a/src/stable/tcpsocket.cpp b/src/stable/tcpsocket.cpp deleted file mode 100644 index d036063..0000000 --- a/src/stable/tcpsocket.cpp +++ /dev/null | |||
@@ -1,482 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2019 Xagasoft, All rights reserved. | ||
3 | * | ||
4 | * This file is part of the libbu++ library and is released under the | ||
5 | * terms of the license contained in the file LICENSE. | ||
6 | */ | ||
7 | |||
8 | #include <string.h> | ||
9 | #include <stdio.h> | ||
10 | #include <errno.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <unistd.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <sys/time.h> | ||
15 | #include <errno.h> | ||
16 | #include <fcntl.h> | ||
17 | #include "bu/tcpsocket.h" | ||
18 | |||
19 | #include "bu/config.h" | ||
20 | |||
21 | #ifndef WIN32 | ||
22 | #include <sys/socket.h> | ||
23 | #include <netinet/in.h> | ||
24 | #include <netdb.h> | ||
25 | #include <arpa/inet.h> | ||
26 | #else | ||
27 | #include <Winsock2.h> | ||
28 | #endif | ||
29 | |||
30 | #define RBS (1024*2) | ||
31 | |||
32 | namespace Bu { subExceptionDef( TcpSocketException ) } | ||
33 | |||
34 | Bu::TcpSocket::TcpSocket( handle nTcpSocket ) : | ||
35 | nTcpSocket( nTcpSocket ), | ||
36 | bActive( true ), | ||
37 | bBlocking( true ) | ||
38 | { | ||
39 | #ifdef WIN32 | ||
40 | Bu::Winsock2::getInstance(); | ||
41 | #endif | ||
42 | setAddress(); | ||
43 | } | ||
44 | |||
45 | Bu::TcpSocket::TcpSocket( const Bu::String &sAddr, int nPort, int nTimeout, | ||
46 | bool bBlocking ) : | ||
47 | nTcpSocket( 0 ), | ||
48 | bActive( false ), | ||
49 | bBlocking( true ) | ||
50 | { | ||
51 | #ifdef WIN32 | ||
52 | Bu::Winsock2::getInstance(); | ||
53 | #endif | ||
54 | |||
55 | /* Create the socket. */ | ||
56 | nTcpSocket = bu_socket( PF_INET, SOCK_STREAM, 0 ); | ||
57 | |||
58 | #ifdef WIN32 | ||
59 | if( nTcpSocket == INVALID_SOCKET ) | ||
60 | #else | ||
61 | if( nTcpSocket < 0 ) | ||
62 | #endif | ||
63 | { | ||
64 | throw ExceptionBase("Couldn't create socket.\n"); | ||
65 | } | ||
66 | |||
67 | setBlocking( false ); | ||
68 | |||
69 | /* Connect to the server. */ | ||
70 | //printf("Resolving hostname (%s)...\n", sAddr ); | ||
71 | { | ||
72 | struct addrinfo *pAddr = NULL; | ||
73 | struct addrinfo aiHints; | ||
74 | memset( &aiHints, 0, sizeof(addrinfo) ); | ||
75 | aiHints.ai_flags = AI_CANONNAME; | ||
76 | aiHints.ai_family = AF_INET; | ||
77 | aiHints.ai_socktype = SOCK_STREAM; | ||
78 | char ibuf[10]; | ||
79 | sprintf( ibuf, "%d", nPort ); | ||
80 | |||
81 | int ret; | ||
82 | if( (ret = bu_getaddrinfo( | ||
83 | sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 ) | ||
84 | { | ||
85 | close(); | ||
86 | throw Bu::TcpSocketException("Couldn't resolve hostname %s (%s).\n", | ||
87 | sAddr.getStr(), bu_gai_strerror(ret)); | ||
88 | } | ||
89 | |||
90 | bu_connect( | ||
91 | nTcpSocket, | ||
92 | pAddr->ai_addr, | ||
93 | pAddr->ai_addrlen | ||
94 | ); | ||
95 | |||
96 | sAddress = pAddr->ai_canonname; | ||
97 | |||
98 | bu_freeaddrinfo( pAddr ); | ||
99 | } | ||
100 | |||
101 | bActive = true; | ||
102 | |||
103 | if( nTimeout > 0 ) | ||
104 | { | ||
105 | fd_set rfds, wfds, efds; | ||
106 | int retval; | ||
107 | |||
108 | FD_ZERO(&rfds); | ||
109 | FD_SET(nTcpSocket, &rfds); | ||
110 | FD_ZERO(&wfds); | ||
111 | FD_SET(nTcpSocket, &wfds); | ||
112 | FD_ZERO(&efds); | ||
113 | FD_SET(nTcpSocket, &efds); | ||
114 | |||
115 | struct timeval tv; | ||
116 | tv.tv_sec = nTimeout; | ||
117 | tv.tv_usec = 0; | ||
118 | |||
119 | retval = bu_select( nTcpSocket+1, &rfds, &wfds, &efds, &tv ); | ||
120 | |||
121 | if( retval == 0 ) | ||
122 | { | ||
123 | close(); | ||
124 | throw ExceptionBase("Connection timeout.\n"); | ||
125 | } | ||
126 | read( NULL, 0 ); // See if we can get any errors out of the way early. | ||
127 | } | ||
128 | |||
129 | if( bBlocking ) | ||
130 | setBlocking( bBlocking ); | ||
131 | } | ||
132 | |||
133 | Bu::TcpSocket::~TcpSocket() | ||
134 | { | ||
135 | close(); | ||
136 | } | ||
137 | |||
138 | void Bu::TcpSocket::close() | ||
139 | { | ||
140 | if( bActive ) | ||
141 | { | ||
142 | #ifndef WIN32 | ||
143 | fsync( nTcpSocket ); | ||
144 | #endif | ||
145 | #ifdef WIN32 | ||
146 | #ifndef SHUT_RDWR | ||
147 | #define SHUT_RDWR (SD_BOTH) | ||
148 | #endif | ||
149 | #endif | ||
150 | bu_shutdown( nTcpSocket, SHUT_RDWR ); | ||
151 | ::close( nTcpSocket ); | ||
152 | } | ||
153 | bActive = false; | ||
154 | } | ||
155 | |||
156 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes ) | ||
157 | { | ||
158 | fd_set rfds; | ||
159 | FD_ZERO(&rfds); | ||
160 | FD_SET(nTcpSocket, &rfds); | ||
161 | struct timeval tv = {0, 0}; | ||
162 | if( bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ) < 0 ) | ||
163 | { | ||
164 | int iErr = errno; | ||
165 | close(); | ||
166 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); | ||
167 | } | ||
168 | if( FD_ISSET( nTcpSocket, &rfds ) || bBlocking ) | ||
169 | { | ||
170 | int nRead = TEMP_FAILURE_RETRY( | ||
171 | bu_recv( nTcpSocket, (char *) pBuf, nBytes, 0 ) ); | ||
172 | if( nRead == 0 && nBytes > 0 ) | ||
173 | { | ||
174 | close(); | ||
175 | throw TcpSocketException( TcpSocketException::cClosed, "TcpSocket closed."); | ||
176 | } | ||
177 | if( nRead < 0 ) | ||
178 | { | ||
179 | #ifdef WIN32 | ||
180 | int iWSAError = bu_WSAGetLastError(); | ||
181 | if( iWSAError == WSAEWOULDBLOCK ) | ||
182 | return 0; | ||
183 | #else | ||
184 | if( errno == ENETRESET || errno == ECONNRESET ) | ||
185 | { | ||
186 | close(); | ||
187 | throw TcpSocketException( TcpSocketException::cClosed, | ||
188 | strerror(errno) ); | ||
189 | } | ||
190 | if( errno == EAGAIN ) | ||
191 | return 0; | ||
192 | int iErr = errno; | ||
193 | close(); | ||
194 | throw TcpSocketException( TcpSocketException::cRead, strerror(iErr) ); | ||
195 | #endif | ||
196 | } | ||
197 | return nRead; | ||
198 | } | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | Bu::size Bu::TcpSocket::read( void *pBuf, Bu::size nBytes, | ||
203 | uint32_t nSec, uint32_t nUSec ) | ||
204 | { | ||
205 | struct timeval tv; | ||
206 | Bu::size nRead = 0; | ||
207 | |||
208 | fd_set rfds; | ||
209 | FD_ZERO(&rfds); | ||
210 | FD_SET(nTcpSocket, &rfds); | ||
211 | |||
212 | #ifdef WIN32 | ||
213 | DWORD dwStart = GetTickCount(); | ||
214 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | ||
215 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | ||
216 | #else | ||
217 | struct timeval nt, ct; | ||
218 | gettimeofday( &nt, NULL ); | ||
219 | nt.tv_sec += nSec; | ||
220 | nt.tv_usec += nUSec; | ||
221 | #endif | ||
222 | |||
223 | for(;;) | ||
224 | { | ||
225 | tv.tv_sec = nSec; | ||
226 | tv.tv_usec = nUSec; | ||
227 | bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); | ||
228 | nRead += read( ((char *)pBuf)+nRead, nBytes-nRead ); | ||
229 | if( nRead >= nBytes ) | ||
230 | break; | ||
231 | #ifdef WIN32 | ||
232 | DWORD dwNow = GetTickCount(); | ||
233 | if( dwNow > dwEnd ) | ||
234 | break; | ||
235 | #else | ||
236 | gettimeofday( &ct, NULL ); | ||
237 | if( (ct.tv_sec > nt.tv_sec) || | ||
238 | (ct.tv_sec == nt.tv_sec && | ||
239 | ct.tv_usec >= nt.tv_usec) ) | ||
240 | break; | ||
241 | #endif | ||
242 | } | ||
243 | return nRead; | ||
244 | } | ||
245 | |||
246 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes ) | ||
247 | { | ||
248 | //#ifdef WIN32 | ||
249 | int nWrote = TEMP_FAILURE_RETRY( | ||
250 | bu_send( nTcpSocket, (const char *) pBuf, nBytes, 0 ) ); | ||
251 | //#else | ||
252 | // int nWrote = TEMP_FAILURE_RETRY( ::write( nTcpSocket, pBuf, nBytes ) ); | ||
253 | //#endif | ||
254 | if( nWrote < 0 ) | ||
255 | { | ||
256 | #ifdef WIN32 | ||
257 | int iWSAError = bu_WSAGetLastError(); | ||
258 | if( iWSAError == WSAEWOULDBLOCK ) | ||
259 | return 0; | ||
260 | #else | ||
261 | if( errno == EAGAIN ) return 0; | ||
262 | #endif | ||
263 | throw TcpSocketException( TcpSocketException::cWrite, strerror(errno) ); | ||
264 | } | ||
265 | return nWrote; | ||
266 | } | ||
267 | |||
268 | Bu::size Bu::TcpSocket::write( const void *pBuf, Bu::size nBytes, uint32_t nSec, uint32_t nUSec ) | ||
269 | { | ||
270 | struct timeval tv; | ||
271 | Bu::size nWrote = 0; | ||
272 | |||
273 | fd_set wfds; | ||
274 | FD_ZERO(&wfds); | ||
275 | FD_SET(nTcpSocket, &wfds); | ||
276 | |||
277 | #ifdef WIN32 | ||
278 | DWORD dwStart = GetTickCount(); | ||
279 | uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000)); | ||
280 | DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver; | ||
281 | #else | ||
282 | struct timeval nt, ct; | ||
283 | gettimeofday( &nt, NULL ); | ||
284 | nt.tv_sec += nSec; | ||
285 | nt.tv_usec += nUSec; | ||
286 | #endif | ||
287 | |||
288 | for(;;) | ||
289 | { | ||
290 | tv.tv_sec = nSec; | ||
291 | tv.tv_usec = nUSec; | ||
292 | bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); | ||
293 | nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote ); | ||
294 | if( nWrote >= nBytes ) | ||
295 | break; | ||
296 | #ifdef WIN32 | ||
297 | DWORD dwNow = GetTickCount(); | ||
298 | if( dwNow > dwEnd ) | ||
299 | break; | ||
300 | #else | ||
301 | gettimeofday( &ct, NULL ); | ||
302 | if( (ct.tv_sec > nt.tv_sec) || | ||
303 | (ct.tv_sec == nt.tv_sec && | ||
304 | ct.tv_usec >= nt.tv_usec) ) | ||
305 | break; | ||
306 | #endif | ||
307 | } | ||
308 | return nWrote; | ||
309 | } | ||
310 | |||
311 | Bu::size Bu::TcpSocket::tell() | ||
312 | { | ||
313 | throw UnsupportedException(); | ||
314 | } | ||
315 | |||
316 | void Bu::TcpSocket::seek( Bu::size ) | ||
317 | { | ||
318 | throw UnsupportedException(); | ||
319 | } | ||
320 | |||
321 | void Bu::TcpSocket::setPos( Bu::size ) | ||
322 | { | ||
323 | throw UnsupportedException(); | ||
324 | } | ||
325 | |||
326 | void Bu::TcpSocket::setPosEnd( Bu::size ) | ||
327 | { | ||
328 | throw UnsupportedException(); | ||
329 | } | ||
330 | |||
331 | bool Bu::TcpSocket::isEos() | ||
332 | { | ||
333 | return !bActive; | ||
334 | } | ||
335 | |||
336 | bool Bu::TcpSocket::canRead() | ||
337 | { | ||
338 | fd_set rfds; | ||
339 | FD_ZERO(&rfds); | ||
340 | FD_SET(nTcpSocket, &rfds); | ||
341 | struct timeval tv = { 0, 0 }; | ||
342 | int retval = bu_select( nTcpSocket+1, &rfds, NULL, NULL, &tv ); | ||
343 | if( retval == -1 ) | ||
344 | throw TcpSocketException( | ||
345 | TcpSocketException::cBadRead, | ||
346 | "Bad Read error" | ||
347 | ); | ||
348 | |||
349 | if( !FD_ISSET( nTcpSocket, &rfds ) ) | ||
350 | return false; | ||
351 | return true; | ||
352 | } | ||
353 | |||
354 | bool Bu::TcpSocket::canWrite() | ||
355 | { | ||
356 | fd_set wfds; | ||
357 | FD_ZERO(&wfds); | ||
358 | FD_SET(nTcpSocket, &wfds); | ||
359 | struct timeval tv = { 0, 0 }; | ||
360 | int retval = bu_select( nTcpSocket+1, NULL, &wfds, NULL, &tv ); | ||
361 | if( retval == -1 ) | ||
362 | throw TcpSocketException( | ||
363 | TcpSocketException::cBadRead, | ||
364 | "Bad Read error" | ||
365 | ); | ||
366 | if( !FD_ISSET( nTcpSocket, &wfds ) ) | ||
367 | return false; | ||
368 | return true; | ||
369 | } | ||
370 | |||
371 | bool Bu::TcpSocket::isReadable() | ||
372 | { | ||
373 | return true; | ||
374 | } | ||
375 | |||
376 | bool Bu::TcpSocket::isWritable() | ||
377 | { | ||
378 | return true; | ||
379 | } | ||
380 | |||
381 | bool Bu::TcpSocket::isSeekable() | ||
382 | { | ||
383 | return false; | ||
384 | } | ||
385 | |||
386 | bool Bu::TcpSocket::isBlocking() | ||
387 | { | ||
388 | #ifndef WIN32 | ||
389 | return ((fcntl( nTcpSocket, F_GETFL, 0 ) & O_NONBLOCK) != O_NONBLOCK); | ||
390 | #else | ||
391 | return false; | ||
392 | #endif | ||
393 | } | ||
394 | |||
395 | void Bu::TcpSocket::setBlocking( bool bBlocking ) | ||
396 | { | ||
397 | this->bBlocking = bBlocking; | ||
398 | #ifndef WIN32 | ||
399 | if( bBlocking ) | ||
400 | { | ||
401 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) & (~O_NONBLOCK) ); | ||
402 | } | ||
403 | else | ||
404 | { | ||
405 | fcntl( nTcpSocket, F_SETFL, fcntl( nTcpSocket, F_GETFL, 0 ) | O_NONBLOCK ); | ||
406 | } | ||
407 | #else | ||
408 | u_long iMode; | ||
409 | if( bBlocking ) | ||
410 | iMode = 0; | ||
411 | else | ||
412 | iMode = 1; | ||
413 | //------------------------- | ||
414 | // Set the socket I/O mode: In this case FIONBIO | ||
415 | // enables or disables the blocking mode for the | ||
416 | // socket based on the numerical value of iMode. | ||
417 | // If iMode = 0, blocking is enabled; | ||
418 | // If iMode != 0, non-blocking mode is enabled. | ||
419 | bu_ioctlsocket(nTcpSocket, FIONBIO, &iMode); | ||
420 | #endif | ||
421 | } | ||
422 | |||
423 | void Bu::TcpSocket::setSize( Bu::size ) | ||
424 | { | ||
425 | } | ||
426 | |||
427 | void Bu::TcpSocket::flush() | ||
428 | { | ||
429 | } | ||
430 | |||
431 | bool Bu::TcpSocket::isOpen() | ||
432 | { | ||
433 | return bActive; | ||
434 | } | ||
435 | |||
436 | void Bu::TcpSocket::setAddress() | ||
437 | { | ||
438 | struct sockaddr_in addr; | ||
439 | socklen_t len = sizeof(addr); | ||
440 | addr.sin_family = AF_INET; | ||
441 | bu_getpeername( nTcpSocket, (sockaddr *)(&addr), &len ); | ||
442 | sAddress = bu_inet_ntoa( addr.sin_addr ); | ||
443 | } | ||
444 | |||
445 | Bu::String Bu::TcpSocket::getAddress() const | ||
446 | { | ||
447 | return sAddress; | ||
448 | } | ||
449 | |||
450 | Bu::TcpSocket::operator Bu::TcpSocket::handle() const | ||
451 | { | ||
452 | return nTcpSocket; | ||
453 | } | ||
454 | |||
455 | Bu::TcpSocket::handle Bu::TcpSocket::getHandle() const | ||
456 | { | ||
457 | return nTcpSocket; | ||
458 | } | ||
459 | |||
460 | Bu::TcpSocket::handle Bu::TcpSocket::takeHandle() | ||
461 | { | ||
462 | handle nRet = nTcpSocket; | ||
463 | bActive = false; | ||
464 | nTcpSocket = 0; | ||
465 | return nRet; | ||
466 | } | ||
467 | |||
468 | Bu::size Bu::TcpSocket::getSize() const | ||
469 | { | ||
470 | throw UnsupportedException(); | ||
471 | } | ||
472 | |||
473 | Bu::size Bu::TcpSocket::getBlockSize() const | ||
474 | { | ||
475 | return 1500; //TODO: Fix this, it's stupid. | ||
476 | } | ||
477 | |||
478 | Bu::String Bu::TcpSocket::getLocation() const | ||
479 | { | ||
480 | return getAddress(); | ||
481 | } | ||
482 | |||