libassa 3.5.1
Loading...
Searching...
No Matches
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
22using namespace ASSA;
23
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
33int
35sync ()
36{
37 trace_with_mask("Socketbuf::sync",STRMBUFTRACE);
38 return flush_output ();
39}
40
41int
43showmanyc ()
44{
45 trace_with_mask("Socketbuf::showmanyc",STRMBUFTRACE);
46 return m_s->getBytesAvail ();
47}
48
49void
51xput_char (char c_)
52{
53 trace_with_mask("Socketbuf::xput_char",STRMBUFTRACE);
54 *pptr() = c_;
55 pbump (1);
56}
57
60{
61 trace_with_mask("Socketbuf::~Socketbuf",STRMBUFTRACE);
62 overflow (EOF); // flush put area
63}
64
65int
67sys_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
84int
86sys_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
103int
105underflow ()
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
160int
162overflow (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
190int
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);
217
218 if (requested > 0) {
219 ::memmove (pbase (), pbase () + xmitted, requested);
220 }
221
222 return 0;
223}
224
225int
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
254 setb (buf, buf + MAXTCPFRAMESZ, 1);
255
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.
A wrapper class to provide AutoPtr with reference semantics.
Definition AutoPtr.h:32
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 ...
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.
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,...
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
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
@ 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.