libassa 3.5.1
Loading...
Searching...
No Matches
Socket.cpp
Go to the documentation of this file.
1// -*- c++ -*-
2//------------------------------------------------------------------------------
3// $Id: Socket.cpp,v 1.13 2006/09/24 17:35:33 vlg Exp $
4//------------------------------------------------------------------------------
5// Socket.C
6//------------------------------------------------------------------------------
7// Copyright (c) 1999,2005 by Vladislav Grinchenko
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Library General Public
11// License as published by the Free Software Foundation; either
12// version 2 of the License, or (at your option) any later version.
13//------------------------------------------------------------------------
14// Created: 03/22/99
15//------------------------------------------------------------------------
16
17#include <sstream>
18#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__CYGWIN32__) || defined (__GNU__)
19# include <sys/ioctl.h>
20#endif
21
22#if defined (__NetBSD__)
23# include <sys/filio.h>
24# include <sys/ioctl.h>
25#endif
26
27#if defined (WIN32)
28# define O_NONBLOCK 04000
29typedef unsigned int socklen_t;
30#endif
31
32#include "assa/Socket.h"
33#include "assa/XDRHack.h"
34
35using namespace ASSA;
36
37const int ASSA::Socket::PGSIZE = 4096;
38
46int
48getBytesAvail (void) const
49{
50 trace_with_mask("Socket::getBytesAvail",SOCKTRACE);
51
52 Socket* This = (Socket*) this;
53 u_long ba = 0;
54 int ret = 0;
55
56#if defined(WIN32)
58#else
59 ret = ioctl (m_fd, FIONREAD, &ba);
60#endif
61
62 if (ret == -1) {
63 EL((ASSAERR,"ioctl(2) failed with ret: %d\n", ret));
64 return ret;
65 }
66 ba += This->rdbuf ()->in_avail ();
67
68 DL((SOCKTRACE,"%ld bytes available for reading\n", ba));
69 return (int(ba));
70}
71
72Socket&
74flush ()
75{
76 if (good () && rdbuf ()) {
77 if (rdbuf ()->pubsync () == EOF) {
79 }
80 }
81 return (*this);
82}
83
84int
86set_option (int level_, int optname_, int val_)
87{
88 int ret = setsockopt (m_fd,
89 level_,
90 optname_,
91 (const char*) &val_,
92 sizeof (val_));
93 if (ret < 0) {
95 }
96 return ret;
97}
98
102int
105{
106 trace_with_mask("Socket::set_fd_options",SOCKTRACE);
107 int val;
108 int ret;
109
110#if defined (WIN32)
111
113 if ((val = ioctlsocket (m_fd, FIONBIO, &set_nonblock)) == 0) {
114 m_nonblocking = true;
115 return 0;
116 }
117 return -1;
118
119#else // POSIX/UNIX
120
121 if ((val = ::fcntl (m_fd, F_GETFL, 0)) < 0) {
122 return -1;
123 }
124 val |= flags_; // turn flags on
125
126 DL ((SOCKTRACE,"Set flags fcntl(%d, %s)\n", m_fd,
127 decode_fcntl_flags (val).c_str ()));
128
129 ret = ::fcntl (m_fd, F_SETFL, val);
130
131 val = ::fcntl (m_fd, F_GETFL, 0);
132 DL ((SOCKTRACE,"Flags are set to %s via fcntl(25)\n",
133 decode_fcntl_flags (val).c_str ()));
134
135 return (ret);
136
137#endif
138}
139
145int
148{
149 trace_with_mask("Socket::clear_fd_options",SOCKTRACE);
150 long oldflags;
151 long newflags;
152 int ret;
153
154#if defined (WIN32)
155
156 u_long set_block = 0;
157 if ((ret = ioctlsocket (m_fd, FIONBIO, &set_block)) == 0) {
158 m_nonblocking = false;
159 return 0;
160 }
161 return -1;
162
163#else
164
165 if ((oldflags = ::fcntl (m_fd, F_GETFL, 0)) < 0) {
166 return -1;
167 }
168 newflags = oldflags & ~flags_; // clear flags
169
170 DL ((SOCKTRACE,"Set flags fcntl(%d, %s)\n", m_fd,
171 decode_fcntl_flags (newflags).c_str ()));
172
174
176 DL ((SOCKTRACE,"Flags are set to %s via fcntl(%d)\n",
177 decode_fcntl_flags (newflags).c_str ()));
178
179 return (ret);
180#endif
181}
182
183bool
186{
187 trace_with_mask("Socket::turnOptionOn",SOCKTRACE);
188
189 if (nonblocking == opt_)
190 return set_fd_options (O_NONBLOCK);
191
192 int optname;
193 if (reuseaddr == opt_)
195 else {
196 EL((ASSAERR,"Invalid socket option\n"));
197 return false;
198 }
199 return set_option (SOL_SOCKET, optname, 1) == 0;
200}
201
202bool
205{
206 trace_with_mask("Socket::turnOptionOff",SOCKTRACE);
207
208 if (nonblocking == opt_)
210
211 int optname;
212 if (reuseaddr == opt_)
214 else {
215 EL((ASSAERR,"Invalid socket option\n"));
216 return false;
217 }
218 return set_option (SOL_SOCKET, optname, 0) == 0;
219}
220
221bool
224{
225 trace_with_mask("Socket::setOption(,)",SOCKTRACE);
226 int optname;
227
228 if (nonblocking == opt_) {
229 return (arg_ == 1) ? set_fd_options (O_NONBLOCK)
231 }
232
233 if (rcvlowat == opt_) {
235 }
236 else if (sndlowat == opt_) {
238 }
239 else {
240 EL((ASSAERR,"Invalid socket option\n"));
241 return false;
242 }
243 return set_option (SOL_SOCKET, optname, arg_) == 0;
244}
245
246int
248getOption (opt_t opt_) const
249{
250 trace_with_mask("Socket::getOption",SOCKTRACE);
251 int optval = 0;
252
253 if (nonblocking == opt_)
254 {
255#if defined (WIN32)
256 return (m_nonblocking ? 1 : 0);
257#else
258 if ((optval = ::fcntl (m_fd, F_GETFL, 0)) < 0) {
259 return -1;
260 }
261 return ((optval & O_NONBLOCK) == O_NONBLOCK ? 1 : 0);
262#endif
263 }
264
265 int optname;
266 int level = SOL_SOCKET;
267 bool bin = false;
268
269 socklen_t len = sizeof (optval);
270 int ret;
271
272 if (rcvlowat == opt_) {
274 }
275 else if (sndlowat == opt_) {
277 }
278 else if (reuseaddr == opt_) {
280 bin = true;
281 }
282 else {
283 EL((ASSAERR,"Invalid socket option\n"));
284 return (-1);
285 }
286
287#if defined (__CYGWIN32__) || defined (WIN32)
288
289 ret = getsockopt (m_fd, level, optname, (char*) &optval, (int*)&len);
290
291#else // posix/unix
292
293 ret = getsockopt (m_fd, level, optname, (char*) &optval, &len);
294
295#endif
296
297 if (ret < 0) {
298 return (-1);
299 }
300 if (bin) {
301 return (ret == 0 ? 0 : 1);
302 }
303 return (ret);
304}
305
306int
308ignore(int n_, int delim_)
309{
310 trace_with_mask("Socket::ignore",SOCKTRACE);
311 register int b;
312 register int count = 0;
313 register char c;
314
315 if (n_ == INT_MAX && delim_ == EOF) {
316 char buf[PGSIZE];
317 while ((b = read (buf, PGSIZE))) {
318 count += b;
319 }
321 return count;
322 }
323 for (; n_; n_--, count++) {
324 if ( (b = read (&c, 1)) == 0 ) {
326 break;
327 }
328 if ( c == delim_ )
329 break;
330 }
331 return count;
332}
333
334//-----------------------------------------------------------------------------
335// Input operators
336//-----------------------------------------------------------------------------
337
357Socket&
359operator>>(char& n_)
360{
361
362 int c = 0;
363 int len = sizeof (int);
364 XDR xdrs;
366
367 if (read ((char* ) &c, len) == len) {
368 xdr_char (&xdrs, &n_);
369 }
370 else {
372 }
373 xdr_destroy(&xdrs);
374 return *this;
375}
376
379Socket&
381operator>> (std::string& s_)
382{
383 char c = 0;
384 size_t n = 0;
385 s_ = "";
386
387 (*this) >> n;
388
389 if (n == 0) {
390 return *this;
391 }
392 size_t len = n;
393 while (len-- && read (&c, 1) == 1) {
394 s_ += c;
395 }
396 ignore (4 - n % 4);
397 return *this;
398}
399
400Socket&
402operator>> (short& n_)
403{
404 short val;
405 if (read ((char*) &val, sizeof(short)) == sizeof(short)) {
406 n_ = (short) ntohs ((short)val);
407 }
408 else {
410 }
411 return *this;
412}
413
414Socket&
416operator>> (unsigned short& n_)
417{
418 u_short val;
419 if (read ((char*) &val, sizeof(u_short)) == sizeof(u_short)) {
420 n_ = (u_short) ntohs ((u_short)val);
421 }
422 else {
424 }
425 return *this;
426}
427
428#define LONGEST long
429
430/* On 64-bit platforms, sizeof (long) = 8 bytes.
431 * ntohl()/htonh() operats only on int32_t types which is 4 bytes long
432 * everywhere. So, for 64-bit longs we need to process twice as much
433 * and swapt data accordingly.
434 */
435
436#define READ_INT(TYPE) \
437Socket& Socket::operator>>(TYPE& n_) \
438{\
439 LONGEST val;\
440 int typesz = sizeof(TYPE);\
441 if (read ( (char* ) &val, typesz) == typesz) {\
442 if (sizeof(int32_t) <= typesz) {\
443 n_ = (TYPE) ntohl (val); \
444 }\
445 else {\
446 if (Socket::is_little_endian ()) {\
447 *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val)) );\
448 *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val))+1);\
449 }\
450 else {\
451 *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val)) );\
452 *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val))+1);\
453 }\
454 }\
455 }\
456 else {\
457 setstate (Socket::eofbit|Socket::failbit);\
458 }\
459 return *this;\
460}
461
463READ_INT(unsigned int);
465READ_INT(unsigned long);
466
467Socket&
469operator>> (float& n_)
470{
471 float val;
472 XDR xdrs;
473 xdrmem_create (&xdrs, (caddr_t) &val, sizeof(float), XDR_DECODE);
474
475 if (read ((char*) &val, sizeof(float)) == sizeof(float)) {
476 xdr_float (&xdrs, &n_);
477 }
478 else {
480 }
481 xdr_destroy (&xdrs);
482 return *this;
483}
484
485Socket&
487operator>> (double& n_)
488{
489 double val = 0;
490 XDR xdrs;
491 xdrmem_create (&xdrs, (caddr_t) &val, sizeof(double), XDR_DECODE);
492 if (read ((char*) &val, sizeof(double)) == sizeof(double)) {
493 xdr_double (&xdrs, &n_);
494 }
495 else {
497 }
498 xdr_destroy (&xdrs);
499 return *this;
500}
501
502//-----------------------------------------------------------------------------
503// Output operators
504//-----------------------------------------------------------------------------
505
508operator<< (char n_)
509{
510 /* See comment to operator>>(char n_) */
511
512 int buf = 0;
513 int len = sizeof (int);
514 XDR xdrs;
515
517 xdr_char (&xdrs, &n_);
518
519 if (write ((const char*) &buf, len) != len) {
521 }
522 xdr_destroy (&xdrs);
523 return *this;
524}
525
546operator<< (const std::string& s_)
547{
548 static const char pad [4] = { 0, 0, 0, 0 };
549
550 (*this) << s_.length ();
551 int ret = write (s_.c_str (), s_.length ());
552 if ( ret != s_.length () ) {
554 }
555 size_t r = 4 - s_.length() % 4;
556 if (r) {
557 if (write (pad, r) != r) {
559 }
560 }
561 return *this;
562}
563
565operator<< (short n_)
566{
567 short val = (short) htons((short)n_);
568
569 if (write ((const char*) &val, sizeof(short)) != sizeof(short))
570 {
572 }
573 return *this;
574}
575
577operator<< (unsigned short n_)
578{
580
581 if (write ((const char*) &val, sizeof(u_short)) != sizeof(u_short))
582 {
584 }
585 return *this;
586}
587
588#define WRITE_INT(TYPE) \
589Socket& Socket::operator<< (TYPE n_) \
590{ \
591 LONGEST val;\
592 int typesz = sizeof(TYPE);\
593 if (sizeof(int32_t) <= typesz) {\
594 val = (TYPE) ntohl (n_); \
595 }\
596 else {\
597 if (Socket::is_little_endian ()) {\
598 *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_)) );\
599 *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_))+1);\
600 }\
601 else {\
602 *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_)) );\
603 *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_))+1);\
604 }\
605 }\
606 if (write ((const char*) &val, typesz) != typesz) {\
607 setstate (Socket::eofbit|Socket::failbit);\
608 }\
609 return *this;\
610}
611
613WRITE_INT(unsigned int);
615WRITE_INT(unsigned long);
616
619operator<< (float n_)
620{
621 float buf, f = n_;
622 XDR xdrs;
623 xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(float), XDR_ENCODE);
624 xdr_float (&xdrs, &f);
625
626 int ret = write ((const char*) &buf, sizeof(float));
627 xdr_destroy (&xdrs);
628 if ( ret != sizeof(float) ) {
630 }
631 return *this;
632}
633
636operator<< (double n_)
637{
638 double buf, f = n_;
639 XDR xdrs;
640 xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(double), XDR_ENCODE);
641 xdr_double (&xdrs, &f);
642
643 int ret = write ((const char*) &buf, sizeof(double));
644 xdr_destroy (&xdrs);
645 if ( ret != sizeof(double) ) {
647 }
648 return *this;
649}
650
651void
653dumpState (void) const
654{
655 trace_with_mask("Socket::dumpState",SOCKTRACE);
656
657 char state_set[] = "[ set]\n";
658 char state_not_set[] = "[not set]\n";
659
660 std::ostringstream msg;
661
662 msg << "\n";
663 msg << "\tTesting good() ....... ";
664
665 if (this->good ()) msg << state_set;
666 else msg << state_not_set;
667
668 msg << "\tTesting eof() ........ ";
669 if (this->eof ()) msg << state_set;
670 else msg << state_not_set;
671
672 msg << "\tTesting fail() ....... ";
673 if (this->fail ()) msg << state_set;
674 else msg << state_not_set;
675
676 msg << "\tTesting bad() ........ ";
677 if (this->bad ()) msg << state_set;
678 else msg << state_not_set;
679
680 msg << "\tTesting !() .......... ";
681 if ( !(*this) ) msg << state_set;
682 else msg << state_not_set;
683
684 msg << "\tTesting void *() ..... ";
685 if ( *this ) msg << state_set;
686 else msg << state_not_set;
687
688 msg << "\tTesting nonblocking... ";
689 if (getOption (nonblocking) == 1) msg << state_set;
690 else msg << state_not_set;
691
692 /*--- Terminate stream buffer ---*/
693 msg << std::ends;
694
695 DL((SOCKTRACE,"%s\n", msg.str ().c_str ()));
696}
697
698bool
701{
702 union {
703 char c [sizeof (short)];
704 short v;
705 } endian_u;
706
707 endian_u.v = 256;
708 return (endian_u.c [0] == 0);
709}
710
711string
714{
715 string answer;
716
717#if !defined (WIN32)
718
719 if (mask_ & O_RDONLY) {
720 answer = "O_RDONLY|"; // 000000
721 }
722 if (mask_ & O_WRONLY) {
723 answer += "O_WRONLY|"; // 000001
724 }
725 if (mask_ & O_RDWR) {
726 answer += "O_RDWR|"; // 000002
727 }
728 if (mask_ & O_APPEND) {
729 answer += "O_APPEND|"; // 001000
730 }
731 if (mask_ & O_NONBLOCK) {
732 answer += "O_NONBLOCK|";// 004000
733 }
734 if (mask_ & O_SYNC) {
735 answer += "O_SYNC|"; // 010000
736 }
737
738 if (mask_ & O_ASYNC) { // 020000
739 answer += "O_ASYNC|";
740 }
741
742 answer.erase (answer.end () - 1);
743
744#endif
745
746 return answer;
747}
#define EL(X)
A macro for writing error message to the Logger.
Definition Logger.h:285
#define DL(X)
A macro for writing debug message to the Logger.
Definition Logger.h:273
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition Logger.h:437
unsigned short u_short
Definition Logger_Impl.h:39
#define READ_INT(TYPE)
Definition Socket.cpp:436
#define WRITE_INT(TYPE)
Definition Socket.cpp:588
Abstraction of socket data type.
XDRHack provides XDR definitions for systems that have them missing.
A wrapper class to provide AutoPtr with reference semantics.
Definition AutoPtr.h:32
bool fail() const
Indicates that earlier extraction opeartion has failed to match the required pattern of input.
Definition Socket.h:328
int clear_fd_options(long flags_)
Gateway method for clearing file descriptor options.
Definition Socket.cpp:147
Socket & operator>>(char &c)
Input of built-in char type. The value will be XDR-decoded.
Definition Socket.cpp:359
virtual Streambuf * rdbuf()
Return a pointer to the Streambuf associated with the stream.
Definition Socket.h:240
void dumpState() const
Write state bits of the socket to the log file.
Definition Socket.cpp:653
void setstate(iostate flag_)
Set socket state to flag_ by adding flag_ to the existing state.
Definition Socket.h:577
static string decode_fcntl_flags(long mask_)
Decipher flags packed into mask_ used in fcntl() call.
Definition Socket.cpp:713
int set_fd_options(long flags_)
Gateway method for setting file descriptor options.
Definition Socket.cpp:104
bool turnOptionOff(opt_t opt_)
Disable socket option.
Definition Socket.cpp:204
virtual int read(char *buf_, const u_int size_)
Read expected number of bytes from the socket.
Definition Socket.h:551
int set_option(int level_, int optname_, int val_)
Gateway method of setting socket options.
Definition Socket.cpp:86
bool turnOptionOn(opt_t opt_)
Enable socket option.
Definition Socket.cpp:185
opt_t
Socket options.
Definition Socket.h:99
@ reuseaddr
Allow local address reuse.
Definition Socket.h:100
@ sndlowat
The send low-water mark si the amount of available space that must exist in the socket send buffer fo...
Definition Socket.h:108
@ rcvlowat
The receiver low-water mark is the amount of data that must be in the socket receive buffer for selec...
Definition Socket.h:102
@ nonblocking
Set Socket to a non-blocking mode (O_RDWR|O_NONBLOCK).
Definition Socket.h:115
static bool is_little_endian()
Determine the endianess of the platform we are on.
Definition Socket.cpp:700
bool eof() const
An earlier extraction operation has encountered the end of file of the input stream (peer closed its ...
Definition Socket.h:321
handler_t m_fd
File descriptor.
Definition Socket.h:485
bool bad() const
Socket fd == -1 or read/write error occured or some loss of integrity on assosiated stream buffer.
Definition Socket.h:337
int getOption(opt_t opt_) const
Get current value of a socket option.
Definition Socket.cpp:248
bool good() const
Indicates no error on the socket.
Definition Socket.h:315
int ignore(int n_=INT_MAX, int delim_=EOF)
Extracts bytes and discards them.
Definition Socket.cpp:308
Socket & operator<<(char c)
Output of built-in char type. The value will be XDR-encoded.
Definition Socket.cpp:508
virtual Socket & flush()
This function simply calls the public "synchronizing" function rdbuf()->pubsync() (assuming the assoc...
Definition Socket.cpp:74
@ eofbit
indicates that an input operation reached the end of an input sequence
Definition Socket.h:82
@ badbit
indicates a loss of integrity in an input or output sequence (such as an irrecoverable read error fro...
Definition Socket.h:87
@ failbit
indicates that an input operation failed to read the expected characters, or that an output operation...
Definition Socket.h:84
static const int PGSIZE
Size of bytes of a kernel page.
Definition Socket.h:74
bool setOption(opt_t opt_, int arg_)
Set socket option to value required.
Definition Socket.cpp:223
virtual int write(const char *buf_, const u_int size_)
Write specified number of bytes to the socket.
Definition Socket.h:544
int getBytesAvail(void) const
Return number of bytes available in socket receive buffer.
Definition Socket.cpp:48
@ SOCKTRACE
Extended Socket & friends messages
Definition LogMask.h:42
@ ASSAERR
ASSA and system errors
Definition LogMask.h:34