Switch to unified view

a b/src/bincimapmime/iodevice.cc
1
/*-*-mode:c++-*-*/
2
/*  --------------------------------------------------------------------
3
 *  Filename:
4
 *    src/iodevice.cc
5
 *  
6
 *  Description:
7
 *    Implementation of the IODevice class.
8
 *  --------------------------------------------------------------------
9
 *  Copyright 2002, 2003 Andreas Aardal Hanssen
10
 *
11
 *  This program is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  This program is distributed in the hope that it will be useful,
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 *  GNU General Public License for more details.
20
 *
21
 *  You should have received a copy of the GNU General Public License
22
 *  along with this program; if not, write to the Free Software
23
 *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
24
 *  --------------------------------------------------------------------
25
 */
26
#include "iodevice.h"
27
#include "convert.h" // BincStream
28
#include "session.h" // getEnv/hasEnv
29
30
#include <stdlib.h>
31
#include <unistd.h>
32
33
using namespace ::std;
34
using namespace ::Binc;
35
36
//------------------------------------------------------------------------
37
IODevice::IODevice(int f) : flags(f | IsEnabled),
38
                maxInputBufferSize(0),
39
                maxOutputBufferSize(0),
40
                timeout(0), 
41
                readCount(0), writeCount(0),
42
                outputLevel(0), outputLevelLimit(0),
43
                error(Unknown), errorString("Unknown error"),
44
                dumpfd(0)
