libassa  3.5.1
Socketbuf.cpp
Go to the documentation of this file.
1 // -*- c++ -*-
2 //------------------------------------------------------------------------------
3 // Socketbuf.cpp
4 //------------------------------------------------------------------------------
5 // Copyright (C) 1997-2002,2005 Vladislav Grinchenko
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //------------------------------------------------------------------------------
12 // Created: 12/03/99
13 //------------------------------------------------------------------------------
14 
15 // win32
16 #include <iostream>
17 
18 #include "assa/Socket.h"
19 #include "assa/Socketbuf.h"
20 #include "assa/MemDump.h"
21 
22 using namespace ASSA;
23 
25 Socketbuf (Socket* s_)
26  : m_s (s_)
27 {
28  trace_with_mask("Socketbuf::Socketbuf",STRMBUFTRACE);
29  // By default, I am doing buffering IO
30  unbuffered (0);
31 }
32 
33 int
35 sync ()
36 {
37  trace_with_mask("Socketbuf::sync",STRMBUFTRACE);
38  return flush_output ();
39 }
40 
41 int
43 showmanyc ()
44 {
45  trace_with_mask("Socketbuf::showmanyc",STRMBUFTRACE);
46  return m_s->getBytesAvail ();
47 }
48 
49 void
51 xput_char (char c_)
52 {
53  trace_with_mask("Socketbuf::xput_char",STRMBUFTRACE);
54  *pptr() = c_;
55  pbump (1);
56 }
57 
59 ~Socketbuf ()
60 {
61  trace_with_mask("Socketbuf::~Socketbuf",STRMBUFTRACE);
62  overflow (EOF); // flush put area
63 }
64 
65 int
67 sys_read (char* b_, int len_)
68 {
69  trace_with_mask("Socketbuf::sys_read",STRMBUFTRACE);
70 
71  int ret = ::recv (m_s->getHandler (), b_, len_, 0);
72 
73  DL((STRMBUFTRACE,"Tried to read %d bytes from fd=%d\n",
74  len_, m_s->getHandler ()));
75  DL((STRMBUFTRACE,"::recv() returned %d\n", ret));
76 
77  if (ret == -1) {
78  DL((STRMBUFTRACE,"::recv() error: %d (%s)\n",
79  errno, strerror (get_errno ())));
80  }
81  return (ret);
82 }
83 
84 int
86 sys_write (char* b_, int len_)
87 {
88  trace_with_mask("Socketbuf::sys_write",STRMBUFTRACE);
89 
90  int ret = ::send (m_s->getHandler (), b_, len_, 0);
91 
92  DL((STRMBUFTRACE,"Tried to write %d bytes to fd=%d\n",
93  len_, m_s->getHandler ()));
94  DL((STRMBUFTRACE,"::send() returned %d\n", ret));
95 
96  if (ret == -1) {
97  DL((STRMBUFTRACE,"::send() error: %d\n",errno));
98  }
99 
100  return (ret);
101 }
102 
103 int
105 underflow ()
106 {
107  /*
108  The important thing to note is that this function
109  returns:
110  a) pointer to the first character in buffer available.
111  b) EOF if sys_read () failed.
112 
113  In case of peer closing its connection, a) will be true.
114  Caller can always find out number of bytes in buffer
115  and determine if peer indeed closed connection.
116  */
117  trace_with_mask("Socketbuf::underflow",STRMBUFTRACE);
118 
119  if (gptr () < egptr ()) // The get area is not empty,
120  {
121  return *(unsigned char*) gptr (); // return 1st character
122  }
123 
124  if (base () == 0 && // If buffer isn't established,
125  doallocate () == EOF) // allocate buffer (both buff & unbuff IO)
126  {
127  return EOF;
128  }
129 
130  int bufsz = unbuffered () ? 1 : MAXTCPFRAMESZ;
131 
132  /*
133  Read as much as I can up to the allocated buffer size.
134  EOF = (-1).
135  */
136  int rval = sys_read (base (), bufsz);
137 
138  DL((STRMBUF,"Socketbuf::sys_read() returned %d bytes\n", rval));
139 
140  if (rval == EOF)
141  {
142  if (get_errno () != EWOULDBLOCK) {
143  m_flags |= EOF_SEEN;
144  }
145  return EOF;
146  }
147 
148  DL((STRMBUF,"Having read %d bytes from socket\n",rval));
149  MemDump::dump_to_log (STRMBUF, "Data received:", base (), rval);
150 
151  // Set get area pointers according to the data just read
152 
153  setg (base (), base (), base () + rval);
154 
155  dump ();
156 
157  return (*(unsigned char*) gptr ()); // Return front character
158 }
159 
160 int
162 overflow (int c_)
163 {
164  trace_with_mask("Socketbuf::overflow",STRMBUFTRACE);
165 
166  // If c == EOF, return flush_output()
167  // Otherwise, insert c into the buffer
168 
169  if (c_ == EOF)
170  return flush_output ();
171 
172  if (pbase () == 0 && doallocate () == EOF)
173  return EOF;
174 
175  if (pptr () >= epptr() && flush_output () == EOF)
176  return EOF;
177 
178  xput_char (c_);
179 
180  dump ();
181 
182  if ((unbuffered () || pptr () >= epptr ()) && flush_output () == EOF)
183  return EOF;
184 
185  dump ();
186 
187  return c_;
188 }
189 
190 int
192 flush_output ()
193 {
194  trace_with_mask("Socketbuf::flush_output",STRMBUFTRACE);
195 
196  if (pptr () <= pbase ()) { // Nothing to flush
197  return 0;
198  }
199 
200  int requested;
201  int xmitted;
202 
203  requested = pptr () - pbase ();
204 
205  if ((xmitted = sys_write (pbase (), requested)) < 0) {
206  return EOF;
207  }
208 
209  if (unbuffered ()) {
210  setp (pbase (), epptr ());
211  return 0;
212  }
213 
214  requested -= xmitted;
215  setp (pbase (), pbase () + MAXTCPFRAMESZ);
216  pbump (requested);
217 
218  if (requested > 0) {
219  ::memmove (pbase (), pbase () + xmitted, requested);
220  }
221 
222  return 0;
223 }
224 
225 int
227 {
228  trace_with_mask("Socketbuf::doallocate",STRMBUFTRACE);
229 
230  // Get area comes first and matches entier buffer area.
231  // Put area comes right after it. They are two equally-sized
232  // separate buffers.
233  //
234  // ------------ -
235  // | | ^
236  // | get area | | buffer area
237  // | | v
238  // ------------ -
239  // | put area |
240  // | |
241  // ------------
242  //
243  // Return 1 on allocation and 0 if there is no need
244 
245  if (m_buf_base)
246  return 0;
247 
248  if ( ! (m_flags & UNBUFFERED) ) {
249  DL((STRMBUF,"Buffered IO - allocating %d bytes\n",
250  2 * MAXTCPFRAMESZ));
251  char* buf = new char [2 * MAXTCPFRAMESZ];
252 
253  setg (buf, buf + MAXTCPFRAMESZ, buf + MAXTCPFRAMESZ);
254  setb (buf, buf + MAXTCPFRAMESZ, 1);
255 
256  buf += MAXTCPFRAMESZ;
257  setp (buf, buf+MAXTCPFRAMESZ);
258  }
259  else {
260  DL((STRMBUF,"Unbuffered IO - same 1 byte array\n"));
261  setb (m_shortbuf, m_shortbuf+1, 0);
262 
263  // read_base is pointing to the begining, and
264  // read_end to one past end of the buffer.
265  // Because buffer is empty, read_ptr should point
266  // to the end (same as read_end). This way, calling
267  // routines will detect that get area needs data from sync.
268  //
269  // +- read_base +- read_ptr
270  // | |- read_end
271  // | |+----- one past end-of-block
272  // v vv
273  // +--------------+-+
274  // | get area | |
275  // +--------------+-+
277 
278  // write_base & write_ptr are pointing to the begining,
279  // and write_end to one past end of the buffer.
280  // Because buffer is empty, read_ptr should point
281  // to the beginning (same as write_base). This way, calling
282  // routines will detect that put area needs data from sync.
283  //
284  // +- write_base +- write_end points one past
285  // |- write_ptr | end-of-block
286  // v v
287  // +--------------+-+
288  // | put area | |
289  // +--------------+-+
290 
292  }
293  dump ();
294  return 1;
295 }
296 
297 
#define DL(X)
A macro for writing debug message to the Logger.
Definition: Logger.h:273
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition: Logger.h:437
A Hex/Ascii memory dump of similar to od(1) UNIX utility.
Abstraction of socket data type.
Socketbuf class is derived from Streambuf to provide I/O with the socket file descriptor.
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
virtual handler_t getHandler() const =0
Get file descriptor.
int getBytesAvail(void) const
Return number of bytes available in socket receive buffer.
Definition: Socket.cpp:48
virtual ~Socketbuf()
Definition: Socketbuf.cpp:59
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
Socket * m_s
Reference to the Socket stream.
Definition: Socketbuf.h:51
virtual int showmanyc()
The morphemes of showmanyc are "es-how-many-see", not "show-man-ic".
Definition: Socketbuf.cpp:43
int sys_read(char *b_, int len_)
Definition: Socketbuf.cpp:67
virtual int doallocate()
This function is called by allocate when unbuffered() is zero and base() is zero.
Definition: Socketbuf.cpp:226
int sys_write(char *b_, int len_)
Definition: Socketbuf.cpp:86
Socketbuf(Socket *s_)
Definition: Socketbuf.cpp:25
void xput_char(char c_)
Definition: Socketbuf.cpp:51
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
virtual int sync()
This function synchronizes the streambuf with its actual stream of characters.
Definition: Socketbuf.cpp:35
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
char * base() const
Returns the lowest possible value for gptr() - the beginning of the get area.
Definition: Streambuf.h:464
void setp(char *pbeg_, char *pend_)
Set put area pointers.
Definition: Streambuf.h:588
char * epptr() const
Returns a pointer just past the end of the put area, the maximum possible value for pptr().
Definition: Streambuf.h:507
int unbuffered()
Definition: Streambuf.h:408
char * egptr() const
Returns a pointer just past the end of the get area, the maximum possible value for gptr().
Definition: Streambuf.h:482
static const int MAXTCPFRAMESZ
Size of the internal input/output buffer.
Definition: Streambuf.h:106
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
void setb(char *b_, char *eb_, int del_)
Establish the reserve area (buffer).
Definition: Streambuf.cpp:80
void pbump(int n_)
Advances the next pointer for the output sequence by n_.
Definition: Streambuf.h:515
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
void setg(char *gbeg_, char *gnext_, char *gend_)
Set get area pointers.
Definition: Streambuf.cpp:69
char m_shortbuf[1]
Definition: Streambuf.h:47
char * m_buf_base
Definition: Streambuf.h:41
void dump() const
Definition: Streambuf.cpp:23
Definition: Acceptor.h:40
@ STRMBUFTRACE
Extended Streambuf & friends messages
Definition: LogMask.h:46
@ STRMBUF
Class Streambuf & friends messages
Definition: LogMask.h:45
int get_errno()
Fetch error number in a portable way.
Definition: Logger_Impl.h:115