ASSA::IPv4Socket Class Reference

#include <IPv4Socket.h>

Inheritance diagram for ASSA::IPv4Socket:

ASSA::Socket List of all members.

Public Member Functions

 IPv4Socket ()
 Default constructor.
 IPv4Socket (const int fd_)
 Constructor from file descriptor.
 ~IPv4Socket ()
 Destructor will close connection.
IPv4Socketclone () const
 "Virtual constructor".
bool open (const int domain_)
 Create socket.
bool close ()
 Close socket connection.
bool connect (const Address &address_)
 Client makes connection with the server at address_.
virtual bool bind (const Address &my_address_)
 Server binds listening socket to its local well-known port.
IPv4Socketaccept ()
 Accept connection on the listening socket.
int read (char *buf_, const unsigned int size_)
 Read packet of specified size and save it to the given buffer.
int write (const char *buf_, const unsigned int size_)
 Perform blocking write by writing packet of specified size.
const int getHandler () const
 Get socket file descriptor.
const int getDomain () const
 Get socket domain type.
virtual Streambufrdbuf ()
 Return a pointer to the Socketbuf associated with the stream.
virtual Streambufrdbuf (Streambuf *sb_)
 Set new Socketbuf for internal IO buffering.
virtual int in_avail () const
 This function returns the number of characters immediately available in the get area of the underlying Socketbuf buffer without making a system call if Socket is doing buffering I/O.

Static Public Attributes

static const int MAXTCPBUFSZ
 Maximum TCP data frame (no options).

Private Member Functions

 IPv4Socket (const IPv4Socket &)
IPv4Socketoperator= (const IPv4Socket &)

Private Attributes

char * m_path
 Path of UNIX domain socket.
Streambufm_rdbuf
 Socketbuf.

Detailed Description

Definition at line 25 of file IPv4Socket.h.


Constructor & Destructor Documentation

ASSA::IPv4Socket::IPv4Socket  )  [inline]
 

Default constructor.

Definition at line 32 of file IPv4Socket.h.

References ASSA::SOCKTRACE, and trace_with_mask.

Referenced by accept(), and clone().

00033         : m_path (0), m_rdbuf (new Socketbuf (this)) {
00034         trace_with_mask("IPv4Socket::IPv4Socket()",SOCKTRACE);
00035     }

ASSA::IPv4Socket::IPv4Socket const int  fd_  )  [inline]
 

Constructor from file descriptor.

Parameters:
fd_ file descriptor to use

Definition at line 40 of file IPv4Socket.h.

References ASSA::Socket::m_fd, ASSA::SOCKTRACE, and trace_with_mask.

00041         : m_path (0), m_rdbuf (new Socketbuf (this)) {
00042         trace_with_mask("IPv4Socket::IPv4Socket(fd_)",SOCKTRACE);
00043 
00044         m_fd = fd_;
00045     }

ASSA::IPv4Socket::~IPv4Socket  )  [inline]
 

Destructor will close connection.

Definition at line 48 of file IPv4Socket.h.

References close(), m_rdbuf, ASSA::SOCKTRACE, and trace_with_mask.

00048                   {
00049         trace_with_mask("IPv4Socket::~IPv4Socket",SOCKTRACE);
00050         this->close ();
00051 
00052         if (m_rdbuf != 0) {
00053             delete m_rdbuf;
00054         }
00055     }

ASSA::IPv4Socket::IPv4Socket const IPv4Socket  )  [private]
 


Member Function Documentation

IPv4Socket * IPv4Socket::accept  ) 
 

Accept connection on the listening socket.

