]> err.no Git - sope/blob - sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c
milli => micro
[sope] / sope-appserver / mod_ngobjweb / NGBufferedDescriptor.c
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include "NGBufferedDescriptor.h"
27
28 // returns the number of bytes which where read from the buffer
29 #define numberOfConsumedReadBufferBytes(self) \
30   ((self->readBufferSize == 0) ? 0 : (self->readBufferPos - self->readBuffer))
31
32 // returns the number of bytes which can be read from buffer (without source access)
33 #define numberOfAvailableReadBufferBytes(self) \
34   (self->readBufferFillSize - numberOfConsumedReadBufferBytes(self))
35
36 // look whether all bytes in the buffer where consumed, if so, reset the buffer
37 #define checkReadBufferFillState(self) \
38   if (numberOfAvailableReadBufferBytes(self) == 0) { \
39     self->readBufferPos = self->readBuffer; \
40     self->readBufferFillSize = 0;  \
41   }
42
43 // implementation
44
45 NGBufferedDescriptor *
46 NGBufferedDescriptor_newWithDescriptorAndSize(int _fd, int _size)
47 {
48   NGBufferedDescriptor *self = malloc(sizeof(NGBufferedDescriptor));
49   if (self) {
50     self->fd                  = _fd;
51     self->readBuffer          = malloc(_size);
52     self->writeBuffer         = malloc(_size);
53     self->readBufferPos       = self->readBuffer;
54     self->readBufferSize      = _size;
55     self->readBufferFillSize  = 0; // no bytes are read from source
56     self->writeBufferFillSize = 0;
57     self->writeBufferSize     = _size;
58     self->ownsFd              = 0;
59   }
60   return self;
61 }
62
63 NGBufferedDescriptor *NGBufferedDescriptor_newWithDescriptor(int _fd) {
64   return NGBufferedDescriptor_newWithDescriptorAndSize(_fd, 1024);
65 }
66 NGBufferedDescriptor *
67 NGBufferedDescriptor_newWithOwnedDescriptorAndSize(int _fd, int _size) {
68   NGBufferedDescriptor *self = NULL;
69   
70   if ((self = NGBufferedDescriptor_newWithDescriptorAndSize(_fd, _size)))
71     self->ownsFd = 1;
72   else
73     close(_fd);
74   return self;
75 }
76
77 void NGBufferedDescriptor_free(NGBufferedDescriptor *self) {
78   if (self) {
79     NGBufferedDescriptor_flush(self);
80
81     if (self->ownsFd && self->fd != -1) {
82       close(self->fd);
83       self->fd = -1;
84     }
85
86     if (self->readBuffer) {
87       free(self->readBuffer);
88       self->readBuffer    = NULL;
89       self->readBufferPos = NULL;
90     }
91     self->readBufferFillSize = 0;
92     self->readBufferSize     = 0;
93
94     if (self->writeBuffer) {
95       free(self->writeBuffer);
96       self->writeBuffer = NULL;
97     }
98     self->writeBufferFillSize = 0;
99     self->writeBufferSize     = 0;
100     
101     free(self);
102   }
103 }
104
105 int NGBufferedDescriptor_getReadBufferSize(NGBufferedDescriptor *self) {
106   if (self == NULL) return 0;
107   return self->readBufferSize;
108 }
109 int NGBufferedDescriptor_getWriteBufferSize(NGBufferedDescriptor *self) {
110   if (self == NULL) return 0;
111   return self->writeBufferSize;
112 }
113
114 int NGBufferedDescriptor_read(NGBufferedDescriptor *self,
115                                    void *_buf, int _len) {
116   register int availBytes = numberOfAvailableReadBufferBytes(self);
117
118   if (self == NULL) return 0;
119   
120   if (self->readBufferSize == 0) { // no read buffering is done (buffersize==0)
121     return read(self->fd, _buf, _len);
122   }
123     
124   if (availBytes >= _len) {
125     // there are enough bytes in the buffer to fulfill the request
126     if (_len == 1) {
127       *(unsigned char *)_buf = *(unsigned char *)self->readBufferPos;
128       self->readBufferPos++;
129     }
130     else {
131       memcpy(_buf, self->readBufferPos, _len);
132       self->readBufferPos += _len;          // update read position (consumed-size)
133     }
134     checkReadBufferFillState(self); // check whether all bytes where consumed
135     return _len;
136   }
137   else if (availBytes > 0) {
138     // there are some bytes in the buffer, these are returned
139     
140     memcpy(_buf, self->readBufferPos, availBytes); // copy all bytes from buffer
141     self->readBufferPos      = self->readBuffer; // reset position
142     self->readBufferFillSize = 0;        // no bytes available in buffer anymore
143     return availBytes;
144   }
145   else if (_len > self->readBufferSize) {
146     // requested _len is bigger than the buffersize, so we can bypass the
147     // buffer (which is empty, as guaranteed by the previous 'ifs'
148     return read(self->fd, _buf, _len);
149   }
150   else {
151     // no bytes are available and the requested _len is smaller than the possible
152     // buffer size, we have to read the next block of input from the source
153
154     self->readBufferFillSize = read(self->fd,
155                                     self->readBuffer, self->readBufferSize);
156
157     // no comes a section which is roughly the same like the first to conditionals
158     // in this method
159     if (self->readBufferFillSize >= _len) {
160       // there are enough bytes in the buffer to fulfill the request
161     
162       memcpy(_buf, self->readBufferPos, _len);
163       self->readBufferPos += _len;          // update read position (consumed-size)
164       checkReadBufferFillState(self); // check whether all bytes where consumed
165       return _len;
166     }
167     else { // (readBufferFillSize > 0) (this is ensured by the above assert)
168       // there are some bytes in the buffer, these are returned
169
170       availBytes = self->readBufferFillSize;
171       memcpy(_buf, self->readBufferPos, self->readBufferFillSize); // copy all bytes from buffer
172       self->readBufferPos      = self->readBuffer; // reset position
173       self->readBufferFillSize = 0;          // no bytes available in buffer anymore
174       return availBytes;
175     }
176   }
177 }
178
179 int NGBufferedDescriptor_write(NGBufferedDescriptor *self,
180                                const void *_buf, int _len)
181 {
182   register int  tmp       = 0;
183   register int  remaining = _len;
184   register void *track    = (void *)_buf;
185
186   if (self == NULL) return 0;
187   
188   while (remaining > 0) {
189     // how much bytes available in buffer ?
190     tmp = self->writeBufferSize - self->writeBufferFillSize; 
191     tmp = (tmp > remaining) ? remaining : tmp;
192   
193     memcpy((self->writeBuffer + self->writeBufferFillSize), track, tmp);
194     track += tmp;
195     remaining -= tmp;
196     self->writeBufferFillSize += tmp;
197
198     if (self->writeBufferFillSize == self->writeBufferSize) {
199       void *pos = self->writeBuffer;
200
201       while (self->writeBufferFillSize > 0) {
202         int result;
203         
204         result = write(self->fd, pos, self->writeBufferFillSize);
205         
206         if ((result == 0) || (result < 0)) { // socket closed || error
207           self->writeBufferFillSize = 0; // content is lost ..
208           return result;
209         }
210         self->writeBufferFillSize -= result;
211         pos += result;
212       }
213     }
214   }
215
216 #if 0
217   if (self->flags._flushOnNewline == 1) {
218     // scan buffer for newlines, if one is found, flush buffer
219     
220     for (tmp = 0; tmp < _len; tmp++) {
221       if (tmp == '\n') {
222         NGBufferedDescriptor_flush(self);
223         break;
224       }
225     }
226   }
227 #endif
228   
229   // clean up for GC
230   tmp       = 0;    
231   track     = NULL; // clean up for GC
232   remaining = 0;
233   
234   return _len;
235 }
236
237 char NGBufferedDescriptor_flush(NGBufferedDescriptor *self) {
238   if (self == NULL) return 0;
239   
240   if (self->writeBufferFillSize > 0) {
241     int  toGo = self->writeBufferFillSize;
242     void *pos = self->writeBuffer;
243
244     while (toGo > 0) {
245       int result = write(self->fd, pos, toGo);
246
247       if (result == 0) // socket was closed
248         return 0;
249       else if (result < 1) // socket error
250         return 0;
251
252       toGo -= result;
253       pos  += result;
254     }
255     self->writeBufferFillSize = 0;
256   }
257   return 1;
258 }
259
260 unsigned char NGBufferedDescriptor_safeRead(NGBufferedDescriptor *self,
261                                             void *_buffer, int _len) {
262   if (self == NULL) return 0;
263   
264   if (_len > 0) {
265     while (_len > 0) {
266       int result = NGBufferedDescriptor_read(self, _buffer, _len);
267
268       if (result == 0) // socket was closed
269         return 0;
270       else if (result < 1) // socket error
271         return 0;
272
273       _len    -= result;
274       _buffer += result;
275     }
276   }
277   return 1;
278 }
279 char NGBufferedDescriptor_safeWrite(NGBufferedDescriptor *self,
280                                     const void *_buffer, int _len) {
281   if (self == NULL) return 0;
282   
283   if (_len > 0) {
284     while (_len > 0) {
285       int result;
286       
287       result = NGBufferedDescriptor_write(self, _buffer, _len);
288       
289       if (result == 0) // socket was closed
290         return 0;
291       else if (result < 1) // socket error
292         return 0;
293
294       _len    -= result;
295       _buffer += result;
296     }
297   }
298   return 1;
299 }
300
301 int NGBufferedDescriptor_readChar(NGBufferedDescriptor *self) {
302   unsigned char c;
303   return (NGBufferedDescriptor_safeRead(self, &c, 1)) ? c : -1;
304 }
305
306 char NGBufferedDescriptor_writeHttpHeader(NGBufferedDescriptor *self,
307                                           const unsigned char *_key,
308                                           const unsigned char *_value)
309 {
310   if (NGBufferedDescriptor_safeWrite(self, _key, strlen(_key))) {
311     if (NGBufferedDescriptor_safeWrite(self, ": ", 2)) {
312       if (NGBufferedDescriptor_safeWrite(self, _value, strlen(_value))) {
313         if (NGBufferedDescriptor_safeWrite(self, "\r\n", 2)) {
314           return 1;
315         }
316       }
317     }
318   }
319   return 0;
320 }