libassa 3.5.0
Public Member Functions | Static Public Attributes | Private Member Functions

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 handler_t 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.
handler_t 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().

        : m_path (0), m_rdbuf (new Socketbuf (this)) {
        trace_with_mask("IPv4Socket::IPv4Socket()",SOCKTRACE);
    }
ASSA::IPv4Socket::IPv4Socket ( const handler_t  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.

        : m_path (0), m_rdbuf (new Socketbuf (this))
    {
        trace_with_mask("IPv4Socket::IPv4Socket(fd_)",SOCKTRACE);

        m_fd = fd_;             // inherited from the parent class
    }
ASSA::IPv4Socket::~IPv4Socket ( ) [inline]

Destructor will close connection.

Definition at line 49 of file IPv4Socket.h.

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

    {
        trace_with_mask("IPv4Socket::~IPv4Socket",SOCKTRACE);
        this->close ();

        if (m_rdbuf != 0) {
            delete m_rdbuf;
        }
    }
ASSA::IPv4Socket::IPv4Socket ( const IPv4Socket ) [private]

Member Function Documentation

IPv4Socket * IPv4Socket::accept ( )

Accept connection on the listening socket.

Here's an interesting spot - because accept() suppose to work both for INET and UNIX domain socket addresses, we have to allocate enough space and pass exact size of the address type expected.

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.

Otherwise, if we use, for example, struct sockaddr_un as max. and accept returns struct sockaddr_in, we can cast back to struct sockaddr_in, but internally address data members are not guaranteed to be aligned correctly!!!

Definition at line 176 of file IPv4Socket.cpp.

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

{
    trace_with_mask("IPv4Socket::accept",SOCKTRACE);

    socklen_t length = 0;
    SA*       remote_address = NULL;
    handler_t new_fd;

    disable_handler (new_fd);

    if ( getDomain() == AF_UNIX ) {
        length = sizeof(struct sockaddr_in);
        remote_address = (SA*) new SA_IN;
    }
    else   /* AF_INET */
    { 
        remote_address = (SA*) new SA_UN;
        length = sizeof(struct sockaddr_un);
    }
    memset(remote_address, 0, length);

#if !defined (_CYGWIN32__)
    new_fd = ::accept(m_fd, remote_address, &length);
#else
    new_fd = ::accept(m_fd, remote_address, (int*)&length);
#endif
    
    if (!is_valid_handler (new_fd)) {
        EL((ASSAERR,"::accept() failed (new_fd=%d)\n", new_fd));
        close();
        return NULL;
    }
    if (length == sizeof(SA_IN)) {
        SA_IN* sa_in = (SA_IN*) remote_address;

        DL((SOCK,"Accepted new TCP connection from Addr %s, port %d\n", 
            inet_ntoa(sa_in->sin_addr), ntohs( sa_in->sin_port)));
    }
    else {
#if !defined(WIN32)
        SA_UN* sa_un = (SA_UN*) remote_address;
        DL((SOCK,"Accepted new UNIX connection from %s\n", sa_un->sun_path));
#endif
    }
    delete remote_address;

    IPv4Socket* s = new IPv4Socket (new_fd);
    s->clear ();
    s->turnOptionOn (Socket::nonblocking);
    return s;
}
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

If UNIX domain, save the path

Implements ASSA::Socket.

Definition at line 123 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().

{
    trace_with_mask("IPv4Socket::bind",SOCKTRACE);

#if !defined(WIN32)

    if ( getDomain() == AF_UNIX ) {
        char* p = ((SA_UN *) addr_.getAddress())->sun_path;
        m_path = new char[strlen(p)+1];
        strcpy(m_path, p);
        struct stat sb;

        if (stat (m_path, &sb) == 0) {
            if ( S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode) ) {
                unlink(m_path);
            }
        }
    }
#endif

    /*---
      From Stevens, Ch 7.5 (p.196):
      "Set the SO_REUSEADDR socket option before calling bind(2)
      in all TCP servers."
      ---*/
    Assure_return ( turnOptionOn (reuseaddr) );

    int rt = ::bind(m_fd, addr_.getAddress(), addr_.getLength());

    if ( rt < 0) {
        EL((SOCK,"::bind() FD: %d failed\n",m_fd));
        setstate (Socket::failbit);
        return (false);
    }
    Assure_return ( (::listen(m_fd, 5) == 0) );
    return (true);
}
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 329 of file IPv4Socket.cpp.

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