Returned is a COMPLETED connection (meaning that socket pair is ready for data transfer and doesn't need call to open()). This method will block waiting on connection to come if there is no connection requests waiting on the listenning socket queue. To avoid blocking, use select() first.

Returns:
newly created connected socket to the client, or 0 if error.

Definition at line 146 of file IPv4Socket.cpp.

References ASSA::Socket::clear(), close(), DL, EL, ASSA::ERROR, getDomain(), IPv4Socket(), ASSA::Socket::m_fd, ASSA::Socket::nonblocking, ASSA::SOCK, ASSA::SOCKTRACE, trace_with_mask, and ASSA::Socket::turnOptionOn().

00147 {
00148     /*
00149       Here's interesting spot - because accept() suppose to work
00150       both for INET and UNIX domain socket addresses, we have to
00151       allocate enough space and pass exact size of the address type 
00152       expected.
00153     
00154       Otherwise, if we use, for example, struct sockaddr_un as max.
00155       possible, and accept returns struct sockaddr_in, we can cast
00156       back to struct sockaddr_in, but internally address data members
00157       are not guaranteed to be aligned correctly!!!
00158     */
00159     trace_with_mask("IPv4Socket::accept",SOCKTRACE);
00160 
00161     socklen_t length = 0;
00162     int new_fd = -1;
00163     SA* remote_address = NULL;
00164 
00165     if ( getDomain() == AF_UNIX ) {
00166         length = sizeof(struct sockaddr_in);
00167         remote_address = (SA*) new SA_IN;
00168     }
00169     else { 
00170         remote_address = (SA*) new SA_UN;
00171         length = sizeof(struct sockaddr_un);
00172     }
00173     memset(remote_address, 0, length);
00174 
00175 #ifndef __CYGWIN32__
00176     new_fd = ::accept(m_fd, remote_address, &length);
00177 #else
00178     new_fd = ::accept(m_fd, remote_address, (int*)&length);
00179 #endif
00180     
00181     if ( new_fd < 0 ) {
00182         EL((ERROR,"OS::accept() failed\n"));
00183         close();
00184         return NULL;
00185     }
00186     if (length == sizeof(SA_IN)) {
00187         SA_IN* sa_in = (SA_IN*) remote_address;
00188 
00189         DL((SOCK,"Accepted new TCP connection from Addr %s, port %d\n", 
00190             inet_ntoa(sa_in->sin_addr), ntohs( sa_in->sin_port)));
00191     }
00192     else {
00193         SA_UN* sa_un = (SA_UN*) remote_address;
00194         DL((SOCK,"Accepted new UNIX connection from %s\n",
00195              sa_un->sun_path));
00196     }
00197     delete remote_address;
00198 
00199     IPv4Socket* s = new IPv4Socket (new_fd);
00200     s->clear ();
00201     s->turnOptionOn (Socket::nonblocking);
00202     return s;
00203 }

bool IPv4Socket::bind const Address my_address_  )  [virtual]
 

Server binds listening socket to its local well-known port.

This call should follow the call to open() and precede the call to accept().

Parameters:
my_address_ address to bind to
Returns:
true if success, false otherwise

Implements ASSA::Socket.

Definition at line 109 of file IPv4Socket.cpp.

References Assure_return, EL, ASSA::Socket::failbit, ASSA::Address::getAddress(), getDomain(), ASSA::Address::getLength(), ASSA::Socket::m_fd, m_path, ASSA::Socket::reuseaddr, ASSA::Socket::setstate(), ASSA::SOCK, ASSA::SOCKTRACE, trace_with_mask, and ASSA::Socket::turnOptionOn().

00110 {
00111     trace_with_mask("IPv4Socket::bind",SOCKTRACE);
00112 
00113     // if UNIX domain, save the path
00114     if ( getDomain() == AF_UNIX ) {
00115         char* p = ((SA_UN *) addr_.getAddress())->sun_path;
00116         m_path = new char[strlen(p)+1];
00117         strcpy(m_path, p);
00118         struct stat sb;
00119 
00120         if (stat (m_path, &sb) == 0) {
00121             if ( S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode) ) {
00122                 unlink(m_path);
00123             }
00124         }
00125     }
00126     /*---
00127       From Stevens, Ch 7.5 (p.196):
00128       "Set the SO_REUSEADDR socket option before calling bind(2)
00129       in all TCP servers."
00130       ---*/
00131     Assure_return ( turnOptionOn (reuseaddr) );
00132 
00133     int rt = ::bind(m_fd, addr_.getAddress(), addr_.getLength());
00134 
00135     if ( rt < 0) {
00136         EL((SOCK,"::bind() FD: %d failed\n",m_fd));
00137         setstate (Socket::failbit);
00138         return (false);
00139     }
00140     Assure_return ( (::listen(m_fd, 5) == 0) );
00141     return (true);
00142 }

