libassa  3.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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__)
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
29 typedef unsigned int socklen_t;
30 #endif
31 
32 #include "assa/Socket.h"
33 #include "assa/XDRHack.h"
34 
35 using namespace ASSA;
36 
37 const int ASSA::Socket::PGSIZE = 4096;
38 
46 int
48 getBytesAvail (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)
57  ret = ioctlsocket (m_fd, FIONREAD, &ba);
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 
72 Socket&
75 {
76  if (good () && rdbuf ()) {
77  if (rdbuf ()->pubsync () == EOF) {
78  setstate (badbit);
79  }
80  }
81  return (*this);
82 }
83 
84 int
86 set_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 
102 int
103 Socket::
104 set_fd_options (long flags_)
105 {
106  trace_with_mask("Socket::set_fd_options",SOCKTRACE);
107  int val;
108  int ret;
109 
110 #if defined (WIN32)
111 
112  u_long set_nonblock = 1;
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 
145 int
146 Socket::
147 clear_fd_options (long flags_)
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 
173  ret = ::fcntl (m_fd, F_SETFL, newflags);
174 
175  newflags = ::fcntl (m_fd, F_GETFL, 0);
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 
183 bool
184 Socket::
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_)
194  optname = SO_REUSEADDR;
195  else {
196  EL((ASSAERR,"Invalid socket option\n"));
197  return false;
198  }
199  return set_option (SOL_SOCKET, optname, 1) == 0;
200 }
201 
202 bool
203 Socket::
205 {
206  trace_with_mask("Socket::turnOptionOff",SOCKTRACE);
207 
208  if (nonblocking == opt_)
209  return clear_fd_options (O_NONBLOCK);
210 
211  int optname;
212  if (reuseaddr == opt_)
213  optname = SO_REUSEADDR;
214  else {
215  EL((ASSAERR,"Invalid socket option\n"));
216  return false;
217  }
218  return set_option (SOL_SOCKET, optname, 0) == 0;
219 }
220 
221 bool
222 Socket::
223 setOption (opt_t opt_, int arg_)
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)
230  : clear_fd_options (O_NONBLOCK);
231  }
232 
233  if (rcvlowat == opt_) {
234  optname = SO_RCVLOWAT;
235  }
236  else if (sndlowat == opt_) {
237  optname = SO_SNDLOWAT;
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 
246 int
247 Socket::
248 getOption (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_) {
273  optname = SO_RCVLOWAT;
274  }
275  else if (sndlowat == opt_) {
276  optname = SO_SNDLOWAT;
277  }
278  else if (reuseaddr == opt_) {
279  optname = SO_REUSEADDR;
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 
306 int
307 Socket::
308 ignore(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 
357 Socket&
358 Socket::
359 operator>>(char& n_)
360 {
361 
362  int c = 0;
363  int len = sizeof (int);
364  XDR xdrs;
365  xdrmem_create (&xdrs, (caddr_t) &c, len, XDR_DECODE);
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 
379 Socket&
380 Socket::
381 operator>> (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 
400 Socket&
401 Socket::
402 operator>> (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 
414 Socket&
415 Socket::
416 operator>> (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) \
437 Socket& 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 
462 READ_INT(int);
463 READ_INT(unsigned int);
464 READ_INT(long);
465 READ_INT(unsigned long);
466 
467 Socket&
468 Socket::
469 operator>> (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 
485 Socket&
486 Socket::
487 operator>> (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 
506 Socket&
507 Socket::
508 operator<< (char n_)
509 {
510  /* See comment to operator>>(char n_) */
511 
512  int buf = 0;
513  int len = sizeof (int);
514  XDR xdrs;
515 
516  xdrmem_create (&xdrs, (caddr_t) &buf, len, XDR_ENCODE);
517  xdr_char (&xdrs, &n_);
518 
519  if (write ((const char*) &buf, len) != len) {
521  }
522  xdr_destroy (&xdrs);
523  return *this;
524 }
525 
544 Socket&
545 Socket::
546 operator<< (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 
565 operator<< (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 
577 operator<< (unsigned short n_)
578 {
579  u_short val = (u_short) htons((u_short)n_);
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) \
589 Socket& 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 
613 WRITE_INT(unsigned int);
614 WRITE_INT(long);
615 WRITE_INT(unsigned long);
616 
617 Socket&
618 Socket::
619 operator<< (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 
634 Socket&
635 Socket::
636 operator<< (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 
651 void
652 Socket::
653 dumpState (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 
698 bool
699 Socket::
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 
711 string
712 Socket::
713 decode_fcntl_flags (long mask_)
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 }
static string decode_fcntl_flags(long mask_)
Decipher flags packed into mask_ used in fcntl() call.
Definition: Socket.cpp:713
ASSA and system errors.
Definition: LogMask.h:34
bool fail() const
Indicates that earlier extraction opeartion has failed to match the required pattern of input...
Definition: Socket.h:328
void dumpState() const
Write state bits of the socket to the log file.
Definition: Socket.cpp:653
#define READ_INT(TYPE)
Definition: Socket.cpp:436
virtual int write(const char *buf_, const u_int size_)
Write specified number of bytes to the socket.
Definition: Socket.h:544
int ignore(int n_=INT_MAX, int delim_=EOF)
Extracts bytes and discards them.
Definition: Socket.cpp:308
unsigned short u_short
Definition: Logger_Impl.h:39
indicates that an input operation failed to read the expected characters, or that an output operation...
Definition: Socket.h:84
bool turnOptionOff(opt_t opt_)
Disable socket option.
Definition: Socket.cpp:204
int in_avail()
This function returns the number of characters immediately available in the get area.
Definition: Streambuf.h:399
int getBytesAvail(void) const
Return number of bytes available in socket receive buffer.
Definition: Socket.cpp:48
bool eof() const
An earlier extraction operation has encountered the end of file of the input stream (peer closed its ...
Definition: Socket.h:321
#define DL(X)
A macro for writing debug message to the Logger.
Definition: Logger.h:273
#define WRITE_INT(TYPE)
Definition: Socket.cpp:588
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition: Logger.h:437
bool setOption(opt_t opt_, int arg_)
Set socket option to value required.
Definition: Socket.cpp:223
int getOption(opt_t opt_) const
Get current value of a socket option.
Definition: Socket.cpp:248
virtual int read(char *buf_, const u_int size_)
Read expected number of bytes from the socket.
Definition: Socket.h:551
#define EL(X)
A macro for writing error message to the Logger.
Definition: Logger.h:285
int set_fd_options(long flags_)
Gateway method for setting file descriptor options.
Definition: Socket.cpp:104
Set Socket to a non-blocking mode (O_RDWR|O_NONBLOCK).
Definition: Socket.h:115
int clear_fd_options(long flags_)
Gateway method for clearing file descriptor options.
Definition: Socket.cpp:147
Socket & ends(Socket &os_)
ends manipulator.
Definition: Socket.h:622
static const int PGSIZE
Size of bytes of a kernel page.
Definition: Socket.h:74
virtual Socket & flush()
This function simply calls the public "synchronizing" function rdbuf()->pubsync() (assuming the assoc...
Definition: Socket.cpp:74
XDRHack provides XDR definitions for systems that have them missing.
Socket & operator>>(char &c)
Input of built-in char type. The value will be XDR-decoded.
Definition: Socket.cpp:359
unsigned long u_long
Definition: Logger_Impl.h:41
bool bad() const
Socket fd == -1 or read/write error occured or some loss of integrity on assosiated stream buffer...
Definition: Socket.h:337
virtual Streambuf * rdbuf()
Return a pointer to the Streambuf associated with the stream.
Definition: Socket.h:240
handler_t m_fd
File descriptor.
Definition: Socket.h:485
void setstate(iostate flag_)
Set socket state to flag_ by adding flag_ to the existing state.
Definition: Socket.h:577
opt_t
Socket options.
Definition: Socket.h:98
Socket & operator<<(char c)
Output of built-in char type. The value will be XDR-encoded.
Definition: Socket.cpp:508
bool good() const
Indicates no error on the socket.
Definition: Socket.h:315
static bool is_little_endian()
Determine the endianess of the platform we are on.
Definition: Socket.cpp:700
The receiver low-water mark is the amount of data that must be in the socket receive buffer for selec...
Definition: Socket.h:102
bool turnOptionOn(opt_t opt_)
Enable socket option.
Definition: Socket.cpp:185
Allow local address reuse.
Definition: Socket.h:100
The send low-water mark si the amount of available space that must exist in the socket send buffer fo...
Definition: Socket.h:108
int set_option(int level_, int optname_, int val_)
Gateway method of setting socket options.
Definition: Socket.cpp:86
indicates a loss of integrity in an input or output sequence (such as an irrecoverable read error fro...
Definition: Socket.h:87
indicates that an input operation reached the end of an input sequence
Definition: Socket.h:82
Abstraction of socket data type.
Extended Socket & friends messages.
Definition: LogMask.h:42