2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
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.
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
26 #include "NGBufferedDescriptor.h"
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))
32 // returns the number of bytes which can be read from buffer (without source access)
33 #define numberOfAvailableReadBufferBytes(self) \
34 (self->readBufferFillSize - numberOfConsumedReadBufferBytes(self))
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; \
45 NGBufferedDescriptor *
46 NGBufferedDescriptor_newWithDescriptorAndSize(int _fd, int _size)
48 NGBufferedDescriptor *self = malloc(sizeof(NGBufferedDescriptor));
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;
63 NGBufferedDescriptor *NGBufferedDescriptor_newWithDescriptor(int _fd) {
64 return NGBufferedDescriptor_newWithDescriptorAndSize(_fd, 1024);
66 NGBufferedDescriptor *
67 NGBufferedDescriptor_newWithOwnedDescriptorAndSize(int _fd, int _size) {
68 NGBufferedDescriptor *self = NULL;
70 if ((self = NGBufferedDescriptor_newWithDescriptorAndSize(_fd, _size)))
77 void NGBufferedDescriptor_free(NGBufferedDescriptor *self) {
79 NGBufferedDescriptor_flush(self);
81 if (self->ownsFd && self->fd != -1) {
86 if (self->readBuffer) {
87 free(self->readBuffer);
88 self->readBuffer = NULL;
89 self->readBufferPos = NULL;
91 self->readBufferFillSize = 0;
92 self->readBufferSize = 0;
94 if (self->writeBuffer) {
95 free(self->writeBuffer);
96 self->writeBuffer = NULL;
98 self->writeBufferFillSize = 0;
99 self->writeBufferSize = 0;
105 int NGBufferedDescriptor_getReadBufferSize(NGBufferedDescriptor *self) {
106 if (self == NULL) return 0;
107 return self->readBufferSize;
109 int NGBufferedDescriptor_getWriteBufferSize(NGBufferedDescriptor *self) {
110 if (self == NULL) return 0;
111 return self->writeBufferSize;
114 int NGBufferedDescriptor_read(NGBufferedDescriptor *self,
115 void *_buf, int _len) {
116 register int availBytes = numberOfAvailableReadBufferBytes(self);
118 if (self == NULL) return 0;
120 if (self->readBufferSize == 0) { // no read buffering is done (buffersize==0)
121 return read(self->fd, _buf, _len);
124 if (availBytes >= _len) {
125 // there are enough bytes in the buffer to fulfill the request
127 *(unsigned char *)_buf = *(unsigned char *)self->readBufferPos;
128 self->readBufferPos++;
131 memcpy(_buf, self->readBufferPos, _len);
132 self->readBufferPos += _len; // update read position (consumed-size)
134 checkReadBufferFillState(self); // check whether all bytes where consumed
137 else if (availBytes > 0) {
138 // there are some bytes in the buffer, these are returned
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
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);
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
154 self->readBufferFillSize = read(self->fd,
155 self->readBuffer, self->readBufferSize);
157 // no comes a section which is roughly the same like the first to conditionals
159 if (self->readBufferFillSize >= _len) {
160 // there are enough bytes in the buffer to fulfill the request
162 memcpy(_buf, self->readBufferPos, _len);
163 self->readBufferPos += _len; // update read position (consumed-size)
164 checkReadBufferFillState(self); // check whether all bytes where consumed
167 else { // (readBufferFillSize > 0) (this is ensured by the above assert)
168 // there are some bytes in the buffer, these are returned
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
179 int NGBufferedDescriptor_write(NGBufferedDescriptor *self,
180 const void *_buf, int _len)
182 register int tmp = 0;
183 register int remaining = _len;
184 register void *track = (void *)_buf;
186 if (self == NULL) return 0;
188 while (remaining > 0) {
189 // how much bytes available in buffer ?
190 tmp = self->writeBufferSize - self->writeBufferFillSize;
191 tmp = (tmp > remaining) ? remaining : tmp;
193 memcpy((self->writeBuffer + self->writeBufferFillSize), track, tmp);
196 self->writeBufferFillSize += tmp;
198 if (self->writeBufferFillSize == self->writeBufferSize) {
199 void *pos = self->writeBuffer;
201 while (self->writeBufferFillSize > 0) {
204 result = write(self->fd, pos, self->writeBufferFillSize);
206 if ((result == 0) || (result < 0)) { // socket closed || error
207 self->writeBufferFillSize = 0; // content is lost ..
210 self->writeBufferFillSize -= result;
217 if (self->flags._flushOnNewline == 1) {
218 // scan buffer for newlines, if one is found, flush buffer
220 for (tmp = 0; tmp < _len; tmp++) {
222 NGBufferedDescriptor_flush(self);
231 track = NULL; // clean up for GC
237 char NGBufferedDescriptor_flush(NGBufferedDescriptor *self) {
238 if (self == NULL) return 0;
240 if (self->writeBufferFillSize > 0) {
241 int toGo = self->writeBufferFillSize;
242 void *pos = self->writeBuffer;
245 int result = write(self->fd, pos, toGo);
247 if (result == 0) // socket was closed
249 else if (result < 1) // socket error
255 self->writeBufferFillSize = 0;
260 unsigned char NGBufferedDescriptor_safeRead(NGBufferedDescriptor *self,
261 void *_buffer, int _len) {
262 if (self == NULL) return 0;
266 int result = NGBufferedDescriptor_read(self, _buffer, _len);
268 if (result == 0) // socket was closed
270 else if (result < 1) // socket error
279 char NGBufferedDescriptor_safeWrite(NGBufferedDescriptor *self,
280 const void *_buffer, int _len) {
281 if (self == NULL) return 0;
287 result = NGBufferedDescriptor_write(self, _buffer, _len);
289 if (result == 0) // socket was closed
291 else if (result < 1) // socket error
301 int NGBufferedDescriptor_readChar(NGBufferedDescriptor *self) {
303 return (NGBufferedDescriptor_safeRead(self, &c, 1)) ? c : -1;
306 char NGBufferedDescriptor_writeHttpHeader(NGBufferedDescriptor *self,
307 const unsigned char *_key,
308 const unsigned char *_value)
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)) {