aboutsummaryrefslogtreecommitdiff
path: root/src/socket.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2010-10-16 03:02:11 +0000
committerMike Buland <eichlan@xagasoft.com>2010-10-16 03:02:11 +0000
commit9031e2af7dd4e65ec70890ee78a7cf600d1b2cc5 (patch)
tree17bc9d96b13d16d79385016c087321fc1267743f /src/socket.cpp
parent93c028162318a00b9bd03fc4a48383f830cc529d (diff)
downloadlibbu++-9031e2af7dd4e65ec70890ee78a7cf600d1b2cc5.tar.gz
libbu++-9031e2af7dd4e65ec70890ee78a7cf600d1b2cc5.tar.bz2
libbu++-9031e2af7dd4e65ec70890ee78a7cf600d1b2cc5.tar.xz
libbu++-9031e2af7dd4e65ec70890ee78a7cf600d1b2cc5.zip
Many, many changes. Documentation changes, renamed the socket class to
TcpSocket, fixed many other things, and finally removed ParamProc. Anything that needs it will now have to switch to OptParser.
Diffstat (limited to 'src/socket.cpp')
-rw-r--r--src/socket.cpp446
1 files changed, 0 insertions, 446 deletions
diff --git a/src/socket.cpp b/src/socket.cpp
deleted file mode 100644
index baf3be3..0000000
--- a/src/socket.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
1/*
2 * Copyright (C) 2007-2010 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/socket.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
32namespace Bu { subExceptionDef( SocketException ) }
33
34Bu::Socket::Socket( int nSocket ) :
35 nSocket( nSocket ),
36 bActive( true ),
37 bBlocking( true )
38{
39#ifdef WIN32
40 Bu::Winsock2::getInstance();
41#endif
42 setAddress();
43}
44
45Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) :
46 nSocket( 0 ),
47 bActive( false ),
48 bBlocking( true )
49{
50#ifdef WIN32
51 Bu::Winsock2::getInstance();
52#endif
53
54 /* Create the socket. */
55 nSocket = bu_socket( PF_INET, SOCK_STREAM, 0 );
56
57 if( nSocket < 0 )
58 {
59 throw ExceptionBase("Couldn't create socket.\n");
60 }
61
62 setBlocking( false );
63
64 /* Connect to the server. */
65 //printf("Resolving hostname (%s)...\n", sAddr );
66 {
67 struct addrinfo *pAddr = NULL;
68 struct addrinfo aiHints;
69 memset( &aiHints, 0, sizeof(addrinfo) );
70 aiHints.ai_flags = AI_CANONNAME;
71 aiHints.ai_family = AF_INET;
72 aiHints.ai_socktype = SOCK_STREAM;
73 char ibuf[10];
74 sprintf( ibuf, "%d", nPort );
75
76 int ret;
77 if( (ret = bu_getaddrinfo(
78 sAddr.getStr(), ibuf, &aiHints, &pAddr )) != 0 )
79 {
80 close();
81 throw Bu::SocketException("Couldn't resolve hostname %s (%s).\n",
82 sAddr.getStr(), bu_gai_strerror(ret));
83 }
84
85 bu_connect(
86 nSocket,
87 pAddr->ai_addr,
88 pAddr->ai_addrlen
89 );
90
91 sAddress = pAddr->ai_canonname;
92
93 bu_freeaddrinfo( pAddr );
94 }
95
96 bActive = true;
97
98 if( nTimeout > 0 )
99 {
100 fd_set rfds, wfds, efds;
101 int retval;
102
103 FD_ZERO(&rfds);
104 FD_SET(nSocket, &rfds);
105 FD_ZERO(&wfds);
106 FD_SET(nSocket, &wfds);
107 FD_ZERO(&efds);
108 FD_SET(nSocket, &efds);
109
110 struct timeval tv;
111 tv.tv_sec = nTimeout;
112 tv.tv_usec = 0;
113
114 retval = bu_select( nSocket+1, &rfds, &wfds, &efds, &tv );
115
116 if( retval == 0 )
117 {
118 close();
119 throw ExceptionBase("Connection timeout.\n");
120 }
121 read( NULL, 0 ); // See if we can get any errors out of the way early.
122 }
123}
124
125Bu::Socket::~Socket()
126{
127 close();
128}
129
130void Bu::Socket::close()
131{
132 if( bActive )
133 {
134#ifndef WIN32
135 fsync( nSocket );
136#endif
137#ifdef WIN32
138 #ifndef SHUT_RDWR
139 #define SHUT_RDWR (SD_BOTH)
140 #endif
141#endif
142 bu_shutdown( nSocket, SHUT_RDWR );
143 ::close( nSocket );
144 }
145 bActive = false;
146}
147
148size_t Bu::Socket::read( void *pBuf, size_t nBytes )
149{
150 fd_set rfds;
151 FD_ZERO(&rfds);
152 FD_SET(nSocket, &rfds);
153 struct timeval tv = {0, 0};
154 if( bu_select( nSocket+1, &rfds, NULL, NULL, &tv ) < 0 )
155 {
156 int iErr = errno;
157 close();
158 throw SocketException( SocketException::cRead, strerror(iErr) );
159 }
160 if( FD_ISSET( nSocket, &rfds ) || bBlocking )
161 {
162 int nRead = TEMP_FAILURE_RETRY(
163 bu_recv( nSocket, (char *) pBuf, nBytes, 0 ) );
164 if( nRead == 0 )
165 {
166 close();
167 throw SocketException( SocketException::cClosed, "Socket closed.");
168 }
169 if( nRead < 0 )
170 {
171#ifdef WIN32
172 int iWSAError = bu_WSAGetLastError();
173 if( iWSAError == WSAEWOULDBLOCK )
174 return 0;
175#else
176 if( errno == ENETRESET || errno == ECONNRESET )
177 {
178 close();
179 throw SocketException( SocketException::cClosed,
180 strerror(errno) );
181 }
182 if( errno == EAGAIN )
183 return 0;
184 int iErr = errno;
185 close();
186 throw SocketException( SocketException::cRead, strerror(iErr) );
187#endif
188 }
189 return nRead;
190 }
191 return 0;
192}
193
194size_t Bu::Socket::read( void *pBuf, size_t nBytes,
195 uint32_t nSec, uint32_t nUSec )
196{
197 struct timeval tv;
198 size_t nRead = 0;
199
200 fd_set rfds;
201 FD_ZERO(&rfds);
202 FD_SET(nSocket, &rfds);
203
204#ifdef WIN32
205 DWORD dwStart = GetTickCount();
206 uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000));
207 DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver;
208#else
209 struct timeval nt, ct;
210 gettimeofday( &nt, NULL );
211 nt.tv_sec += nSec;
212 nt.tv_usec += nUSec;
213#endif
214
215 for(;;)
216 {
217 tv.tv_sec = nSec;
218 tv.tv_usec = nUSec;
219 bu_select( nSocket+1, &rfds, NULL, NULL, &tv );
220 nRead += read( ((char *)pBuf)+nRead, nBytes-nRead );
221 if( nRead >= nBytes )
222 break;
223#ifdef WIN32
224 DWORD dwNow = GetTickCount();
225 if( dwNow > dwEnd )
226 break;
227#else
228 gettimeofday( &ct, NULL );
229 if( (ct.tv_sec > nt.tv_sec) ||
230 (ct.tv_sec == nt.tv_sec &&
231 ct.tv_usec >= nt.tv_usec) )
232 break;
233#endif
234 }
235 return nRead;
236}
237
238size_t Bu::Socket::write( const void *pBuf, size_t nBytes )
239{
240//#ifdef WIN32
241 int nWrote = TEMP_FAILURE_RETRY(
242 bu_send( nSocket, (const char *) pBuf, nBytes, 0 ) );
243//#else
244// int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) );
245//#endif
246 if( nWrote < 0 )
247 {
248#ifdef WIN32
249 int iWSAError = bu_WSAGetLastError();
250 if( iWSAError == WSAEWOULDBLOCK )
251 return 0;
252#else
253 if( errno == EAGAIN ) return 0;
254#endif
255 throw SocketException( SocketException::cWrite, strerror(errno) );
256 }
257 return nWrote;
258}
259
260size_t Bu::Socket::write( const void *pBuf, size_t nBytes, uint32_t nSec, uint32_t nUSec )
261{
262 struct timeval tv;
263 size_t nWrote = 0;
264
265 fd_set wfds;
266 FD_ZERO(&wfds);
267 FD_SET(nSocket, &wfds);
268
269#ifdef WIN32
270 DWORD dwStart = GetTickCount();
271 uint64_t uOver = dwStart + ((nUSec / 1000) * (nSec * 1000));
272 DWORD dwEnd = uOver>4294967295U?uOver-4294967295U:uOver;
273#else
274 struct timeval nt, ct;
275 gettimeofday( &nt, NULL );
276 nt.tv_sec += nSec;
277 nt.tv_usec += nUSec;
278#endif
279
280 for(;;)
281 {
282 tv.tv_sec = nSec;
283 tv.tv_usec = nUSec;
284 bu_select( nSocket+1, NULL, &wfds, NULL, &tv );
285 nWrote += write( ((char *)pBuf)+nWrote, nBytes-nWrote );
286 if( nWrote >= nBytes )
287 break;
288#ifdef WIN32
289 DWORD dwNow = GetTickCount();
290 if( dwNow > dwEnd )
291 break;
292#else
293 gettimeofday( &ct, NULL );
294 if( (ct.tv_sec > nt.tv_sec) ||
295 (ct.tv_sec == nt.tv_sec &&
296 ct.tv_usec >= nt.tv_usec) )
297 break;
298#endif
299 }
300 return nWrote;
301}
302
303long Bu::Socket::tell()
304{
305 throw UnsupportedException();
306}
307
308void Bu::Socket::seek( long )
309{
310 throw UnsupportedException();
311}
312
313void Bu::Socket::setPos( long )
314{
315 throw UnsupportedException();
316}
317
318void Bu::Socket::setPosEnd( long )
319{
320 throw UnsupportedException();
321}
322
323bool Bu::Socket::isEos()
324{
325 return !bActive;
326}
327
328bool Bu::Socket::canRead()
329{
330 fd_set rfds;
331 FD_ZERO(&rfds);
332 FD_SET(nSocket, &rfds);
333 struct timeval tv = { 0, 0 };
334 int retval = bu_select( nSocket+1, &rfds, NULL, NULL, &tv );
335 if( retval == -1 )
336 throw SocketException(
337 SocketException::cBadRead,
338 "Bad Read error"
339 );
340
341 if( !FD_ISSET( nSocket, &rfds ) )
342 return false;
343 return true;
344}
345
346bool Bu::Socket::canWrite()
347{
348 fd_set wfds;
349 FD_ZERO(&wfds);
350 FD_SET(nSocket, &wfds);
351 struct timeval tv = { 0, 0 };
352 int retval = bu_select( nSocket+1, NULL, &wfds, NULL, &tv );
353 if( retval == -1 )
354 throw SocketException(
355 SocketException::cBadRead,
356 "Bad Read error"
357 );
358 if( !FD_ISSET( nSocket, &wfds ) )
359 return false;
360 return true;
361}
362
363bool Bu::Socket::isReadable()
364{
365 return true;
366}
367
368bool Bu::Socket::isWritable()
369{
370 return true;
371}
372
373bool Bu::Socket::isSeekable()
374{
375 return false;
376}
377
378bool Bu::Socket::isBlocking()
379{
380#ifndef WIN32
381 return ((fcntl( nSocket, F_GETFL, 0 ) & O_NONBLOCK) != O_NONBLOCK);
382#else
383 return false;
384#endif
385}
386
387void Bu::Socket::setBlocking( bool bBlocking )
388{
389 this->bBlocking = bBlocking;
390#ifndef WIN32
391 if( bBlocking )
392 {
393 fcntl( nSocket, F_SETFL, fcntl( nSocket, F_GETFL, 0 ) & (~O_NONBLOCK) );
394 }
395 else
396 {
397 fcntl( nSocket, F_SETFL, fcntl( nSocket, F_GETFL, 0 ) | O_NONBLOCK );
398 }
399#else
400 u_long iMode;
401 if( bBlocking )
402 iMode = 0;
403 else
404 iMode = 1;
405 //-------------------------
406 // Set the socket I/O mode: In this case FIONBIO
407 // enables or disables the blocking mode for the
408 // socket based on the numerical value of iMode.
409 // If iMode = 0, blocking is enabled;
410 // If iMode != 0, non-blocking mode is enabled.
411 bu_ioctlsocket(nSocket, FIONBIO, &iMode);
412#endif
413}
414
415void Bu::Socket::setSize( long )
416{
417}
418
419void Bu::Socket::flush()
420{
421}
422
423bool Bu::Socket::isOpen()
424{
425 return bActive;
426}
427
428void Bu::Socket::setAddress()
429{
430 struct sockaddr_in addr;
431 socklen_t len = sizeof(addr);
432 addr.sin_family = AF_INET;
433 bu_getpeername( nSocket, (sockaddr *)(&addr), &len );
434 sAddress = bu_inet_ntoa( addr.sin_addr );
435}
436
437Bu::FString Bu::Socket::getAddress() const
438{
439 return sAddress;
440}
441
442Bu::Socket::operator int() const
443{
444 return nSocket;
445}
446