IPv4Socket * IPv4Socket::clone  )  const
 

"Virtual constructor".

clone() function creates an exact copy of Socket by dup(2)-ing file descriptor and copying Socket's internal state.

Definition at line 300 of file IPv4Socket.cpp.

References ASSA::Socket::clear(), DL, ASSA::Socket::failbit, ASSA::Socket::good(), ASSA::Streambuf::in_avail(), IPv4Socket(), ASSA::Socket::m_fd, m_rdbuf, ASSA::Socket::setstate(), ASSA::SOCK, ASSA::SOCKTRACE, and trace_with_mask.

00301 {
00302     const char self[] = "IPv4Socket::clone"; 
00303     trace_with_mask(self,SOCKTRACE);
00304 
00305     int nfd = dup (m_fd);
00306 
00307     IPv4Socket* s = new IPv4Socket (nfd);
00308 
00309     DL((SOCK,"Original socket has %d bytes in its get_area\n",
00310         m_rdbuf->in_avail ()));
00311 
00312     if (nfd < 0 || !good ()) {
00313         s->setstate (Socket::failbit);
00314     }
00315     else {
00316         s->clear ();
00317     }
00318     return s;
00319 }

bool IPv4Socket::close  )  [virtual]
 

Close socket connection.

Returns:
true if success, fail if call to close() failed.

Implements ASSA::Socket.

Definition at line 54 of file IPv4Socket.cpp.

References DL, ASSA::Socket::failbit, ASSA::Socket::flush(), ASSA::Streambuf::in_avail(), ASSA::Socket::m_fd, m_rdbuf, ASSA::Streambuf::sbumpc(), ASSA::Socket::setstate(), ASSA::SOCK, ASSA::SOCKTRACE, and trace_with_mask.

Referenced by accept(), and ~IPv4Socket().

00055 {
00056     trace_with_mask("IPv4Socket::close()",SOCKTRACE);
00057 
00058     if (m_fd >= 0) {
00059         DL((SOCK,"Closed FD: %d\n",m_fd));
00060 
00061         /*--- Flush data in output stream buffer ---*/
00062         flush ();
00063 		::close(m_fd);
00064         setstate (Socket::failbit);
00065         m_fd = -1;
00066 
00067         /*--- 
00068           Socket can be re-opened in the future.
00069           If there is some bytes left in it since last read(2),
00070           clean them up.
00071           ---*/
00072 
00073         if (m_rdbuf && m_rdbuf->in_avail ()) {
00074             for (char c; (c=m_rdbuf->sbumpc ()) != EOF;) { }
00075         }
00076     }
00077     return (true);
00078 }

bool IPv4Socket::connect const Address address_  )  [virtual]
 

Client makes connection with the server at address_.

If socket is set to non-blocking mode, most likely connect() would return false with errno set to EINPROGRESS. See connect(2) manpage for details.

Parameters:
address_ peer address to connect with
Returns:
true for success, false for error

Reimplemented from ASSA::Socket.

Definition at line 82 of file IPv4Socket.cpp.

References DL, EL, ASSA::Address::getAddress(), getDomain(), ASSA::Address::getLength(), ASSA::Socket::m_fd, open(), ASSA::SOCK, ASSA::SOCKTRACE, and trace_with_mask.

00083 {
00084     trace_with_mask("IPv4Socket::connect()",SOCKTRACE);
00085 
00086     if (m_fd < 0 && open (getDomain()) == false) {
00087         return false;
00088     }
00089 
00090     int ret = ::connect (m_fd, 
00091                          (SA*) his_address_.getAddress(),
00092                          his_address_.getLength());
00093     if (ret < 0) {
00094         if (errno == EINPROGRESS) { // is it ASYNC connect in progress?
00095             DL((SOCK,"FD: %d OS::connect() error\n",m_fd));
00096         }
00097         else {
00098             EL((SOCK,"FD: %d OS::connect() error\n",m_fd));
00099         }
00100         return (false);
00101     }
00102     clear ();
00103     DL((SOCK,"Connection opened on FD: %d\n", m_fd));
00104     return (true);
00105 }

const int ASSA::IPv4Socket::getDomain  )  const [inline, virtual]
 

Get socket domain type.

Implements ASSA::Socket.

