Loading...
Searching...
No Matches
Socketbuf.cpp
Go to the documentation of this file.
// -*- c++ -*-
//------------------------------------------------------------------------------
// Socketbuf.cpp
//------------------------------------------------------------------------------
// Copyright (C) 1997-2002,2005 Vladislav Grinchenko
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//------------------------------------------------------------------------------
// Created: 12/03/99
//------------------------------------------------------------------------------
// win32
#include <iostream>
#include "assa/Socket.h"
#include "assa/Socketbuf.h"
#include "assa/MemDump.h"
using namespace ASSA;
Socketbuf::
Socketbuf (Socket* s_)
: m_s (s_)
{
trace_with_mask("Socketbuf::Socketbuf",STRMBUFTRACE);
// By default, I am doing buffering IO
unbuffered (0);
}
int
Socketbuf::
sync ()
{
trace_with_mask("Socketbuf::sync",STRMBUFTRACE);
return flush_output ();
}
int
Socketbuf::
showmanyc ()
{
trace_with_mask("Socketbuf::showmanyc",STRMBUFTRACE);
return m_s->getBytesAvail ();
}
void
Socketbuf::
xput_char (char c_)
{
trace_with_mask("Socketbuf::xput_char",STRMBUFTRACE);
*pptr() = c_;
pbump (1);
}
Socketbuf::
~Socketbuf ()
{
trace_with_mask("Socketbuf::~Socketbuf",STRMBUFTRACE);
overflow (EOF); // flush put area
}
int
Socketbuf::
sys_read (char* b_, int len_)
{
trace_with_mask("Socketbuf::sys_read",STRMBUFTRACE);
int ret = ::recv (m_s->getHandler (), b_, len_, 0);
DL((STRMBUFTRACE,"Tried to read %d bytes from fd=%d\n",
len_, m_s->getHandler ()));
DL((STRMBUFTRACE,"::recv() returned %d\n", ret));
if (ret == -1) {
DL((STRMBUFTRACE,"::recv() error: %d (%s)\n",
errno, strerror (get_errno ())));
}
return (ret);
}
int
Socketbuf::
sys_write (char* b_, int len_)
{
trace_with_mask("Socketbuf::sys_write",STRMBUFTRACE);
int ret = ::send (m_s->getHandler (), b_, len_, 0);
DL((STRMBUFTRACE,"Tried to write %d bytes to fd=%d\n",
len_, m_s->getHandler ()));
DL((STRMBUFTRACE,"::send() returned %d\n", ret));
if (ret == -1) {
DL((STRMBUFTRACE,"::send() error: %d\n",errno));
}
return (ret);
}
int
Socketbuf::
underflow ()
{
/*
The important thing to note is that this function
returns:
a) pointer to the first character in buffer available.
b) EOF if sys_read () failed.
In case of peer closing its connection, a) will be true.
Caller can always find out number of bytes in buffer
and determine if peer indeed closed connection.
*/
trace_with_mask("Socketbuf::underflow",STRMBUFTRACE);
if (gptr () < egptr ()) // The get area is not empty,
{
return *(unsigned char*) gptr (); // return 1st character
}
if (base () == 0 && // If buffer isn't established,
doallocate () == EOF) // allocate buffer (both buff & unbuff IO)
{
return EOF;
}
int bufsz = unbuffered () ? 1 : MAXTCPFRAMESZ;
/*
Read as much as I can up to the allocated buffer size.
EOF = (-1).
*/
int rval = sys_read (base (), bufsz);
DL((STRMBUF,"Socketbuf::sys_read() returned %d bytes\n", rval));
if (rval == EOF)
{
if (get_errno () != EWOULDBLOCK) {
m_flags |= EOF_SEEN;
}
return EOF;
}
DL((STRMBUF,"Having read %d bytes from socket\n",rval));
MemDump::dump_to_log (STRMBUF, "Data received:", base (), rval);
// Set get area pointers according to the data just read
setg (base (), base (), base () + rval);
dump ();
return (*(unsigned char*) gptr ()); // Return front character
}
int
Socketbuf::
overflow (int c_)
{
trace_with_mask("Socketbuf::overflow",STRMBUFTRACE);
// If c == EOF, return flush_output()
// Otherwise, insert c into the buffer
if (c_ == EOF)
return flush_output ();
if (pbase () == 0 && doallocate () == EOF)
return EOF;
if (pptr () >= epptr() && flush_output () == EOF)
return EOF;
xput_char (c_);
dump ();
if ((unbuffered () || pptr () >= epptr ()) && flush_output () == EOF)
return EOF;
dump ();
return c_;
}
int
Socketbuf::
flush_output ()
{
trace_with_mask("Socketbuf::flush_output",STRMBUFTRACE);
if (pptr () <= pbase ()) { // Nothing to flush
return 0;
}
int requested;
int xmitted;
requested = pptr () - pbase ();
if ((xmitted = sys_write (pbase (), requested)) < 0) {
return EOF;
}
if (unbuffered ()) {
setp (pbase (), epptr ());
return 0;
}
requested -= xmitted;
setp (pbase (), pbase () + MAXTCPFRAMESZ);
pbump (requested);
if (requested > 0) {
::memmove (pbase (), pbase () + xmitted, requested);
}
return 0;
}
int
Socketbuf::doallocate ()
{
trace_with_mask("Socketbuf::doallocate",STRMBUFTRACE);
// Get area comes first and matches entier buffer area.
// Put area comes right after it. They are two equally-sized
// separate buffers.
//
// ------------ -
// | | ^
// | get area | | buffer area
// | | v
// ------------ -
// | put area |
// | |
// ------------
//
// Return 1 on allocation and 0 if there is no need
if (m_buf_base)
return 0;
if ( ! (m_flags & UNBUFFERED) ) {
DL((STRMBUF,"Buffered IO - allocating %d bytes\n",
2 * MAXTCPFRAMESZ));
char* buf = new char [2 * MAXTCPFRAMESZ];
setg (buf, buf + MAXTCPFRAMESZ, buf + MAXTCPFRAMESZ);
setb (buf, buf + MAXTCPFRAMESZ, 1);
buf += MAXTCPFRAMESZ;
setp (buf, buf+MAXTCPFRAMESZ);
}
else {
DL((STRMBUF,"Unbuffered IO - same 1 byte array\n"));
setb (m_shortbuf, m_shortbuf+1, 0);
// read_base is pointing to the begining, and
// read_end to one past end of the buffer.
// Because buffer is empty, read_ptr should point
// to the end (same as read_end). This way, calling
// routines will detect that get area needs data from sync.
//
// +- read_base +- read_ptr
// | |- read_end
// | |+----- one past end-of-block
// v vv
// +--------------+-+
// | get area | |
// +--------------+-+
setg (m_shortbuf, m_shortbuf+1, m_shortbuf+1);
// write_base & write_ptr are pointing to the begining,
// and write_end to one past end of the buffer.
// Because buffer is empty, read_ptr should point
// to the beginning (same as write_base). This way, calling
// routines will detect that put area needs data from sync.
//
// +- write_base +- write_end points one past
// |- write_ptr | end-of-block
// v v
// +--------------+-+
// | put area | |
// +--------------+-+
setp (m_shortbuf, m_shortbuf+1);
}
dump ();
return 1;
}
DL
#define DL(X)
A macro for writing debug message to the Logger.
Definition Logger.h:273
trace_with_mask
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition Logger.h:437
MemDump.h
A Hex/Ascii memory dump of similar to od(1) UNIX utility.
Socket.h
Abstraction of socket data type.
Socketbuf.h
Socketbuf class is derived from Streambuf to provide I/O with the socket file descriptor.
ASSA::MemDump::dump_to_log
static void dump_to_log(unsigned long mask_, const char *info_, const char *msg_, int len_)
Write hex/ascii dump of a memory region to log file.
Definition MemDump.cpp:111
ASSA::Socket
Definition Socket.h:71
ASSA::Socketbuf::flush_output
int flush_output()
Definition Socketbuf.cpp:192
ASSA::Socketbuf::~Socketbuf
virtual ~Socketbuf()
Definition Socketbuf.cpp:59
ASSA::Socketbuf::overflow
virtual int overflow(int c_=EOF)
This function is called to consume characters (flush them to output), typically when the put area is ...
Definition Socketbuf.cpp:162
ASSA::Socketbuf::m_s
Socket * m_s
Reference to the Socket stream.
Definition Socketbuf.h:51
ASSA::Socketbuf::showmanyc
virtual int showmanyc()
Definition Socketbuf.cpp:43
ASSA::Socketbuf::sys_read
int sys_read(char *b_, int len_)
Definition Socketbuf.cpp:67
ASSA::Socketbuf::doallocate
virtual int doallocate()
This function is called by allocate when unbuffered() is zero and base() is zero.
Definition Socketbuf.cpp:226
ASSA::Socketbuf::sys_write
int sys_write(char *b_, int len_)
Definition Socketbuf.cpp:86
ASSA::Socketbuf::Socketbuf
Socketbuf(Socket *s_)
Definition Socketbuf.cpp:25
ASSA::Socketbuf::xput_char
void xput_char(char c_)
Definition Socketbuf.cpp:51
ASSA::Socketbuf::underflow
virtual int underflow()
This function is called to supply characters for input (from some source) when the get area is empty,...
Definition Socketbuf.cpp:105
ASSA::Socketbuf::sync
virtual int sync()
This function synchronizes the streambuf with its actual stream of characters.
Definition Socketbuf.cpp:35
ASSA::Streambuf::pptr
char * pptr() const
Returns a pointer to the beginning of the put area, and thus to the location of the next character th...
Definition Streambuf.h:499
ASSA::Streambuf::base
char * base() const
Returns the lowest possible value for gptr() - the beginning of the get area.
Definition Streambuf.h:464
ASSA::Streambuf::setp
void setp(char *pbeg_, char *pend_)
Set put area pointers.
Definition Streambuf.h:588
ASSA::Streambuf::epptr
char * epptr() const
Returns a pointer just past the end of the put area, the maximum possible value for pptr().
Definition Streambuf.h:507
ASSA::Streambuf::unbuffered
int unbuffered()
Definition Streambuf.h:408
ASSA::Streambuf::egptr
char * egptr() const
Returns a pointer just past the end of the get area, the maximum possible value for gptr().
Definition Streambuf.h:482
ASSA::Streambuf::MAXTCPFRAMESZ
static const int MAXTCPFRAMESZ
Size of the internal input/output buffer.
Definition Streambuf.h:106
ASSA::Streambuf::pbase
char * pbase() const
Returns a pointer to the beginning fo the space available for the put area, the lowest possible value...
Definition Streambuf.h:491
ASSA::Streambuf::setb
void setb(char *b_, char *eb_, int del_)
Establish the reserve area (buffer).
Definition Streambuf.cpp:80
ASSA::Streambuf::pbump
void pbump(int n_)
Advances the next pointer for the output sequence by n_.
Definition Streambuf.h:515
ASSA::Streambuf::unbuffered
void unbuffered(int i_)
If i_ is non-zero, then all IO operations are buffered.
Definition Streambuf.h:417
ASSA::Streambuf::gptr
char * gptr() const
Returns a pointer to the beginning of the get area, and thus to the next character to be fetched (if ...
Definition Streambuf.h:473
ASSA::Streambuf::setg
void setg(char *gbeg_, char *gnext_, char *gend_)
Set get area pointers.
Definition Streambuf.cpp:69
ASSA::io_ptrs::m_shortbuf
char m_shortbuf[1]
Definition Streambuf.h:47
ASSA::io_ptrs::m_buf_base
char * m_buf_base
Definition Streambuf.h:41
ASSA::io_ptrs::UNBUFFERED
@ UNBUFFERED
Definition Streambuf.h:44
ASSA::io_ptrs::EOF_SEEN
@ EOF_SEEN
Definition Streambuf.h:44
ASSA::io_ptrs::dump
void dump() const
Definition Streambuf.cpp:23
ASSA::io_ptrs::m_flags
int m_flags
Definition Streambuf.h:46
ASSA
Definition Acceptor.h:40
ASSA::STRMBUFTRACE
@ STRMBUFTRACE
Extended Streambuf & friends messages.
Definition LogMask.h:46
ASSA::STRMBUF
@ STRMBUF
Class Streambuf & friends messages.
Definition LogMask.h:45
ASSA::get_errno
int get_errno()
Fetch error number in a portable way.
Definition Logger_Impl.h:115