]> err.no Git - sope/blob - sope-appserver/mod_ngobjweb/NGBufferedDescriptor.c
Add libxml2-dev to libsope-xml4.7-dev deps
[sope] / sope-appserver / mod_ngobjweb / NGBufferedDescriptor.c
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdio.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 {
117   register int availBytes;
118   
119   if (self == NULL) return 0;
120   
121   if (self->readBufferSize == 0) // no read buffering is done (buffersize==0)
122     return read(self->fd, _buf, _len);
123   
124   availBytes = numberOfAvailableReadBufferBytes(self);
125   if (availBytes >= _len) {
126     // there are enough bytes in the buffer to fulfill the request
127     if (_len == 1) {
128       *(unsigned char *)_buf = *(unsigned char *)self->readBufferPos;
129       self->readBufferPos++;
130     }
131     else {
132       memcpy(_buf, self->readBufferPos, _len);
133       self->readBufferPos += _len;  // update read position (consumed-size)
134     }
135     checkReadBufferFillState(self); // check whether all bytes where consumed
136     return _len;
137   }
138   else if (availBytes > 0) {
139     // there are some bytes in the buffer, these are returned
140     
141     memcpy(_buf, self->readBufferPos, availBytes); // copy all bytes from buffer
142     self->readBufferPos      = self->readBuffer; // reset position
143     self->readBufferFillSize = 0;        // no bytes available in buffer anymore
144     return availBytes;
145   }
146   else if (_len > self->readBufferSize) {
147     // requested _len is bigger than the buffersize, so we can bypass the
148     // buffer (which is empty, as guaranteed by the previous 'ifs'
149     return read(self->fd, _buf, _len);
150   }
151   else {
152     // no bytes are available and the requested _len is smaller than the possible
153     // buffer size, we have to read the next block of input from the source
154
155     self->readBufferFillSize = read(self->fd,
156                                     self->readBuffer, self->readBufferSize);
157
158     // no comes a section which is roughly the same like the first to conditionals
159     // in this method
160     if (self->readBufferFillSize >= _len) {
161       // there are enough bytes in the buffer to fulfill the request
162     
163       memcpy(_buf, self->readBufferPos, _len);
164       self->readBufferPos += _len;          // update read position (consumed-size)
165       checkReadBufferFillState(self); // check whether all bytes where consumed
166       return _len;
167     }
168     else { // (readBufferFillSize > 0) (this is ensured by the above assert)
169       // there are some bytes in the buffer, these are returned
170
171       availBytes = self->readBufferFillSize;
172       memcpy(_buf, self->readBufferPos, self->readBufferFillSize); // copy all bytes from buffer
173       self->readBufferPos      = self->readBuffer; // reset position
174       self->readBufferFillSize = 0;          // no bytes available in buffer anymore
175       return availBytes;
176     }
177   }
178 }
179
180 int NGBufferedDescriptor_write(NGBufferedDescriptor *self,
181                                const void *_buf, int _len)
182 {
183   register int  tmp       = 0;
184   register int  remaining = _len;
185   register void *track    = (void *)_buf;
186
187   if (self == NULL) return 0;
188   
189   while (remaining > 0) {
190     // how much bytes available in buffer ?
191     tmp = self->writeBufferSize - self->writeBufferFillSize; 
192     tmp = (tmp > remaining) ? remaining : tmp;
193   
194     memcpy((self->writeBuffer + self->writeBufferFillSize), track, tmp);
195     track += tmp;
196     remaining -= tmp;
197     self->writeBufferFillSize += tmp;
198
199     if (self->writeBufferFillSize == self->writeBufferSize) {
200       void *pos = self->writeBuffer;
201
202       while (self->writeBufferFillSize > 0) {
203         int result;
204         
205         result = write(self->fd, pos, self->writeBufferFillSize);
206         
207         if ((result == 0) || (result < 0)) { // socket closed || error
208           self->writeBufferFillSize = 0; // content is lost ..
209           return result;
210         }
211         self->writeBufferFillSize -= result;
212         pos += result;
213       }
214     }
215   }
216
217 #if 0
218   if (self->flags._flushOnNewline == 1) {
219     // scan buffer for newlines, if one is found, flush buffer
220     
221     for (tmp = 0; tmp < _len; tmp++) {
222       if (tmp == '\n') {
223         NGBufferedDescriptor_flush(self);
224         break;
225       }
226     }
227   }
228 #endif
229   
230   // clean up for GC
231   tmp       = 0;    
232   track     = NULL; // clean up for GC
233   remaining = 0;
234   
235   return _len;
236 }
237
238 char NGBufferedDescriptor_flush(NGBufferedDescriptor *self) {
239   if (self == NULL) return 0;
240   
241   if (self->writeBufferFillSize > 0) {
242     int  toGo = self->writeBufferFillSize;
243     void *pos = self->writeBuffer;
244
245     while (toGo > 0) {
246       int result = write(self->fd, pos, toGo);
247
248       if (result == 0) // socket was closed
249         return 0;
250       else if (result < 1) // socket error
251         return 0;
252
253       toGo -= result;
254       pos  += result;
255     }
256     self->writeBufferFillSize = 0;
257   }
258   return 1;
259 }
260
261 unsigned char NGBufferedDescriptor_safeRead(NGBufferedDescriptor *self,
262                                             void *_buffer, int _len) {
263   if (self == NULL) return 0;
264   
265   if (_len > 0) {
266     while (_len > 0) {
267       int result = NGBufferedDescriptor_read(self, _buffer, _len);
268
269       if (result == 0) // socket was closed
270         return 0;
271       else if (result < 1) // socket error
272         return 0;
273
274       _len    -= result;
275       _buffer += result;
276     }
277   }
278   return 1;
279 }
280 char NGBufferedDescriptor_safeWrite(NGBufferedDescriptor *self,
281                                     const void *_buffer, int _len) {
282   if (self == NULL) return 0;
283   
284   if (_len > 0) {
285     while (_len > 0) {
286       int result;
287       
288       result = NGBufferedDescriptor_write(self, _buffer, _len);
289       
290       if (result == 0) // socket was closed
291         return 0;
292       else if (result < 1) // socket error
293         return 0;
294
295       _len    -= result;
296       _buffer += result;
297     }
298   }
299   return 1;
300 }
301
302 int NGBufferedDescriptor_readChar(NGBufferedDescriptor *self) {
303   unsigned char c;
304   return (NGBufferedDescriptor_safeRead(self, &c, 1)) ? c : -1;
305 }
306
307 char NGBufferedDescriptor_writeHttpHeader(NGBufferedDescriptor *self,
308                                           const char *_key,
309                                           const unsigned char *_value)
310 {
311   register unsigned int len;
312   
313   if (!NGBufferedDescriptor_safeWrite(self, _key, strlen((char *)_key)))
314     return 0;
315   
316   if (!NGBufferedDescriptor_safeWrite(self, ": ", 2))
317     return 0;
318   
319   len = strlen((char *)_value);
320   
321   /*
322      Required for deliverying certificates, we encode \n and \r as %10 and %13
323      assuming that the certficiate is in base64. To safeguard, we also encode
324      % as %25.
325   */
326   if (len > 0 && (index((char *)_value, '\n') != NULL || 
327                   index((char *)_value, '\r') !=NULL)) {
328     for (len = 0; _value[len] != '\0'; len++) {
329       switch (_value[len]) {
330       case '%':
331       case '\r':
332       case '\n': {
333         char buf[4];
334         sprintf(buf, "%%%02i", _value[len]);
335         if (NGBufferedDescriptor_write(self, buf, 3) <= 0)
336           return 0;
337         break;
338       }
339       default:
340         if (NGBufferedDescriptor_write(self, &(_value[len]), 1) <= 0)
341           return 0;
342         break;
343       }
344     }
345   }
346   else {
347     if (!NGBufferedDescriptor_safeWrite(self, _value, len))
348       return 0;
349   }
350   
351   if (!NGBufferedDescriptor_safeWrite(self, "\r\n", 2))
352     return 0;
353   
354   return 1;
355 }