{
    const char self[] = "IPv4Socket::clone"; 
    trace_with_mask(self,SOCKTRACE);

    handler_t nfd = dup (m_fd);
    IPv4Socket* s = new IPv4Socket (nfd);

    DL((SOCK,"Original socket has %d bytes in its get_area\n",
        m_rdbuf->in_avail ()));

    if (!is_valid_handler (nfd) || !good ()) {
        s->setstate (Socket::failbit);
    }
    else {
        s->clear ();
    }

    return s;
}
bool IPv4Socket::close ( void  ) [virtual]

Close socket connection.

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

Implements ASSA::Socket.

Definition at line 65 of file IPv4Socket.cpp.

References ASSA::Socket::close_handler(), DL, ASSA::Socket::failbit, ASSA::Socket::flush(), ASSA::Streambuf::in_avail(), ASSA::is_valid_handler(), 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().

{
    trace_with_mask("IPv4Socket::close()",SOCKTRACE);

    if (is_valid_handler (m_fd)) {
        DL((SOCK,"Closed FD: %d\n",m_fd));

        /*--- Flush data in output stream buffer ---*/
        flush ();
        close_handler(m_fd);
        setstate (Socket::failbit);

        /*--- 
          Socket can be re-opened in the future.
          If there is some bytes left in it since last read(2),
          clean them up.
          ---*/

        if (m_rdbuf && m_rdbuf->in_avail ()) {
            for (int c; (c=m_rdbuf->sbumpc ()) != EOF;) { }
        }
    }
    return (true);
}
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 92 of file IPv4Socket.cpp.

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

{
    trace_with_mask("IPv4Socket::connect()",SOCKTRACE);

    if (!is_valid_handler (m_fd) && open (getDomain()) == false) {
        return false;
    }

    int ret = ::connect (m_fd, 
                         (SA*) his_address_.getAddress(),
                         his_address_.getLength());
    if (ret < 0) 
    {
        int e = get_errno ();   // is ASYNC connect in progress?
        if (e == EINPROGRESS || e == EWOULDBLOCK) { 
            DL((SOCK,"FD: %d OS::connect() error\n",m_fd));
        }
        else {
            EL((SOCK,"FD: %d OS::connect() error\n",m_fd));
        }
        return (false);
    }

    clear ();

    DL((SOCK,"Connection opened on FD: %d\n", m_fd));
    return (true);
}
const int ASSA::IPv4Socket::getDomain ( ) const [inline, virtual]

Get socket domain type.

Implements ASSA::Socket.

Definition at line 138 of file IPv4Socket.h.

References ASSA::Socket::m_type.

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

{ return m_type; }
handler_t ASSA::IPv4Socket::getHandler ( ) const [inline, virtual]

Get socket file descriptor.

Implements ASSA::Socket.

Definition at line 135 of file IPv4Socket.h.

References ASSA::Socket::m_fd.

