aboutsummaryrefslogtreecommitdiff
path: root/src/connection.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2007-04-03 03:49:53 +0000
committerMike Buland <eichlan@xagasoft.com>2007-04-03 03:49:53 +0000
commitf4c20290509d7ed3a8fd5304577e7a4cc0b9d974 (patch)
tree13cdf64f7cf134f397a7165b7a3fe0807e37026b /src/connection.cpp
parent74d4c8cd27334fc7204d5a8773deb3d424565778 (diff)
downloadlibbu++-f4c20290509d7ed3a8fd5304577e7a4cc0b9d974.tar.gz
libbu++-f4c20290509d7ed3a8fd5304577e7a4cc0b9d974.tar.bz2
libbu++-f4c20290509d7ed3a8fd5304577e7a4cc0b9d974.tar.xz
libbu++-f4c20290509d7ed3a8fd5304577e7a4cc0b9d974.zip
Ok, no code is left in src, it's all in src/old. We'll gradually move code back
into src as it's fixed and re-org'd. This includes tests, which, I may write a unit test system into libbu++ just to make my life easier.
Diffstat (limited to 'src/connection.cpp')
-rw-r--r--src/connection.cpp564
1 files changed, 0 insertions, 564 deletions
diff --git a/src/connection.cpp b/src/connection.cpp
deleted file mode 100644
index efef144..0000000
--- a/src/connection.cpp
+++ /dev/null
@@ -1,564 +0,0 @@
1#include "connection.h"
2#include <string.h>
3#include <stdio.h>
4#include <errno.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <sys/time.h>
10#include <netinet/in.h>
11#include <netdb.h>
12#include <arpa/inet.h>
13#include <errno.h>
14#include <fcntl.h>
15#include "exceptions.h"
16
17// Read buffer size...maybe fix wierd issues...
18#define RBS (1024*10)
19
20Connection::Connection()
21{
22 nSocket = -1;
23 bActive = false;
24 bDisconnectMe = false;
25 pProtocol = NULL;
26}
27
28Connection::~Connection()
29{
30 if( pProtocol != NULL ) delete pProtocol;
31}
32
33void Connection::ensureCapacity( int nSize )
34{
35 xOutputBuf.ensureCapacity( nSize );
36}
37
38bool Connection::appendOutput( const char *lpOutput, int nSize )
39{
40 return xOutputBuf.appendData( lpOutput, nSize );
41}
42
43bool Connection::appendOutput( const char lOutput )
44{
45 return xOutputBuf.appendData( lOutput );
46}
47
48bool Connection::appendOutput( const short lOutput )
49{
50 return xOutputBuf.appendData( lOutput );
51}
52
53bool Connection::appendOutput( const int lOutput )
54{
55 return xOutputBuf.appendData( lOutput );
56}
57
58bool Connection::appendOutput( const long lOutput )
59{
60 return xOutputBuf.appendData( lOutput );
61}
62
63bool Connection::appendOutput( const float lOutput )
64{
65 return xOutputBuf.appendData( lOutput );
66}
67
68bool Connection::appendOutput( const double lOutput )
69{
70 return xOutputBuf.appendData( lOutput );
71}
72
73bool Connection::appendOutput( const unsigned char lOutput )
74{
75 return xOutputBuf.appendData( lOutput );
76}
77
78bool Connection::appendOutput( const unsigned short lOutput )
79{
80 return xOutputBuf.appendData( lOutput );
81}
82
83bool Connection::appendOutput( const unsigned long lOutput )
84{
85 return xOutputBuf.appendData( lOutput );
86}
87
88bool Connection::appendOutput( const unsigned int lOutput )
89{
90 return xOutputBuf.appendData( lOutput );
91}
92
93bool Connection::appendInput( const char *lpInput, int nSize )
94{
95 return xInputBuf.appendData( lpInput, nSize );
96}
97
98int Connection::scanInputFor( char cTarget )
99{
100 const char *lpTmp = xInputBuf.getData();
101 int jMax = xInputBuf.getLength();
102
103 for( int j = 0; j < jMax; j++ )
104 {
105 if( lpTmp[j] == cTarget )
106 {
107 return j;
108 }
109 }
110
111 return -1;
112}
113
114const char *Connection::getOutput()
115{
116 return xOutputBuf.getData();
117}
118
119const char *Connection::getInput()
120{
121 return xInputBuf.getData();
122}
123
124void Connection::setSocket( int nNewSocket )
125{
126 nSocket = nNewSocket;
127}
128
129int Connection::getSocket()
130{
131 return nSocket;
132}
133
134bool Connection::isActive()
135{
136 return bActive;
137}
138
139void Connection::close()
140{
141 //printf("Close called, socket is: %s\n", bActive?"Active":"Inactive" );
142 if( bActive )
143 {
144 fsync( nSocket );
145 ::close( nSocket );
146 //printf("Socket closed.\n");
147 }
148 bActive = false;
149 //nSocket = -1;
150 xInputBuf.clearData();
151 xOutputBuf.clearData();
152 if( pProtocol != NULL )
153 {
154 delete pProtocol;
155 pProtocol = NULL;
156 }
157}
158
159bool Connection::open( int nNewSocket )
160{
161 bActive = true;
162 setSocket( nNewSocket );
163 bDisconnectMe = false;
164
165 return true;
166}
167
168bool Connection::open( const char *sAddr, int nPort, int nSec )
169{
170 struct sockaddr_in xServerName;
171 bActive = false;
172
173 /* Create the socket. */
174 nSocket = socket( PF_INET, SOCK_STREAM, 0 );
175
176 if( nSocket < 0 )
177 {
178 bActive = false;
179 return false;
180 }
181
182 // These lines set the socket to non-blocking, a good thing?
183 int flags;
184 flags = fcntl(nSocket, F_GETFL, 0);
185 flags |= O_NONBLOCK;
186 if (fcntl(nSocket, F_SETFL, flags) < 0)
187 {
188 return false;
189 }
190
191 /* Connect to the server. */
192 //printf("Resolving hostname (%s)...\n", sAddr );
193 {
194 struct hostent *hostinfo;
195
196 xServerName.sin_family = AF_INET;
197 xServerName.sin_port = htons( nPort );
198 hostinfo = gethostbyname( sAddr );
199 if (hostinfo == NULL)
200 {
201 return false;
202 }
203 xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr;
204 }
205
206 //printf("Making actual connection...");
207 //fflush( stdout );
208 connect(
209 nSocket,
210 (struct sockaddr *)&xServerName,
211 sizeof(xServerName)
212 );
213 //printf("Connected.\n");
214
215 bActive = true;
216 bDisconnectMe = false;
217
218 if( nSec > 0 )
219 {
220 fd_set rfds, wfds, efds;
221 int retval;
222
223 FD_ZERO(&rfds);
224 FD_SET(nSocket, &rfds);
225 FD_ZERO(&wfds);
226 FD_SET(nSocket, &wfds);
227 FD_ZERO(&efds);
228 FD_SET(nSocket, &efds);
229
230 struct timeval tv;
231 tv.tv_sec = nSec;
232 tv.tv_usec = 0;
233
234 retval = select( nSocket+1, &rfds, &wfds, &efds, &tv );
235
236 if( retval == 0 )
237 {
238 close();
239 throw ExceptionBase("Connection timeout.\n");
240 }
241
242 }
243
244 /*
245 if( ret < 0 )
246 {
247 return false;
248 }*/
249
250 return true;
251}
252
253int Connection::readInput()
254{
255 char buffer[RBS];
256 int nbytes;
257 int nTotalRead=0;
258
259 for(;;)
260 {
261 //memset( buffer, 0, RBS );
262
263 nbytes = read( nSocket, buffer, RBS );
264 if( nbytes < 0 && errno != 0 && errno != EAGAIN )
265 {
266 //printf("errno: %d, %s\n", errno, strerror( errno ) );
267 /* Read error. */
268 //perror("readInput");
269 throw ConnectionException( excodeReadError, "Read error: %s", strerror( errno ) );
270 }
271 else
272 {
273 if( nbytes <= 0 )
274 break;
275 nTotalRead += nbytes;
276 appendInput( buffer, nbytes );
277 /* Data read. */
278 if( nbytes < RBS )
279 {
280 break;
281 }
282
283 /* New test, if data is divisible by RBS bytes on some libs the
284 * read could block, this keeps it from happening.
285 */
286 {
287 fd_set rfds;
288 FD_ZERO(&rfds);
289 FD_SET(nSocket, &rfds);
290 struct timeval tv = { 0, 0 };
291 int retval = select( nSocket+1, &rfds, NULL, NULL, &tv );
292 if( retval == -1 )
293 throw ConnectionException(
294 excodeBadReadError,
295 "Bad Read error"
296 );
297 if( !FD_ISSET( nSocket, &rfds ) )
298 break;
299 }
300
301 }
302 }
303
304 if( pProtocol != NULL && nTotalRead > 0 )
305 {
306 pProtocol->onNewData();
307 }
308
309 return nTotalRead;
310}
311
312bool Connection::readInput( int nSec, int nUSec, int *pnSecBack, int *pnUSecBack )
313{
314 fd_set rfds, efds;
315 struct timeval tv, start, end;
316 struct timezone tz;
317 int retval;
318
319 gettimeofday( &start, &tz );
320
321 FD_ZERO(&rfds);
322 FD_SET(nSocket, &rfds);
323 FD_ZERO(&efds);
324 FD_SET(nSocket, &efds);
325
326 tv.tv_sec = nSec;
327 tv.tv_usec = nUSec;
328
329 //printf("Starting at %d %d\n", nSec, nUSec );
330 retval = select( nSocket+1, &rfds, NULL, NULL, &tv );
331
332 if( retval == -1 )
333 {
334 // Oh my god!!! some kind of horrible problem!!!!
335 throw ConnectionException( excodeBadReadError, "Bad Read error");
336 return false;
337 }
338 else if( retval )
339 {
340 //printf("retval=%d, nSocket=%d,%d, sec=%d, usec=%d\n", retval, nSocket, FD_ISSET( nSocket, &rfds ), tv.tv_sec, tv.tv_usec );
341 // None of them have data, but the connection is still active.
342 if( FD_ISSET( nSocket, &rfds ) )
343 {
344 if( readInput() == 0 )
345 {
346 throw ConnectionException( excodeConnectionClosed, "Connection closed"); }
347 }
348 }
349
350 gettimeofday( &end, &tz );
351
352 int st, ust;
353 st = nSec - ( end.tv_sec - start.tv_sec );
354 if( ( end.tv_usec - start.tv_usec ) > nUSec )
355 {
356 (st)--;
357 ust = 1000000 - (end.tv_usec - start.tv_usec);
358 }
359 else
360 {
361 ust = nUSec - (end.tv_usec - start.tv_usec);
362 }
363
364 if( st < 0 )
365 {
366 st = ust = 0;
367 }
368
369 if( pnSecBack )
370 {
371 *pnSecBack = st;
372 *pnUSecBack = ust;
373 }
374
375 //printf("New time: %d %d\n", *pnSecBack, *pnUSecBack );
376
377 return true;
378}
379
380void Connection::waitForInput( int nBytesIn, int nSec, int nUSec )
381{
382 int rlen = getInputAmnt();
383
384 if( rlen >= nBytesIn )
385 return;
386
387 while( rlen < nBytesIn )
388 {
389 if( nSec == 0 && nUSec == 0 )
390 {
391 throw ConnectionException( excodeSocketTimeout, "Timed out while waiting for %d bytes.", nBytesIn );
392 }
393 readInput( nSec, nUSec, &nSec, &nUSec );
394 rlen = getInputAmnt();
395 }
396}
397
398bool Connection::clearOutput()
399{
400 return xOutputBuf.clearData();
401}
402
403bool Connection::clearInput()
404{
405 return xInputBuf.clearData();
406}
407
408#define min( a, b ) ((a<b)?(a):(b))
409
410bool Connection::writeOutput()
411{
412 //int nBytes = TEMP_FAILURE_RETRY( write( nSocket, xOutputBuf.getData(), min( RBS, xOutputBuf.getLength() ) ) );
413 int nBytes = TEMP_FAILURE_RETRY( write( nSocket, xOutputBuf.getData(), xOutputBuf.getLength() ) );
414 if( nBytes < 0 )
415 {
416 perror("writeOutput");
417 return true;
418 }
419 /*
420 if( nBytes < xOutputBuf.getLength() )
421 {
422 printf("Havn't written all the data (%d/%d/%d%%)\n", nBytes, xOutputBuf.getLength(), nBytes/(xOutputBuf.getLength()*100) );
423 }
424 else
425 {
426 printf("Wrote all pending data.\n");
427 }
428 */
429 xOutputBuf.usedData( nBytes );
430 //clearOutput();
431
432 return true;
433}
434
435bool Connection::writeAllOutput()
436{
437 while( hasOutput() ) writeOutput();
438 return true;
439}
440
441bool Connection::hasOutput()
442{
443 if( xOutputBuf.getLength() == 0 )
444 {
445 return false;
446 }
447 else
448 {
449 return true;
450 }
451}
452
453bool Connection::hasInput()
454{
455 if( xInputBuf.getLength() == 0 )
456 {
457 return false;
458 }
459 else
460 {
461 return true;
462 }
463}
464
465bool Connection::usedInput( int nAmount )
466{
467 return xInputBuf.usedData( nAmount );
468}
469
470bool Connection::needDisconnect()
471{
472 return bDisconnectMe;
473}
474
475void Connection::disconnect()
476{
477 bDisconnectMe = true;
478}
479
480void Connection::setProtocol( class Protocol *pNewProtocol )
481{
482 pProtocol = pNewProtocol;
483 pProtocol->setConnection( this );
484}
485
486int Connection::getInputAmnt()
487{
488 return xInputBuf.getLength();
489}
490
491int Connection::getOutputAmnt()
492{
493 return xOutputBuf.getLength();
494}
495
496class Protocol *Connection::getProtocol()
497{
498 return pProtocol;
499}
500
501void Connection::printInputDebug( const char *lpPrefix, FILE *fh, int nBytesMax )
502{
503 printDataDebug(
504 (const unsigned char *)xInputBuf.getData(),
505 xInputBuf.getLength(),
506 "input",
507 lpPrefix,
508 fh,
509 nBytesMax
510 );
511}
512
513void Connection::printOutputDebug( const char *lpPrefix, FILE *fh, int nBytesMax )
514{
515 printDataDebug(
516 (const unsigned char *)xOutputBuf.getData(),
517 xOutputBuf.getLength(),
518 "output",
519 lpPrefix,
520 fh,
521 nBytesMax
522 );
523}
524
525void Connection::printDataDebug( const unsigned char *pData, long nDataLen, const char *lpName, const char *lpPrefix, FILE *fh, int nBytesMax )
526{
527 if( nBytesMax > 0 )
528 {
529 nDataLen = (nBytesMax<nDataLen)?(nBytesMax):(nDataLen);
530 }
531
532 fprintf( fh, "%sDisplaying %ld bytes of %s.\n", lpPrefix, nDataLen, lpName );
533 int j = 0;
534 fprintf( fh, lpPrefix );
535 for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n");
536 for(;;)
537 {
538 fprintf( fh, lpPrefix );
539 int kmax = 8;
540 if( nDataLen-j < 8 ) kmax = nDataLen-j;
541 for(int k = 0; k < 8; k++ )
542 {
543 if( k < kmax )
544 {
545 fprintf( fh, "%02X ", (int)((unsigned char)pData[j+k]) );
546 }
547 else
548 {
549 fprintf( fh, "-- ");
550 }
551 }
552 printf("| ");
553 for(int k = 0; k < kmax; k++ )
554 {
555 fprintf( fh, "%c ", (pData[j+k]>32 && pData[j+k]<=128)?(pData[j+k]):('.') );
556 }
557 fprintf( fh, "\n");
558 j += kmax;
559 if( j >= nDataLen ) break;
560 }
561 fprintf( fh, lpPrefix );
562 for( int l = 0; l < 8*3+2*8+2; l++ ) fprintf( fh, (l!=8*3)?("-"):("+") ); fprintf( fh, "\n");
563}
564