aboutsummaryrefslogtreecommitdiff
path: root/src/socket.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/socket.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/socket.cpp b/src/socket.cpp
new file mode 100644
index 0000000..e567061
--- /dev/null
+++ b/src/socket.cpp
@@ -0,0 +1,294 @@
1#include <string.h>
2#include <stdio.h>
3#include <errno.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <sys/time.h>
9#include <netinet/in.h>
10#include <netdb.h>
11#include <arpa/inet.h>
12#include <errno.h>
13#include <fcntl.h>
14#include "socket.h"
15#include "exceptions.h"
16
17#define RBS (1024*2)
18
19Bu::Socket::Socket( int nSocket ) :
20 nSocket( nSocket ),
21 bActive( true )
22{
23}
24
25Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout )
26{
27 struct sockaddr_in xServerName;
28 bActive = false;
29
30 /* Create the socket. */
31 nSocket = socket( PF_INET, SOCK_STREAM, 0 );
32
33 if( nSocket < 0 )
34 {
35 throw ExceptionBase("Couldn't create socket.\n");
36 }
37
38 // These lines set the socket to non-blocking, a good thing?
39 int flags;
40 flags = fcntl(nSocket, F_GETFL, 0);
41 flags |= O_NONBLOCK;
42 if (fcntl(nSocket, F_SETFL, flags) < 0)
43 {
44 throw ExceptionBase("Couldn't set socket options.\n");
45 }
46
47 /* Connect to the server. */
48 //printf("Resolving hostname (%s)...\n", sAddr );
49 {
50 struct hostent *hostinfo;
51
52 xServerName.sin_family = AF_INET;
53 xServerName.sin_port = htons( nPort );
54 hostinfo = gethostbyname( sAddr.getStr() );
55 if (hostinfo == NULL)
56 {
57 throw ExceptionBase("Couldn't resolve hostname.\n");
58 }
59 xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr;
60 }
61
62 //printf("Making actual connection...");
63 //fflush( stdout );
64 connect(
65 nSocket,
66 (struct sockaddr *)&xServerName,
67 sizeof(xServerName)
68 );
69 //printf("Connected.\n");
70
71 bActive = true;
72
73 if( nTimeout > 0 )
74 {
75 fd_set rfds, wfds, efds;
76 int retval;
77
78 FD_ZERO(&rfds);
79 FD_SET(nSocket, &rfds);
80 FD_ZERO(&wfds);
81 FD_SET(nSocket, &wfds);
82 FD_ZERO(&efds);
83 FD_SET(nSocket, &efds);
84
85 struct timeval tv;
86 tv.tv_sec = nTimeout;
87 tv.tv_usec = 0;
88
89 retval = select( nSocket+1, &rfds, &wfds, &efds, &tv );
90
91 if( retval == 0 )
92 {
93 close();
94 throw ExceptionBase("Connection timeout.\n");
95 }
96
97 }
98}
99
100Bu::Socket::~Socket()
101{
102}
103
104void Bu::Socket::close()
105{
106 if( bActive )
107 {
108 fsync( nSocket );
109 ::close( nSocket );
110 }
111 bActive = false;
112}
113
114/*
115void Bu::Socket::read()
116{
117 char buffer[RBS];
118 int nbytes;
119 int nTotalRead=0;
120
121 for(;;)
122 {
123 //memset( buffer, 0, RBS );
124
125 nbytes = ::read( nSocket, buffer, RBS );
126 if( nbytes < 0 && errno != 0 && errno != EAGAIN )
127 {
128 //printf("errno: %d, %s\n", errno, strerror( errno ) );
129 //perror("readInput");
130 throw ConnectionException(
131 excodeReadError,
132 "Read error: %s",
133 strerror( errno )
134 );
135 }
136 else
137 {
138 if( nbytes <= 0 )
139 break;
140 nTotalRead += nbytes;
141 sReadBuf.append( buffer, nbytes );
142 if( nbytes < RBS )
143 {
144 break;
145 }
146
147 // New test, if data is divisible by RBS bytes on some libs the
148 // read could block, this keeps it from happening.
149 {
150 fd_set rfds;
151 FD_ZERO(&rfds);
152 FD_SET(nSocket, &rfds);
153 struct timeval tv = { 0, 0 };
154 int retval = select( nSocket+1, &rfds, NULL, NULL, &tv );
155 if( retval == -1 )
156 throw ConnectionException(
157 excodeBadReadError,
158 "Bad Read error"
159 );
160 if( !FD_ISSET( nSocket, &rfds ) )
161 break;
162 }
163 }
164 }
165}*/
166
167size_t Bu::Socket::read( void *pBuf, size_t nBytes )
168{
169 int nRead = TEMP_FAILURE_RETRY( ::read( nSocket, pBuf, nBytes ) );
170 if( nRead < 0 )
171 {
172 throw ConnectionException( excodeReadError, strerror(errno) );
173 }
174 return nRead;
175}
176
177//size_t Bu::Socket::read( void *pBuf, size_t nBytes, uint32_t nTimeout )
178//{
179//}
180
181size_t Bu::Socket::write( const void *pBuf, size_t nBytes )
182{
183 int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) );
184 if( nWrote < 0 )
185 {
186 throw ConnectionException( excodeWriteError, strerror(errno) );
187 }
188 return nWrote;
189}
190
191long Bu::Socket::tell()
192{
193 throw UnsupportedException();
194}
195
196void Bu::Socket::seek( long offset )
197{
198 throw UnsupportedException();
199}
200
201void Bu::Socket::setPos( long pos )
202{
203 throw UnsupportedException();
204}
205
206void Bu::Socket::setPosEnd( long pos )
207{
208 throw UnsupportedException();
209}
210
211bool Bu::Socket::isEOS()
212{
213 return !bActive;
214}
215
216bool Bu::Socket::canRead()
217{
218 fd_set rfds;
219 FD_ZERO(&rfds);
220 FD_SET(nSocket, &rfds);
221 struct timeval tv = { 0, 0 };
222 int retval = select( nSocket+1, &rfds, NULL, NULL, &tv );
223 if( retval == -1 )
224 throw ConnectionException(
225 excodeBadReadError,
226 "Bad Read error"
227 );
228 if( !FD_ISSET( nSocket, &rfds ) )
229 return false;
230 return true;
231}
232
233bool Bu::Socket::canWrite()
234{
235 fd_set wfds;
236 FD_ZERO(&wfds);
237 FD_SET(nSocket, &wfds);
238 struct timeval tv = { 0, 0 };
239 int retval = select( nSocket+1, NULL, &wfds, NULL, &tv );
240 if( retval == -1 )
241 throw ConnectionException(
242 excodeBadReadError,
243 "Bad Read error"
244 );
245 if( !FD_ISSET( nSocket, &wfds ) )
246 return false;
247 return true;
248}
249
250bool Bu::Socket::isReadable()
251{
252 return true;
253}
254
255bool Bu::Socket::isWritable()
256{
257 return true;
258}
259
260bool Bu::Socket::isSeekable()
261{
262 return false;
263}
264
265bool Bu::Socket::isBlocking()
266{
267 return false;
268}
269
270void Bu::Socket::setBlocking( bool bBlocking )
271{
272}
273
274void Bu::Socket::flush()
275{
276}
277
278bool Bu::Socket::isOpen()
279{
280 return bActive;
281}
282
283Bu::FString Bu::Socket::getAddress() const
284{
285 struct sockaddr_in addr;
286 socklen_t len = sizeof(addr);
287 addr.sin_family = AF_INET;
288 getsockname( nSocket, (sockaddr *)(&addr), &len );
289 char buf[150];
290 sprintf( buf, "%s", inet_ntoa( addr.sin_addr ) );
291
292 return buf;
293}
294