libassa 3.5.0
|
#include <IPv4Socket.h>
Public Member Functions | |
IPv4Socket () | |
Default constructor. | |
IPv4Socket (const handler_t fd_) | |
Constructor from file descriptor. | |
~IPv4Socket () | |
Destructor will close connection. | |
IPv4Socket * | clone () 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. | |
IPv4Socket * | accept () |
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 Streambuf * | rdbuf () |
Return a pointer to the Socketbuf associated with the stream. | |
virtual Streambuf * | rdbuf (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 &) | |
IPv4Socket & | operator= (const IPv4Socket &) |
Private Attributes | |
char * | m_path |
Path of UNIX domain socket. | |
Streambuf * | m_rdbuf |
Socketbuf. |
Definition at line 25 of file IPv4Socket.h.
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.
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] |
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.
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().
my_address_ | address to bind to |
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.
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.
address_ | peer address to connect with |
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).
domain_ | domain |
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; }
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).
Reimplemented from ASSA::Socket.
Definition at line 26 of file IPv4Socket.cpp.
References m_rdbuf, ASSA::SOCKTRACE, and trace_with_mask.
int IPv4Socket::read | ( | char * | buf_, |
const unsigned int | size_ | ||
) | [virtual] |
Read packet of specified size and save it to the given buffer.
buf_ | buffer where packet will be stored |
size_ | size of the packet to expect |
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.
buf_ | buffer to send |
size_ | packet size |
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; }
char* ASSA::IPv4Socket::m_path [private] |
Streambuf* ASSA::IPv4Socket::m_rdbuf [private] |
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.