|
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.
1.7.3