Definition at line 136 of file IPv4Socket.h.

References ASSA::Socket::m_type.

Referenced by accept(), bind(), and connect().

00136 { return m_type; }

const int ASSA::IPv4Socket::getHandler  )  const [inline, virtual]
 

Get socket file descriptor.

Implements ASSA::Socket.

Definition at line 133 of file IPv4Socket.h.

References ASSA::Socket::m_fd.

00133 { return m_fd; }

virtual int ASSA::IPv4Socket::in_avail  )  const [inline, virtual]
 

This function returns the number of characters immediately available in the get area of the underlying Socketbuf buffer without making a system call if Socket is doing buffering I/O.

Implements ASSA::Socket.

Definition at line 160 of file IPv4Socket.h.

References ASSA::Streambuf::in_avail(), and m_rdbuf.

00160 { return m_rdbuf->in_avail (); }

bool IPv4Socket::open const int  domain_  )  [virtual]
 

Create socket.

Socket domain type is specified as AF_INET for internet socket and AF_UNIX for UNIX domain socket (full duplex pipe).

Parameters:
domain_ domain
Returns:
true if socket is created successfully, false otherwise

Implements ASSA::Socket.

Definition at line 36 of file IPv4Socket.cpp.

References EL, ASSA::ERROR, ASSA::Socket::failbit, ASSA::Socket::m_fd, ASSA::Socket::m_type, ASSA::Socket::nonblocking, ASSA::Socket::setstate(), ASSA::SOCKTRACE, and trace_with_mask.

Referenced by connect().

00037 {
00038     trace_with_mask("IPv4Socket::open",SOCKTRACE);
00039     
00040     m_type = domain_;
00041     m_fd = ::socket(domain_, SOCK_STREAM, 0);
00042     if (m_fd < 0) {
00043         EL((ERROR,"OS::socket() error\n"));
00044         setstate (Socket::failbit);
00045         return (false);
00046     }
00047     clear ();
00048     turnOptionOn (Socket::nonblocking);
00049     return (true);
00050 }

IPv4Socket& ASSA::IPv4Socket::operator= const IPv4Socket  )  [private]
 

Streambuf * IPv4Socket::rdbuf Streambuf sb_  )  [virtual]
 

Set new Socketbuf for internal IO buffering.

IPv4Socket object assumes full ownership of the memory pointed by sb_ (it will be release when ~IPv4Socket destructor is called).

Returns:
Old Socketbuf object or sb_ if it is either NULL or matches old Socketbuf object.

Reimplemented from ASSA::Socket.

Definition at line 21 of file IPv4Socket.cpp.

References m_rdbuf, ASSA::SOCKTRACE, and trace_with_mask.

00022 { 
00023     trace_with_mask("IPv4Socket::rdbuf(sb_)",SOCKTRACE);
00024 
00025     if (sb_ == 0 || sb_ == m_rdbuf) {
00026         return (sb_);
00027     }
00028     Streambuf* old = m_rdbuf;
00029     m_rdbuf = sb_;
00030     return (old);
00031 }

virtual Streambuf* ASSA::IPv4Socket::rdbuf  )  [inline, virtual]
 

Return a pointer to the Socketbuf associated with the stream.

This is part of the construction of a stream, and the buffer class object is not normally changed. This function may be used to get at Socketbuf functionality directly, given a Socket object.

Reimplemented from ASSA::Socket.

Definition at line 144 of file IPv4Socket.h.

References m_rdbuf.

00144 { return m_rdbuf; }

int IPv4Socket::read char *  buf_,
const unsigned int  size_
[virtual]
 

Read packet of specified size and save it to the given buffer.

Parameters:
buf_ buffer where packet will be stored
size_ size of the packet to expect
Returns:
number of bytes read or -1 on error indicating the reason in errno. 0 is returned if remote host closed its socket connection.

Reimplemented from ASSA::Socket.

Definition at line 207 of file IPv4Socket.cpp.

References ASSA::Socket::m_fd, m_rdbuf, ASSA::Streambuf::sbumpc(), ASSA::SOCKTRACE, trace_with_mask, and ASSA::Streambuf::unbuffered().

