libassa
3.5.1
Main Page
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
assa
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
24
Socketbuf::
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
34
Socketbuf::
35
sync
()
36
{
37
trace_with_mask
(
"Socketbuf::sync"
,
STRMBUFTRACE
);
38
return
flush_output
();
39
}
40
41
int
42
Socketbuf::
43
showmanyc
()
44
{
45
trace_with_mask
(
"Socketbuf::showmanyc"
,
STRMBUFTRACE
);
46
return
m_s
->
getBytesAvail
();
47
}
48
49
void
50
Socketbuf::
51
xput_char
(
char
c_)
52
{
53
trace_with_mask
(
"Socketbuf::xput_char"
,
STRMBUFTRACE
);
54
*
pptr
() = c_;
55
pbump
(1);
56
}
57
58
Socketbuf::
59
~Socketbuf
()
60
{
61
trace_with_mask
(
"Socketbuf::~Socketbuf"
,
STRMBUFTRACE
);
62
overflow
(EOF);
// flush put area
63
}
64
65
int
66
Socketbuf::
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
85
Socketbuf::
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
104
Socketbuf::
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
161
Socketbuf::
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
191
Socketbuf::
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
226
Socketbuf::doallocate
()
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
// +--------------+-+
276
setg
(
m_shortbuf
,
m_shortbuf
+1,
m_shortbuf
+1);
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
291
setp
(
m_shortbuf
,
m_shortbuf
+1);
292
}
293
dump
();
294
return
1;
295
}
296
297
Generated on Tue Jun 19 2012 08:07:24 for libassa by
1.8.1.1