45
{
46
}
47
48
//------------------------------------------------------------------------
49
IODevice::~IODevice(void)
50
{
51
}
52
53
//------------------------------------------------------------------------
54
IODevice &IODevice::operator <<(ostream &(*source)(ostream &))
55
{
56
  if (!(flags & IsEnabled) || outputLevel > outputLevelLimit)
57
    return *this;
58
59
  static std::ostream &(*endl_funcptr)(ostream &) = endl;
60
  
61
  if (source != endl_funcptr)
62
    return *this;
63
64
  outputBuffer << "\r\n";
65
66
  if (dumpfd)
67
    ::write(dumpfd, "\r\n", 2);
68
69
  if (flags & FlushesOnEndl)
70
    flush();
71
  else if (flags & HasOutputLimit)
72
    if (outputBuffer.getSize() > maxOutputBufferSize)
73
      flush();
74
75
  return *this;
76
}
77
78
//------------------------------------------------------------------------
79
bool IODevice::canRead(void) const
80
{
81
  return false;
82
}
83
84
//------------------------------------------------------------------------
85
void IODevice::clear()
86
{
87
  if (!(flags & IsEnabled))
88
    return;
89
90
  inputBuffer.clear();
91
  outputBuffer.clear();
92
}
93
94
//------------------------------------------------------------------------
95
bool IODevice::flush()
96
{
97
  if (!(flags & IsEnabled))
98
    return true;
99
100
  WriteResult writeResult = WriteWait;
101
  do {
102
    unsigned int s = outputBuffer.getSize();
103
    if (s == 0)
104
      break;
105
106
    if (!waitForWrite())
107
      return false;
108
    
109
    writeResult = write();
110
    if (writeResult == WriteError)
111
      return false;
112
113
    writeCount += s - outputBuffer.getSize();
114
  } while (outputBuffer.getSize() > 0 && writeResult == WriteWait);
115
116
  outputBuffer.clear();
117
  return true;
118
}
119
120
//------------------------------------------------------------------------
121
void IODevice::setFlags(unsigned int f)
122
{
123
  flags |= f;
124
}
125
126
//------------------------------------------------------------------------
127
void IODevice::clearFlags(unsigned int f)
128
{
129
  flags &= ~f;
130
}
131
132
//------------------------------------------------------------------------
133
void IODevice::setMaxInputBufferSize(unsigned int max)
134
{
135
  maxInputBufferSize = max;
136
}
137
138
//------------------------------------------------------------------------
139
void IODevice::setMaxOutputBufferSize(unsigned int max)
140
{
141
  maxOutputBufferSize = max;
142
}
143
144
//------------------------------------------------------------------------
145
void IODevice::setTimeout(unsigned int t)
146
{
147
  timeout = t;
148
149
  if (t)
150
    flags |= HasTimeout;
151
  else
152
    flags &= ~HasTimeout;
153
}
154
155
//------------------------------------------------------------------------
156
unsigned int IODevice::getTimeout(void) const
157
{
158
  return timeout;
159
}
160
161
//------------------------------------------------------------------------
162
void IODevice::setOutputLevel(unsigned int level)
163
{
164
  outputLevel = level;
165
}
166
167
//------------------------------------------------------------------------
168
unsigned int IODevice::getOutputLevel(void) const
169
{
170
  return outputLevel;
171
}
172
173
//------------------------------------------------------------------------
174
void IODevice::setOutputLevelLimit(unsigned int level)
175
{
176
  outputLevelLimit = level;
177
}
178
179
//------------------------------------------------------------------------
180
unsigned int IODevice::getOutputLevelLimit(void) const
181
{
182
  return outputLevelLimit;
183
}
184
185
//------------------------------------------------------------------------
186
bool IODevice::readStr(string *dest, unsigned int max)
187
{
188
  // If max is 0, fill the input buffer once only if it's empty.
189
  if (!max && inputBuffer.getSize() == 0 && !fillInputBuffer())
190
    return false;
191
192
  // If max is != 0, wait until we have max.
193
  while (max && inputBuffer.getSize() < max) {
194
      if (!fillInputBuffer())
195
    return false;
196
  }
197
198
  unsigned int bytesToRead = max ? max : inputBuffer.getSize();
199
  *dest += inputBuffer.str().substr(0, bytesToRead);
200
  if (dumpfd) {
201
      ::write(dumpfd, inputBuffer.str().substr(0, bytesToRead).c_str(), 
202
        bytesToRead);
203
  }
204
  
205
  inputBuffer.popString(bytesToRead);
206
  readCount += bytesToRead;
207
  return true;
208
}
209
210
//------------------------------------------------------------------------
211
bool IODevice::readChar(char *dest)
212
{
213
  if (inputBuffer.getSize() == 0 && !fillInputBuffer())
214
    return false;
215
216
  char c = inputBuffer.popChar();
217
  if (dest)
218
    *dest = c;
219
  if (dumpfd)
220
    ::write(dumpfd, &c, 1);
221
222
  ++readCount;
223
  return true;
224
}
225
226
//------------------------------------------------------------------------
227
void IODevice::unreadChar(char c)
228
{
229
  inputBuffer.unpopChar(c);
230
}
231
232
//------------------------------------------------------------------------
233
void IODevice::unreadStr(const string &s)
234
{
235
  inputBuffer.unpopStr(s);
236
}
237
238
//------------------------------------------------------------------------
239
bool IODevice::skipTo(char c)
240
{
241
  char dest = '\0';
242
  do {
243
    if (!readChar(&dest))
244
      return false;
245
    if (dumpfd)
246
      ::write(dumpfd, &dest, 1);
247
  } while (c != dest);
248
249
  return true;
250
}
251
252
//------------------------------------------------------------------------
253
string IODevice::service(void) const
254
{
255
  return "nul";
256
}
257
258
//------------------------------------------------------------------------
259
bool IODevice::waitForWrite(void) const
260
{
261
  return false;
262
}
263
264
//------------------------------------------------------------------------
265
bool IODevice::waitForRead(void) const
266
{
267
  return false;
268
}
269
270
//------------------------------------------------------------------------
271
IODevice::WriteResult IODevice::write(void)
272
{
273
  return WriteError;
274
}
275
276
//------------------------------------------------------------------------
277
bool IODevice::fillInputBuffer(void)
278
{
279
  return false;
280
}
281
282
//------------------------------------------------------------------------
283
IODevice::Error IODevice::getLastError(void) const
284
{
285
  return error;
286
}
287
288
//------------------------------------------------------------------------
289
string IODevice::getLastErrorString(void) const
290
{
291
  return errorString;
292
}
293
294
//------------------------------------------------------------------------
295
unsigned int IODevice::getReadCount(void) const
296
{
297
  return readCount;
298
}
299
300
//------------------------------------------------------------------------
301
unsigned int IODevice::getWriteCount(void) const
302
{
303
  return writeCount;
304
}
305
306
//------------------------------------------------------------------------
307
void IODevice::enableProtocolDumping(void)
308
{
309
  BincStream ss;
310
  ss << "/tmp/bincimap-dump-" << (int) time(0) << "-" 
311
     << Session::getInstance().getIP() << "-XXXXXX";
312
  char *safename = strdup(ss.str().c_str());
313
  dumpfd = mkstemp(safename);
314
  if (dumpfd == -1)
315
    dumpfd = 0;
316
  delete safename;
317
}