00208 {
00209     trace_with_mask("IPv4Socket::read",SOCKTRACE);
00210 
00211     register int len;
00212     register int sz = size_;
00213     char* tmp = packet_;
00214     
00215     if (m_fd < 0) return -1;
00216 
00217     len = 0;
00218     if (m_rdbuf->unbuffered ()) { 
00219         /*
00220           --- This needs to be redesigned ---
00221           I should read a character at a time in loop,
00222           until I get all characters, or EWOULDBLOCK or EOF.
00223           If ::read() returns 0 or -1, it will be converted
00224           by sbumpc() into EOF. Otherwise, sbumpc() returns
00225           character read. Is this the right thing here to do? 
00226         */
00227         if ((len = m_rdbuf->sbumpc ()) >= 0) {
00228             *tmp = len; 
00229             len = 1;
00230         }
00231     }
00232     else {
00233         len = m_rdbuf->sgetn (tmp, sz);
00234     }
00235     if (len == -1) {
00236         /*
00237           Non-blocking socket delivered partial packet.
00238         */
00239         if (errno != EWOULDBLOCK) {
00240             EL((ERROR,"::read(fd = %d) \n",m_fd));
00241             setstate (Socket::failbit);
00242         }
00243         return len;
00244     }
00245     tmp += len;
00246     sz -= len;
00247 
00248     if ((size_ - sz) == 0) 
00249     {
00250         DL((SOCK,"Peer has dropped connection FD: %d\n",m_fd));
00251         setstate (Socket::failbit | Socket::eofbit);
00252         return 0;
00253     }
00254 
00255     DL((SOCKTRACE,"==> FD: %d Received %d bytes\n", m_fd, size_ - sz));
00256     MemDump::dump_to_log (SOCKTRACE, "Data received:", packet_, size_ - sz);
00257 
00258     /*
00259       Return number of bytes read. If all requested bytes have been
00260       read, then sz is 0 and size_ is returned. If sz != 0, then
00261       writer has sent us a partial packet.
00262     */
00263     return (size_ - sz);        
00264 }

int IPv4Socket::write const char *  buf_,
const unsigned int  size_
[virtual]
 

Perform blocking write by writing packet of specified size.

Parameters:
buf_ buffer to send
size_ packet size
Returns:
number of bytes written or -1 for error

Reimplemented from ASSA::Socket.

Definition at line 268 of file IPv4Socket.cpp.

References ASSA::Socket::m_fd, m_rdbuf, ASSA::SOCKTRACE, ASSA::Streambuf::sputc(), trace_with_mask, and ASSA::Streambuf::unbuffered().

00269 {
00270     trace_with_mask("IPv4Socket::write()",SOCKTRACE);
00271 
00272     register int ret = 0;
00273 
00274     if (m_fd < 0) return -1;
00275 
00276     if (m_rdbuf->unbuffered ()) {
00277         register int wlen = size_;
00278         register char* p = (char*) packet_;
00279 
00280         while (wlen-- > 0) {
00281             if (m_rdbuf->sputc (*p++) == EOF) {
00282                 return (EOF);
00283             }
00284         }
00285         ret = p - packet_;
00286     }
00287     else
00288         ret = m_rdbuf->sputn ((char*) packet_, size_);
00289 
00290     if (ret > 0) {
00291         DL((SOCK,"<= FD: %d Wrote %d bytes (requested %d bytes)\n",
00292             m_fd, ret, size_));
00293         MemDump::dump_to_log (SOCK, "Data written", (char*)packet_, ret);
00294     }
00295     return ret;
00296 }


Member Data Documentation

char* ASSA::IPv4Socket::m_path [private]
 

Path of UNIX domain socket.

Definition at line 171 of file IPv4Socket.h.

Referenced by bind().

Streambuf* ASSA::IPv4Socket::m_rdbuf [private]
 

Socketbuf.

Definition at line 174 of file IPv4Socket.h.

Referenced by clone(), close(), in_avail(), rdbuf(), read(), write(), and ~IPv4Socket().

const int ASSA::IPv4Socket::MAXTCPBUFSZ [static]
 

Maximum TCP data frame (no options).

Definition at line 29 of file IPv4Socket.h.


The documentation for this class was generated from the following files:
Generated on Mon Dec 19 16:37:18 2005 for libassa by  doxygen 1.4.5