{ 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 162 of file IPv4Socket.h.

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

{ 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 41 of file IPv4Socket.cpp.

References ASSA::ASSAERR, ASSA::Socket::clear(), ASSA::disable_handler(), DL, EL, ASSA::Socket::failbit, ASSA::is_valid_handler(), ASSA::Socket::m_fd, ASSA::Socket::m_type, ASSA::Socket::nonblocking, ASSA::Socket::setstate(), ASSA::SOCK, ASSA::SOCKTRACE, trace_with_mask, and ASSA::Socket::turnOptionOn().

Referenced by connect().

{
    trace_with_mask("IPv4Socket::open",SOCKTRACE);
    
    m_type = domain_;

    m_fd = ::socket(domain_, SOCK_STREAM, 0);

    if (!is_valid_handler (m_fd)) {
        EL((ASSAERR,"OS::socket() error: m_fd = %d\n", m_fd));
        setstate (Socket::failbit);
        disable_handler (m_fd);
        return (false);
    }
    DL ((SOCK,"domain = %d, m_fd = %d\n", domain_, m_fd));

    clear ();
    turnOptionOn (Socket::nonblocking);

    return (true);
}
IPv4Socket& ASSA::IPv4Socket::operator= ( const IPv4Socket ) [private]
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 146 of file IPv4Socket.h.

References m_rdbuf.

{ return m_rdbuf; }
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 26 of file IPv4Socket.cpp.

References m_rdbuf, ASSA::SOCKTRACE, and trace_with_mask.

{ 
    trace_with_mask("IPv4Socket::rdbuf(sb_)",SOCKTRACE);

    if (sb_ == 0 || sb_ == m_rdbuf) {
        return (sb_);
    }
    Streambuf* old = m_rdbuf;
    m_rdbuf = sb_;
    return (old);
}
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.

Non-blocking socket delivered partial packet.

Reimplemented from ASSA::Socket.

Definition at line 230 of file IPv4Socket.cpp.

References ASSA::ASSAERR, DL, ASSA::MemDump::dump_to_log(), EL, ASSA::Socket::eofbit, ASSA::Socket::failbit, ASSA::get_errno(), ASSA::is_valid_handler(), ASSA::Socket::m_fd, m_rdbuf, ASSA::Streambuf::sbumpc(), ASSA::Socket::setstate(), ASSA::Streambuf::sgetn(), ASSA::SOCK, ASSA::SOCKTRACE, trace_with_mask, and ASSA::Streambuf::unbuffered().

{
    trace_with_mask("IPv4Socket::read",SOCKTRACE);

    register int len;
    register int sz = size_;
    char* tmp = packet_;
    
    if (!is_valid_handler (m_fd) < 0) {
        return -1;
    }

    len = 0;
    if (m_rdbuf->unbuffered ()) { 
        /*
          --- This needs to be redesigned ---
          I should read a character at a time in loop,
          until I get all characters, or EWOULDBLOCK or EOF.
          If ::read() returns 0 or -1, it will be converted
          by sbumpc() into EOF. Otherwise, sbumpc() returns
          character read. Is this the right thing here to do? 
        */
        if ((len = m_rdbuf->sbumpc ()) >= 0) {
            *tmp = len; 
            len = 1;
        }
    }
    else {
        len = m_rdbuf->sgetn (tmp, sz);
    }
    if (len == -1) 
    {
        if (get_errno () != EWOULDBLOCK) {
            EL((ASSAERR,"::read (fd=%d) failed.\n",m_fd));
            setstate (Socket::failbit);
        }
        return len;
    }
    tmp += len;
    sz  -= len;

    if ((size_ - sz) == 0) 
    {
        DL((SOCK,"Peer has dropped connection FD: %d\n",m_fd));
        setstate (Socket::failbit | Socket::eofbit);
        return 0;
    }

    DL((SOCKTRACE,"==> FD: %d Received %d bytes\n", m_fd, size_ - sz));
    MemDump::dump_to_log (SOCKTRACE, "Data received:", packet_, size_ - sz);

    /*
      Return number of bytes read. If all requested bytes have been
      read, then sz is 0 and size_ is returned. If sz != 0, then
      writer has sent us a partial packet.
    */
    return (size_ - sz);        
}
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 293 of file IPv4Socket.cpp.

References DL, ASSA::MemDump::dump_to_log(), ASSA::is_valid_handler(), ASSA::Socket::m_fd, m_rdbuf, ASSA::SOCK, ASSA::SOCKTRACE, ASSA::Streambuf::sputc(), ASSA::Streambuf::sputn(), trace_with_mask, and ASSA::Streambuf::unbuffered().

{
    trace_with_mask("IPv4Socket::write()",SOCKTRACE);

    int ret = 0;

    if (!is_valid_handler (m_fd)) {
        return -1;
    }

    if (m_rdbuf->unbuffered ()) 
    {
        int wlen = size_;
        char* p = (char*) packet_;

        while (wlen-- > 0) {
            if (m_rdbuf->sputc (*p++) == EOF) {
                return (EOF);
            }
        }
        ret = p - packet_;
    }
    else {
        ret = m_rdbuf->sputn ((char*) packet_, size_);
    }

    if (ret > 0) {
        DL((SOCK,"<= FD: %d Wrote %d bytes (requested %d bytes)\n",
            m_fd, ret, size_));
        MemDump::dump_to_log (SOCK, "Data written", (char*)packet_, ret);
    }
    return ret;
}

Member Data Documentation

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

Path of UNIX domain socket.

Definition at line 173 of file IPv4Socket.h.

Referenced by bind().

Socketbuf.

Definition at line 176 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:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines