Browse code

fixup to the libxmlrpc pthread support problem - replace the compiled abyss server provided by the libxmlrpc with our own compiling: - import the source files for the abyss server (used by the libxmlrpc) in order to force compiling of fork support (and not pthread) - change makefile to compile these additional files for libxmlrpc ver > 1.0.0 ; also, in this case, the module will not link with the abyss libs provided by the libxmlrpc - if 0.9.10 version is detected, the imported sources will not be compiled and the libxmlrpc code will be used.

Closes bug 1835638.
Many thanks to Dan Pascu for the help in troubleshooting and fixing this nasty problem.


git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@3226 689a6050-402a-0410-94f2-e92a70836424

Bogdan-Andrei Iancu authored on 28/11/2007 19:50:36
Showing 32 changed files
... ...
@@ -49,12 +49,12 @@ endif
49 49
 endif
50 50
 
51 51
 ifneq ($(XMLRPC-C-CONFIG),)
52
-DEFS+=$(shell $(XMLRPC-C-CONFIG) abyss-server --cflags)
53
-LIBS+=$(shell $(XMLRPC-C-CONFIG) abyss-server --libs)
52
+MY_DEFS=$(shell $(XMLRPC-C-CONFIG) abyss-server --cflags)
53
+MY_LIBS=$(shell $(XMLRPC-C-CONFIG) abyss-server --libs)
54 54
 else
55
-DEFS+=-I$(LOCALBASE)/include -I$(LOCALBASE)/include/xmlrpc-c \
56
-		-I$(SYSBASE)/include/xmlrpc-c
57
-LIBS+=-L$(SYSBASE)/lib  -L$(LOCALBASE)/lib -lxmlrpc -lxmlrpc_xmlparse \
55
+MY_DEFS=-I$(LOCALBASE)/include -I$(LOCALBASE)/include/xmlrpc-c \
56
+		-I$(SYSBASE)/include/xmlrpc-c -D_UNIX
57
+MY_LIBS=-L$(SYSBASE)/lib  -L$(LOCALBASE)/lib -lxmlrpc -lxmlrpc_xmlparse \
58 58
 		-lxmlrpc_xmltok -lxmlrpc_abyss -lxmlrpc_abyss_server \
59 59
 		-lxmlrpc_client -lwwwinit -lwwwstream -lwwwxml \
60 60
 		-lwwwapp -lwwwcache -lwwwcore -lwwwdir -lwwwfile \
... ...
@@ -63,6 +63,21 @@ LIBS+=-L$(SYSBASE)/lib  -L$(LOCALBASE)/lib -lxmlrpc -lxmlrpc_xmlparse \
63 63
 		-lwwwtrans -lwwwzip
64 64
 endif
65 65
 
66
+ifeq ($(NEW),yes)
67
+	# remove the abyss library - we already have
68
+	# the code in the module
69
+	MY_DEFS+=-D_UNIX
70
+	MY_LIBS:=$(filter-out %xmlrpc_abyss %xmlrpc_server_abyss %pthread, $(MY_LIBS))
71
+else
72
+	# remove from compiling the code we have in the
73
+	# module for abyss server
74
+	exclude_files=$(wildcard abyss_*.c)
75
+endif
76
+
77
+
78
+DEFS+=$(MY_DEFS)
79
+LIBS+=$(MY_LIBS)
80
+
66 81
 
67 82
 include ../../Makefile.modules
68 83
 
69 84
new file mode 100644
... ...
@@ -0,0 +1,379 @@
0
+/******************************************************************************
1
+**
2
+** conf.c
3
+**
4
+** This file is part of the ABYSS Web server project.
5
+**
6
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
7
+** All rights reserved.
8
+**
9
+** Redistribution and use in source and binary forms, with or without
10
+** modification, are permitted provided that the following conditions
11
+** are met:
12
+** 1. Redistributions of source code must retain the above copyright
13
+**    notice, this list of conditions and the following disclaimer.
14
+** 2. Redistributions in binary form must reproduce the above copyright
15
+**    notice, this list of conditions and the following disclaimer in the
16
+**    documentation and/or other materials provided with the distribution.
17
+** 3. The name of the author may not be used to endorse or promote products
18
+**    derived from this software without specific prior written permission.
19
+** 
20
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
+** SUCH DAMAGE.
31
+**
32
+******************************************************************************/
33
+
34
+#include <stdlib.h>
35
+#include <stdio.h>
36
+#include <string.h>
37
+
38
+#if defined(WIN32) && !defined(__BORLANDC__)
39
+#include <direct.h>
40
+#endif
41
+
42
+#ifdef _UNIX
43
+#include <pwd.h>
44
+#endif
45
+
46
+#include <xmlrpc-c/config.h>
47
+#include "abyss_xmlrpc_int.h"
48
+#include <xmlrpc-c/abyss.h>
49
+#include "abyss_trace.h"
50
+#include "abyss_server.h"
51
+#include "abyss_http.h"
52
+
53
+/*********************************************************************
54
+** Configuration Files Parsing Functions
55
+*********************************************************************/
56
+
57
+
58
+
59
+static abyss_bool
60
+ConfReadLine(TFile *f,char *buffer,uint32_t len) {
61
+    abyss_bool r=TRUE;
62
+    char c,*p,*z=buffer;
63
+
64
+    while ((--len)>0)
65
+    {
66
+        if (FileRead(f,buffer,1)<1)
67
+        {
68
+            if (z==buffer)
69
+                r=FALSE;
70
+            break;
71
+        };
72
+
73
+        if ((*buffer==CR) || (*buffer==LF) )
74
+            break;
75
+
76
+        buffer++;
77
+    };
78
+
79
+    if (len==0)
80
+        while (FileRead(f,&c,1)==1)
81
+            if ((c==CR) || (c==LF))
82
+                break;
83
+
84
+    *buffer='\0';
85
+
86
+    /* Discard comments */
87
+    p=strchr(z,'#');
88
+    if (p)
89
+        *p='\0';
90
+
91
+    return r;
92
+}
93
+
94
+static abyss_bool
95
+ConfNextToken(char **p) {
96
+    while (1)
97
+        switch (**p)
98
+        {
99
+        case '\t':
100
+        case ' ':
101
+            (*p)++;
102
+            break;
103
+        case '\0':
104
+            return FALSE;
105
+        default:
106
+            return TRUE;
107
+        };
108
+}
109
+
110
+static char *
111
+ConfGetToken(char **p) {
112
+    char *p0=*p;
113
+
114
+    while (1)
115
+        switch (**p)
116
+        {
117
+        case '\t':
118
+        case ' ':
119
+        case CR:
120
+        case LF:
121
+        case '\0':
122
+            if (p0==*p)
123
+                return NULL;
124
+
125
+            if (**p)
126
+            {
127
+                **p='\0';
128
+                (*p)++;
129
+            };
130
+            return p0;
131
+
132
+        default:
133
+            (*p)++;
134
+        };
135
+}
136
+
137
+static abyss_bool
138
+ConfReadInt(const char * const p,
139
+            int32_t *    const n,
140
+            int32_t      const min,
141
+            int32_t      const max) {
142
+/*----------------------------------------------------------------------------
143
+   Convert string 'p' to integer *n.
144
+
145
+   If it isn't a valid integer or is not with the bounds [min, max],
146
+   return FALSE.  Otherwise, return TRUE.
147
+-----------------------------------------------------------------------------*/
148
+    char * e;
149
+
150
+    *n = strtol(p, &e, 10);
151
+
152
+    if (min != max)
153
+        return ((e != p) && (*n >= min) && (*n <= max));
154
+    else
155
+        return (e != p);
156
+}
157
+
158
+
159
+
160
+static abyss_bool
161
+ConfReadBool(char *p, abyss_bool *b) {
162
+    if (strcasecmp(p,"yes")==0)
163
+    {
164
+        *b=TRUE;
165
+        return TRUE;
166
+    };
167
+
168
+    if (strcasecmp(p,"no")==0)
169
+    {
170
+        *b=FALSE;
171
+        return TRUE;
172
+    };
173
+
174
+    return FALSE;
175
+}
176
+
177
+/*********************************************************************
178
+** MIME Types File
179
+*********************************************************************/
180
+
181
+static void
182
+readMIMETypesFile(const char * const filename,
183
+                  MIMEType **  const MIMETypePP) {
184
+
185
+    abyss_bool success;
186
+    MIMEType * MIMETypeP;
187
+
188
+    MIMETypeP = MIMETypeCreate();
189
+    if (MIMETypeP) {
190
+        TFile file;
191
+        abyss_bool fileOpened;
192
+
193
+        fileOpened = FileOpen(&file, filename, O_RDONLY);
194
+        if (fileOpened) {
195
+            char z[512];
196
+            while (ConfReadLine(&file, z, 512)) {
197
+                char * p;
198
+                p = &z[0];
199
+            
200
+                if (ConfNextToken(&p)) {
201
+                    const char * mimetype = ConfGetToken(&p);
202
+                    if (mimetype) {
203
+                        while (ConfNextToken(&p)) {
204
+                            const char * const ext = ConfGetToken(&p);
205
+                            if (ext)
206
+                                MIMETypeAdd2(MIMETypeP, mimetype, ext);
207
+                            else
208
+                                break;
209
+                        }
210
+                    }
211
+                }
212
+            }
213
+            FileClose(&file);
214
+            success = TRUE;
215
+        } else
216
+            success = FALSE;
217
+        if (!success)
218
+            MIMETypeDestroy(MIMETypeP);
219
+    } else
220
+        success = FALSE;
221
+
222
+    if (success)
223
+        *MIMETypePP = MIMETypeP;
224
+    else
225
+        *MIMETypePP = NULL;
226
+}
227
+
228
+/*********************************************************************
229
+** Server Configuration File
230
+*********************************************************************/
231
+
232
+static void
233
+chdirx(const char * const newdir,
234
+       abyss_bool * const successP) {
235
+    
236
+#if defined(WIN32) && !defined(__BORLANDC__)
237
+    *successP = _chdir(newdir) == 0;
238
+#else
239
+    *successP = chdir(newdir) == 0;
240
+#endif
241
+}
242
+
243
+
244
+
245
+static void
246
+parseUser(const char *      const p, 
247
+          struct _TServer * const srvP) {
248
+#ifdef _UNIX
249
+    if (p[0] == '#') {
250
+        int32_t n;
251
+        
252
+        if (!ConfReadInt(&p[1], &n, 0, 0))
253
+            TraceExit("Bad user number '%s'", p);
254
+        else
255
+            srvP->uid = n;
256
+    } else {
257
+        struct passwd * pwd;
258
+
259
+        if (!(pwd = getpwnam(p)))
260
+            TraceExit("Unknown user '%s'", p);
261
+        
262
+        srvP->uid = pwd->pw_uid;
263
+        if ((int)srvP->gid==(-1))
264
+            srvP->gid = pwd->pw_gid;
265
+    };
266
+#else
267
+    TraceMsg("User option ignored");
268
+#endif  /* _UNIX */ 
269
+}
270
+
271
+
272
+
273
+static void
274
+parsePidfile(const char *      const p,
275
+             struct _TServer * const srvP) {
276
+#ifdef _UNIX
277
+    if (!FileOpenCreate(&srvP->pidfile, p, O_TRUNC | O_WRONLY)) {
278
+        srvP->pidfile = -1;
279
+        TraceMsg("Bad PidFile value '%s'", p);
280
+    };
281
+#else
282
+    TraceMsg("PidFile option ignored");
283
+#endif  /* _UNIX */ 
284
+}
285
+
286
+
287
+
288
+abyss_bool
289
+ConfReadServerFile(const char * const filename,
290
+                   TServer *    const serverP) {
291
+
292
+    struct _TServer * const srvP = serverP->srvP;
293
+
294
+    TFile f;
295
+    char z[512];
296
+    char * p;
297
+    unsigned int lineNum;
298
+    TFileStat fs;
299
+
300
+    if (!FileOpen(&f, filename, O_RDONLY))
301
+        return FALSE;
302
+
303
+    lineNum = 0;
304
+
305
+    while (ConfReadLine(&f, z, 512)) {
306
+        ++lineNum;
307
+        p = z;
308
+
309
+        if (ConfNextToken(&p)) {
310
+            const char * const option = ConfGetToken(&p);
311
+            if (option) {
312
+                ConfNextToken(&p);
313
+
314
+                if (strcasecmp(option, "port") == 0) {
315
+                    int32_t n;
316
+                    if (ConfReadInt(p, &n, 1, 65535))
317
+                        srvP->port = n;
318
+                    else
319
+                        TraceExit("Invalid port '%s'", p);
320
+                } else if (strcasecmp(option, "serverroot") == 0) {
321
+                    abyss_bool success;
322
+                    chdirx(p, &success);
323
+                    if (!success)
324
+                        TraceExit("Invalid server root '%s'",p);
325
+                } else if (strcasecmp(option, "path") == 0) {
326
+                    if (FileStat(p, &fs))
327
+                        if (fs.st_mode & S_IFDIR) {
328
+                            xmlrpc_strfree(srvP->filespath);
329
+                            srvP->filespath = strdup(p);
330
+                            continue;
331
+                        }
332
+                    TraceExit("Invalid path '%s'", p);
333
+                } else if (strcasecmp(option, "default") == 0) {
334
+                    const char * filename;
335
+                    
336
+                    while ((filename = ConfGetToken(&p))) {
337
+                        ListAdd(&srvP->defaultfilenames, strdup(filename));
338
+                        if (!ConfNextToken(&p))
339
+                            break;
340
+                    }
341
+                } else if (strcasecmp(option, "keepalive") == 0) {
342
+                    int32_t n;
343
+                    if (ConfReadInt(p, &n, 1, 65535))
344
+                        srvP->keepalivemaxconn = n;
345
+                    else
346
+                        TraceExit("Invalid KeepAlive value '%s'", p);
347
+                } else if (strcasecmp(option, "timeout") == 0) {
348
+                    int32_t n;
349
+                    if (ConfReadInt(p, &n, 1, 3600)) {
350
+                        srvP->keepalivetimeout = n;
351
+                        /* Must see what to do with that */
352
+                        srvP->timeout = n;
353
+                    } else
354
+                        TraceExit("Invalid TimeOut value '%s'", p);
355
+                } else if (strcasecmp(option, "mimetypes") == 0) {
356
+                    readMIMETypesFile(p, &srvP->mimeTypeP);
357
+                    if (!srvP->mimeTypeP)
358
+                        TraceExit("Can't read MIME Types file '%s'", p);
359
+                } else if (strcasecmp(option,"logfile") == 0) {
360
+                    srvP->logfilename = strdup(p);
361
+                } else if (strcasecmp(option,"user") == 0) {
362
+                    parseUser(p, srvP);
363
+                } else if (strcasecmp(option, "pidfile")==0) {
364
+                    parsePidfile(p, srvP);
365
+                } else if (strcasecmp(option, "advertiseserver") == 0) {
366
+                    if (!ConfReadBool(p, &srvP->advertise))
367
+                        TraceExit("Invalid boolean value "
368
+                                  "for AdvertiseServer option");
369
+                } else
370
+                    TraceExit("Invalid option '%s' at line %u",
371
+                              option, lineNum);
372
+            }
373
+        }
374
+    }
375
+
376
+    FileClose(&f);
377
+    return TRUE;
378
+}
0 379
new file mode 100644
... ...
@@ -0,0 +1,629 @@
0
+/* Copyright information is at the end of the file. */
1
+
2
+#include <time.h>
3
+#include <string.h>
4
+#include <stdlib.h>
5
+#include <stdio.h>
6
+#include <ctype.h>
7
+#include <assert.h>
8
+
9
+#include "abyss_mallocvar.h"
10
+#include "abyss_xmlrpc_int.h"
11
+#include <xmlrpc-c/abyss.h>
12
+#include "abyss_socket.h"
13
+#include "abyss_server.h"
14
+#include "abyss_thread.h"
15
+
16
+#include "abyss_conn.h"
17
+
18
+/*********************************************************************
19
+** Conn
20
+*********************************************************************/
21
+
22
+static TThreadProc connJob;
23
+
24
+static void
25
+connJob(void * const userHandle) {
26
+/*----------------------------------------------------------------------------
27
+   This is the root function for a thread that processes a connection
28
+   (performs HTTP transactions).
29
+-----------------------------------------------------------------------------*/
30
+    TConn * const connectionP = userHandle;
31
+
32
+    (connectionP->job)(connectionP);
33
+
34
+    connectionP->finished = TRUE;
35
+        /* Note that if we are running in a forked process, setting
36
+           connectionP->finished has no effect, because it's just our own
37
+           copy of *connectionP.  In this case, Parent must update his own
38
+           copy based on a SIGCHLD signal that the OS will generate right
39
+           after we exit.
40
+        */
41
+
42
+    ThreadExit(0);
43
+}
44
+
45
+
46
+
47
+static void
48
+connDone(TConn * const connectionP) {
49
+
50
+    /* In the forked case, this is designed to run in the parent
51
+       process after the child has terminated.
52
+    */
53
+    connectionP->finished = TRUE;
54
+
55
+    if (connectionP->done)
56
+        connectionP->done(connectionP);
57
+}
58
+
59
+
60
+
61
+static TThreadDoneFn threadDone;
62
+
63
+static void
64
+threadDone(void * const userHandle) {
65
+
66
+    TConn * const connectionP = userHandle;
67
+    
68
+    connDone(connectionP);
69
+}
70
+
71
+
72
+
73
+static void
74
+makeThread(TConn *             const connectionP,
75
+           enum abyss_foreback const foregroundBackground,
76
+           abyss_bool          const useSigchld,
77
+           const char **       const errorP) {
78
+           
79
+    switch (foregroundBackground) {
80
+    case ABYSS_FOREGROUND:
81
+        connectionP->hasOwnThread = FALSE;
82
+        *errorP = NULL;
83
+        break;
84
+    case ABYSS_BACKGROUND: {
85
+        const char * error;
86
+        connectionP->hasOwnThread = TRUE;
87
+        ThreadCreate(&connectionP->threadP, connectionP,
88
+                     &connJob, &threadDone, useSigchld,
89
+                     &error);
90
+        if (error) {
91
+            xmlrpc_asprintf(errorP, "Unable to create thread to "
92
+                            "process connection.  %s", error);
93
+            xmlrpc_strfree(error);
94
+        } else
95
+            *errorP = NULL;
96
+    } break;
97
+    } /* switch */
98
+}
99
+
100
+    
101
+
102
+void
103
+ConnCreate(TConn **            const connectionPP,
104
+           TServer *           const serverP,
105
+           TSocket *           const connectedSocketP,
106
+           TThreadProc *       const job,
107
+           TThreadDoneFn *     const done,
108
+           enum abyss_foreback const foregroundBackground,
109
+           abyss_bool          const useSigchld,
110
+           const char **       const errorP) {
111
+/*----------------------------------------------------------------------------
112
+   Create an HTTP connection.
113
+
114
+   A connection carries one or more HTTP transactions (request/response).
115
+
116
+   'connectedSocketP' transports the requests and responses.
117
+
118
+   The connection handles those HTTP requests.
119
+
120
+   The connection handles the requests primarily by running the
121
+   function 'job' once.  Some connections can do that autonomously, as
122
+   soon as the connection is created.  Others don't until Caller
123
+   subsequently calls ConnProcess.  Some connections complete the
124
+   processing before ConnProcess return, while others may run the
125
+   connection asynchronously to the creator, in the background, via a
126
+   TThread thread.  'foregroundBackground' determines which.
127
+
128
+   'job' calls methods of the connection to get requests and send
129
+   responses.
130
+
131
+   Some time after the HTTP transactions are all done, 'done' gets
132
+   called in some context.
133
+-----------------------------------------------------------------------------*/
134
+    TConn * connectionP;
135
+
136
+    MALLOCVAR(connectionP);
137
+
138
+    if (connectionP == NULL)
139
+        xmlrpc_asprintf(errorP, "Unable to allocate memory for a connection "
140
+                        "descriptor.");
141
+    else {
142
+        abyss_bool success;
143
+        uint16_t peerPortNumber;
144
+
145
+        connectionP->server     = serverP;
146
+        connectionP->socketP    = connectedSocketP;
147
+        connectionP->buffersize = 0;
148
+        connectionP->bufferpos  = 0;
149
+        connectionP->finished   = FALSE;
150
+        connectionP->job        = job;
151
+        connectionP->done       = done;
152
+        connectionP->inbytes    = 0;
153
+        connectionP->outbytes   = 0;
154
+        connectionP->trace      = getenv("ABYSS_TRACE_CONN");
155
+
156
+        SocketGetPeerName(connectedSocketP,
157
+                          &connectionP->peerip, &peerPortNumber, &success);
158
+
159
+        if (success)
160
+            makeThread(connectionP, foregroundBackground, useSigchld, errorP);
161
+        else
162
+            xmlrpc_asprintf(errorP, "Failed to get peer name from socket.");
163
+    }
164
+    *connectionPP = connectionP;
165
+}
166
+
167
+
168
+
169
+abyss_bool
170
+ConnProcess(TConn * const connectionP) {
171
+/*----------------------------------------------------------------------------
172
+   Drive the main processing of a connection -- run the connection's
173
+   "job" function, which should read HTTP requests from the connection
174
+   and send HTTP responses.
175
+
176
+   If we succeed, we guarantee the connection's "done" function will get
177
+   called some time after all processing is complete.  It might be before
178
+   we return or some time after.  If we fail, we guarantee the "done"
179
+   function will not be called.
180
+-----------------------------------------------------------------------------*/
181
+    abyss_bool retval;
182
+
183
+    if (connectionP->hasOwnThread) {
184
+        /* There's a background thread to handle this connection.  Set
185
+           it running.
186
+        */
187
+        retval = ThreadRun(connectionP->threadP);
188
+    } else {
189
+        /* No background thread.  We just handle it here while Caller waits. */
190
+        (connectionP->job)(connectionP);
191
+        connDone(connectionP);
192
+        retval = TRUE;
193
+    }
194
+    return retval;
195
+}
196
+
197
+
198
+
199
+void
200
+ConnWaitAndRelease(TConn * const connectionP) {
201
+    if (connectionP->hasOwnThread)
202
+        ThreadWaitAndRelease(connectionP->threadP);
203
+    
204
+    free(connectionP);
205
+}
206
+
207
+
208
+
209
+abyss_bool
210
+ConnKill(TConn * connectionP) {
211
+    connectionP->finished = TRUE;
212
+    return ThreadKill(connectionP->threadP);
213
+}
214
+
215
+
216
+
217
+void
218
+ConnReadInit(TConn * const connectionP) {
219
+    if (connectionP->buffersize>connectionP->bufferpos) {
220
+        connectionP->buffersize -= connectionP->bufferpos;
221
+        memmove(connectionP->buffer,
222
+                connectionP->buffer+connectionP->bufferpos,
223
+                connectionP->buffersize);
224
+        connectionP->bufferpos = 0;
225
+    } else
226
+        connectionP->buffersize=connectionP->bufferpos = 0;
227
+
228
+    connectionP->inbytes=connectionP->outbytes = 0;
229
+}
230
+
231
+
232
+
233
+static void
234
+traceBuffer(const char * const label,
235
+            const char * const buffer,
236
+            unsigned int const size) {
237
+
238
+    unsigned int nonPrintableCount;
239
+    unsigned int i;
240
+    
241
+    nonPrintableCount = 0;  /* Initial value */
242
+    
243
+    for (i = 0; i < size; ++i) {
244
+        if (!isprint(buffer[i]) && buffer[i] != '\n' && buffer[i] != '\r')
245
+            ++nonPrintableCount;
246
+    }
247
+    if (nonPrintableCount > 0)
248
+        fprintf(stderr, "%s contains %u nonprintable characters.\n", 
249
+                label, nonPrintableCount);
250
+    
251
+    fprintf(stderr, "%s:\n", label);
252
+    fprintf(stderr, "%.*s\n", (int)size, buffer);
253
+}
254
+
255
+
256
+
257
+static void
258
+traceSocketRead(TConn *      const connectionP,
259
+                unsigned int const size) {
260
+
261
+    if (connectionP->trace)
262
+        traceBuffer("READ FROM SOCKET:",
263
+                    connectionP->buffer + connectionP->buffersize, size);
264
+}
265
+
266
+
267
+
268
+static void
269
+traceSocketWrite(TConn *      const connectionP,
270
+                 const char * const buffer,
271
+                 unsigned int const size,
272
+                 abyss_bool   const failed) {
273
+
274
+    if (connectionP->trace) {
275
+        const char * const label =
276
+            failed ? "FAILED TO WRITE TO SOCKET:" : "WROTE TO SOCKET";
277
+        traceBuffer(label, buffer, size);
278
+    }
279
+}
280
+
281
+
282
+
283
+static uint32_t
284
+bufferSpace(TConn * const connectionP) {
285
+    
286
+    return BUFFER_SIZE - connectionP->buffersize;
287
+}
288
+                    
289
+
290
+
291
+abyss_bool
292
+ConnRead(TConn *  const connectionP,
293
+         uint32_t const timeout) {
294
+/*----------------------------------------------------------------------------
295
+   Read some stuff on connection *connectionP from the socket.
296
+
297
+   Don't wait more than 'timeout' seconds for data to arrive.  Fail if
298
+   nothing arrives within that time.
299
+-----------------------------------------------------------------------------*/
300
+    time_t const deadline = time(NULL) + timeout;
301
+
302
+    abyss_bool cantGetData;
303
+    abyss_bool gotData;
304
+
305
+    cantGetData = FALSE;
306
+    gotData = FALSE;
307
+    
308
+    while (!gotData && !cantGetData) {
309
+        int const timeLeft = deadline - time(NULL);
310
+
311
+        if (timeLeft <= 0)
312
+            cantGetData = TRUE;
313
+        else {
314
+            int rc;
315
+            
316
+            rc = SocketWait(connectionP->socketP, TRUE, FALSE,
317
+                            timeLeft * 1000);
318
+            
319
+            if (rc != 1)
320
+                cantGetData = TRUE;
321
+            else {
322
+                uint32_t bytesAvail;
323
+            
324
+                bytesAvail = SocketAvailableReadBytes(connectionP->socketP);
325
+                
326
+                if (bytesAvail <= 0)
327
+                    cantGetData = TRUE;
328
+                else {
329
+                    uint32_t const bytesToRead =
330
+                        MIN(bytesAvail, bufferSpace(connectionP)-1);
331
+
332
+                    uint32_t bytesRead;
333
+
334
+                    bytesRead = SocketRead(
335
+                        connectionP->socketP,
336
+                        (unsigned char*)connectionP->buffer + connectionP->buffersize,
337
+                        bytesToRead);
338
+                    if (bytesRead > 0) {
339
+                        traceSocketRead(connectionP, bytesRead);
340
+                        connectionP->inbytes += bytesRead;
341
+                        connectionP->buffersize += bytesRead;
342
+                        connectionP->buffer[connectionP->buffersize] = '\0';
343
+                        gotData = TRUE;
344
+                    }
345
+                }
346
+            }
347
+        }
348
+    }
349
+    if (gotData)
350
+        return TRUE;
351
+    else
352
+        return FALSE;
353
+}
354
+
355
+
356
+            
357
+abyss_bool
358
+ConnWrite(TConn *      const connectionP,
359
+          const void * const buffer,
360
+          uint32_t     const size) {
361
+
362
+    abyss_bool failed;
363
+
364
+    SocketWrite(connectionP->socketP, buffer, size, &failed);
365
+
366
+    traceSocketWrite(connectionP, buffer, size, failed);
367
+
368
+    if (!failed)
369
+        connectionP->outbytes += size;
370
+
371
+    return !failed;
372
+}
373
+
374
+
375
+
376
+abyss_bool
377
+ConnWriteFromFile(TConn *  const connectionP,
378
+                  TFile *  const fileP,
379
+                  uint64_t const start,
380
+                  uint64_t const last,
381
+                  void *   const buffer,
382
+                  uint32_t const buffersize,
383
+                  uint32_t const rate) {
384
+/*----------------------------------------------------------------------------
385
+   Write the contents of the file stream *fileP, from offset 'start'
386
+   up through 'last', to the HTTP connection *connectionP.
387
+
388
+   Meter the reading so as not to read more than 'rate' bytes per second.
389
+
390
+   Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this.
391
+-----------------------------------------------------------------------------*/
392
+    abyss_bool retval;
393
+    uint32_t waittime;
394
+    abyss_bool success;
395
+    uint32_t readChunkSize;
396
+
397
+    if (rate > 0) {
398
+        readChunkSize = MIN(buffersize, rate);  /* One second's worth */
399
+        waittime = (1000 * buffersize) / rate;
400
+    } else {
401
+        readChunkSize = buffersize;
402
+        waittime = 0;
403
+    }
404
+
405
+    success = FileSeek(fileP, start, SEEK_SET);
406
+    if (!success)
407
+        retval = FALSE;
408
+    else {
409
+        uint64_t const totalBytesToRead = last - start + 1;
410
+        uint64_t bytesread;
411
+
412
+        bytesread = 0;  /* initial value */
413
+
414
+        while (bytesread < totalBytesToRead) {
415
+            uint64_t const bytesLeft = totalBytesToRead - bytesread;
416
+            uint64_t const bytesToRead = MIN(readChunkSize, bytesLeft);
417
+
418
+            uint64_t bytesReadThisTime;
419
+
420
+            bytesReadThisTime = FileRead(fileP, buffer, bytesToRead);
421
+            bytesread += bytesReadThisTime;
422
+            
423
+            if (bytesReadThisTime > 0)
424
+                ConnWrite(connectionP, buffer, bytesReadThisTime);
425
+            else
426
+                break;
427
+            
428
+            if (waittime > 0)
429
+                xmlrpc_millisecond_sleep(waittime);
430
+        }
431
+        retval = (bytesread >= totalBytesToRead);
432
+    }
433
+    return retval;
434
+}
435
+
436
+
437
+
438
+static void
439
+processHeaderLine(char *       const start,
440
+                  const char * const headerStart,
441
+                  TConn *      const connectionP,                  
442
+                  time_t       const deadline,
443
+                  abyss_bool * const gotHeaderP,
444
+                  char **      const nextP,
445
+                  abyss_bool * const errorP) {
446
+/*----------------------------------------------------------------------------
447
+  If there's enough data in the buffer at *pP, process a line of HTTP
448
+  header.
449
+
450
+  It is part of a header that starts at 'headerStart' and has been
451
+  previously processed up to 'start'.  The data in the buffer is
452
+  terminated by a NUL.
453
+
454
+  WE MODIFY THE DATA.
455
+-----------------------------------------------------------------------------*/
456
+    abyss_bool gotHeader;
457
+    char * lfPos;
458
+    char * p;
459
+
460
+    p = start;
461
+
462
+    gotHeader = FALSE;  /* initial assumption */
463
+
464
+    lfPos = strchr(p, LF);
465
+    if (lfPos) {
466
+        if ((*p != LF) && (*p != CR)) {
467
+            /* We're looking at a non-empty line */
468
+            if (*(lfPos+1) == '\0') {
469
+                /* There's nothing in the buffer after the line, so we
470
+                   don't know if there's a continuation line coming.
471
+                   Must read more.
472
+                */
473
+                int const timeLeft = deadline - time(NULL);
474
+                
475
+                *errorP = !ConnRead(connectionP, timeLeft);
476
+            }
477
+            if (!*errorP) {
478
+                p = lfPos; /* Point to LF */
479
+                
480
+                /* If the next line starts with whitespace, it's a
481
+                   continuation line, so blank out the line
482
+                   delimiter (LF or CRLF) so as to join the next
483
+                   line with this one.
484
+                */
485
+                if ((*(p+1) == ' ') || (*(p+1) == '\t')) {
486
+                    if (p > headerStart && *(p-1) == CR)
487
+                        *(p-1) = ' ';
488
+                    *p++ = ' ';
489
+                } else
490
+                    gotHeader = TRUE;
491
+            }
492
+        } else {
493
+            /* We're looking at an empty line (i.e. what marks the
494
+               end of the header)
495
+            */
496
+            p = lfPos;  /* Point to LF */
497
+            gotHeader = TRUE;
498
+        }
499
+    }
500
+
501
+    if (gotHeader) {
502
+        /* 'p' points to the final LF */
503
+
504
+        /* Replace the LF or the CR in CRLF with NUL, so as to terminate
505
+           the string at 'headerStart' that is the full header.
506
+        */
507
+        if (p > headerStart && *(p-1) == CR)
508
+            *(p-1) = '\0';  /* NUL out CR in CRLF */
509
+        else
510
+            *p = '\0';  /* NUL out LF */
511
+
512
+        ++p;  /* Point to next line in buffer */
513
+    }
514
+    *gotHeaderP = gotHeader;
515
+    *nextP = p;
516
+}
517
+
518
+
519
+
520
+abyss_bool
521
+ConnReadHeader(TConn * const connectionP,
522
+               char ** const headerP) {
523
+/*----------------------------------------------------------------------------
524
+   Read an HTTP header on connection *connectionP.
525
+
526
+   An HTTP header is basically a line, except that if a line starts
527
+   with white space, it's a continuation of the previous line.  A line
528
+   is delimited by either LF or CRLF.
529
+
530
+   In the course of reading, we read at least one character past the
531
+   line delimiter at the end of the header; we may read much more.  We
532
+   leave everything after the header (and its line delimiter) in the
533
+   internal buffer, with the buffer pointer pointing to it.
534
+
535
+   We use stuff already in the internal buffer (perhaps left by a
536
+   previous call to this subroutine) before reading any more from from
537
+   the socket.
538
+
539
+   Return as *headerP the header value.  This is in the connection's
540
+   internal buffer.  This contains no line delimiters.
541
+-----------------------------------------------------------------------------*/
542
+    uint32_t const deadline = time(NULL) + connectionP->server->srvP->timeout;
543
+
544
+    abyss_bool retval;
545
+    char * p;
546
+    char * headerStart;
547
+    abyss_bool error;
548
+    abyss_bool gotHeader;
549
+
550
+    p = connectionP->buffer + connectionP->bufferpos;
551
+    headerStart = p;
552
+
553
+    gotHeader = FALSE;
554
+    error = FALSE;
555
+
556
+    while (!gotHeader && !error) {
557
+        int const timeLeft = deadline - time(NULL);
558
+
559
+        if (timeLeft <= 0)
560
+            error = TRUE;
561
+        else {
562
+            if (p >= connectionP->buffer + connectionP->buffersize)
563
+                /* Need more data from the socket to chew on */
564
+                error = !ConnRead(connectionP, timeLeft);
565
+
566
+            if (!error) {
567
+                assert(connectionP->buffer + connectionP->buffersize > p);
568
+                processHeaderLine(p, headerStart, connectionP, deadline,
569
+                                  &gotHeader, &p, &error);
570
+            }
571
+        }
572
+    }
573
+    if (gotHeader) {
574
+        /* We've consumed this part of the buffer (but be careful --
575
+           you can't reuse that part of the buffer because the string
576
+           we're returning is in it!
577
+        */
578
+        connectionP->bufferpos += p - headerStart;
579
+        *headerP = headerStart;
580
+        retval = TRUE;
581
+    } else
582
+        retval = FALSE;
583
+
584
+    return retval;
585
+}
586
+
587
+
588
+
589
+TServer *
590
+ConnServer(TConn * const connectionP) {
591
+    return connectionP->server;
592
+}
593
+
594
+
595
+
596
+/*******************************************************************************
597
+**
598
+** conn.c
599
+**
600
+** This file is part of the ABYSS Web server project.
601
+**
602
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
603
+** All rights reserved.
604
+**
605
+** Redistribution and use in source and binary forms, with or without
606
+** modification, are permitted provided that the following conditions
607
+** are met:
608
+** 1. Redistributions of source code must retain the above copyright
609
+**    notice, this list of conditions and the following disclaimer.
610
+** 2. Redistributions in binary form must reproduce the above copyright
611
+**    notice, this list of conditions and the following disclaimer in the
612
+**    documentation and/or other materials provided with the distribution.
613
+** 3. The name of the author may not be used to endorse or promote products
614
+**    derived from this software without specific prior written permission.
615
+** 
616
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
617
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
618
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
619
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
620
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
621
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
622
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
623
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
624
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
625
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
626
+** SUCH DAMAGE.
627
+**
628
+******************************************************************************/
0 629
new file mode 100644
... ...
@@ -0,0 +1,98 @@
0
+#ifndef CONN_H_INCLUDED
1
+#define CONN_H_INCLUDED
2
+
3
+#include <xmlrpc-c/abyss.h>
4
+#include "abyss_socket.h"
5
+#include "abyss_file.h"
6
+
7
+#define BUFFER_SIZE 4096 
8
+
9
+struct _TConn {
10
+    struct _TConn * nextOutstandingP;
11
+        /* Link to the next connection in the list of outstanding
12
+           connections
13
+        */
14
+    TServer * server;
15
+    uint32_t buffersize;
16
+        /* Index into the connection buffer (buffer[], below) where
17
+           the next byte read on the connection will go.
18
+        */
19
+    uint32_t bufferpos;
20
+        /* Index into the connection buffer (buffer[], below) where
21
+           the next byte to be delivered to the user is.
22
+        */
23
+    uint32_t inbytes,outbytes;  
24
+    TSocket * socketP;
25
+    TIPAddr peerip;
26
+    abyss_bool hasOwnThread;
27
+    TThread * threadP;
28
+    abyss_bool finished;
29
+        /* We have done all the processing there is to do on this
30
+           connection, other than possibly notifying someone that we're
31
+           done.  One thing this signifies is that any thread or process
32
+           that the connection spawned is dead or will be dead soon, so
33
+           one could reasonably wait for it to be dead, e.g. with
34
+           pthread_join().  Note that one can scan a bunch of processes
35
+           for 'finished' status, but sometimes can't scan a bunch of
36
+           threads for liveness.
37
+        */
38
+    const char * trace;
39
+    TThreadProc * job;
40
+    TThreadDoneFn * done;
41
+    char buffer[BUFFER_SIZE];
42
+};
43
+
44
+typedef struct _TConn TConn;
45
+
46
+TConn * ConnAlloc(void);
47
+
48
+void ConnFree(TConn * const connectionP);
49
+
50
+void
51
+ConnCreate(TConn **            const connectionPP,
52
+           TServer *           const serverP,
53
+           TSocket *           const connectedSocketP,
54
+           TThreadProc *       const job,
55
+           TThreadDoneFn *     const done,
56
+           enum abyss_foreback const foregroundBackground,
57
+           abyss_bool          const useSigchld,
58
+           const char **       const errorP);
59
+
60
+abyss_bool
61
+ConnProcess(TConn * const connectionP);
62
+
63
+abyss_bool
64
+ConnKill(TConn * const connectionP);
65
+
66
+void
67
+ConnWaitAndRelease(TConn * const connectionP);
68
+
69
+abyss_bool
70
+ConnWrite(TConn *      const connectionP,
71
+          const void * const buffer,
72
+          uint32_t     const size);
73
+
74
+abyss_bool
75
+ConnRead(TConn *  const c,
76
+         uint32_t const timems);
77
+
78
+void
79
+ConnReadInit(TConn * const connectionP);
80
+
81
+abyss_bool
82
+ConnReadHeader(TConn * const connectionP,
83
+               char ** const headerP);
84
+
85
+abyss_bool
86
+ConnWriteFromFile(TConn *  const connectionP,
87
+                  TFile *  const file,
88
+                  uint64_t const start,
89
+                  uint64_t const end,
90
+                  void *   const buffer,
91
+                  uint32_t const buffersize,
92
+                  uint32_t const rate);
93
+
94
+TServer *
95
+ConnServer(TConn * const connectionP);
96
+
97
+#endif
0 98
new file mode 100644
... ...
@@ -0,0 +1,639 @@
0
+/******************************************************************************
1
+**
2
+** list.c
3
+**
4
+** This file is part of the ABYSS Web server project.
5
+**
6
+** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.
7
+** All rights reserved.
8
+**
9
+** Redistribution and use in source and binary forms, with or without
10
+** modification, are permitted provided that the following conditions
11
+** are met:
12
+** 1. Redistributions of source code must retain the above copyright
13
+**    notice, this list of conditions and the following disclaimer.
14
+** 2. Redistributions in binary form must reproduce the above copyright
15
+**    notice, this list of conditions and the following disclaimer in the
16
+**    documentation and/or other materials provided with the distribution.
17
+** 3. The name of the author may not be used to endorse or promote products
18
+**    derived from this software without specific prior written permission.
19
+** 
20
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
+** SUCH DAMAGE.
31
+**
32
+*******************************************************************************/
33
+
34
+#include <assert.h>
35
+#include <stdlib.h>
36
+#include <string.h>
37
+
38
+#include "abyss_mallocvar.h"
39
+#include "abyss_xmlrpc_int.h"
40
+
41
+#include <xmlrpc-c/abyss.h>
42
+
43
+#include "abyss_token.h"
44
+
45
+#include "abyss_data.h"
46
+
47
+/*********************************************************************
48
+** List
49
+*********************************************************************/
50
+
51
+void ListInit(TList *sl)
52
+{
53
+    sl->item=NULL;
54
+    sl->size=sl->maxsize=0;
55
+    sl->autofree=FALSE;
56
+}
57
+
58
+void ListInitAutoFree(TList *sl)
59
+{
60
+    sl->item=NULL;
61
+    sl->size=sl->maxsize=0;
62
+    sl->autofree=TRUE;
63
+}
64
+
65
+
66
+
67
+void
68
+ListFree(TList * const sl) {
69
+
70
+    if (sl->item) {
71
+        if (sl->autofree) {
72
+            unsigned int i;
73
+            for (i = sl->size; i > 0; --i)
74
+                free(sl->item[i-1]);
75
+            
76
+        }
77
+        free(sl->item);
78
+    }
79
+    sl->item = NULL;
80
+    sl->size = 0;
81
+    sl->maxsize = 0;
82
+}
83
+
84
+
85
+
86
+void
87
+ListFreeItems(TList * const sl) {
88
+
89
+    if (sl->item) {
90
+        unsigned int i;
91
+        for (i = sl->size; i > 0; --i)
92
+            free(sl->item[i-1]);
93
+    }
94
+}
95
+
96
+
97
+
98
+abyss_bool
99
+ListAdd(TList * const sl,
100
+        void *  const str) {
101
+/*----------------------------------------------------------------------------
102
+   Add an item to the end of the list.
103
+-----------------------------------------------------------------------------*/
104
+    abyss_bool success;
105
+
106
+    if (sl->size >= sl->maxsize) {
107
+        uint16_t newSize = sl->maxsize + 16;
108
+        void **newitem;
109
+        
110
+        newitem = realloc(sl->item, newSize * sizeof(void *));
111
+        if (newitem) {
112
+            sl->item    = newitem;
113
+            sl->maxsize = newSize;
114
+        }
115
+    }
116
+
117
+    if (sl->size >= sl->maxsize)
118
+        success = FALSE;
119
+    else {
120
+        success = TRUE;
121
+        sl->item[sl->size++] = str;
122
+    }
123
+    return success;
124
+}
125
+
126
+
127
+
128
+void
129
+ListRemove(TList * const sl) {
130
+/*----------------------------------------------------------------------------
131
+   Remove the last item from the list.
132
+-----------------------------------------------------------------------------*/
133
+
134
+    assert(sl->size > 0);
135
+
136
+    --sl->size;
137
+}
138
+
139
+
140
+
141
+abyss_bool
142
+ListAddFromString(TList *      const list,
143
+                  const char * const stringArg) {
144
+
145
+    abyss_bool retval;
146
+    
147
+    if (!stringArg)
148
+        retval = TRUE;
149
+    else {
150
+        char * buffer;
151
+        
152
+        buffer = strdup(stringArg);
153
+        if (!buffer)
154
+            retval = FALSE;
155
+        else {
156
+            abyss_bool endOfString;
157
+            abyss_bool error;
158
+            char * c;
159
+
160
+            for (c = &buffer[0], endOfString = FALSE, error = FALSE;
161
+                 !endOfString && !error;
162
+                ) {
163
+                const char * t;
164
+                NextToken((const char **)&c);
165
+                
166
+                while (*c == ',')
167
+                    ++c;
168
+                
169
+                t = GetToken(&c);
170
+                if (!t)
171
+                    endOfString = TRUE;
172
+                else {
173
+                    char * p;
174
+
175
+                    for (p = c - 2; *p == ','; --p)
176
+                        *p = '\0';
177
+                    
178
+                    if (t[0] != '\0') {
179
+                        abyss_bool added;
180
+                        added = ListAdd(list, (void*)t);
181
+                        
182
+                        if (!added)
183
+                            error = TRUE;
184
+                    }
185
+                }
186
+            }
187
+            retval = !error;
188
+            xmlrpc_strfree(buffer);
189
+        }
190
+    }
191
+    return retval;
192
+}
193
+
194
+
195
+
196
+abyss_bool
197
+ListFindString(TList *      const sl,
198
+               const char * const str,
199
+               uint16_t *   const indexP)
200
+{
201
+    uint16_t i;
202
+
203
+    if (sl->item && str)
204
+        for (i=0;i<sl->size;i++)
205
+            if (strcmp(str,(char *)(sl->item[i]))==0)
206
+            {
207
+                *indexP=i;
208
+                return TRUE;
209
+            };
210
+
211
+    return FALSE;
212
+}
213
+
214
+/*********************************************************************
215
+** Buffer
216
+*********************************************************************/
217
+
218
+abyss_bool BufferAlloc(TBuffer *buf,uint32_t memsize)
219
+{
220
+    /* ************** Implement the static buffers ***/
221
+    buf->staticid=0;
222
+    buf->data=(void *)malloc(memsize);
223
+    if (buf->data)
224
+    {
225
+        buf->size=memsize;
226
+        return TRUE;
227
+    }
228
+    else
229
+    {
230
+        buf->size=0;
231
+        return FALSE;
232
+    };
233
+}
234
+
235
+void BufferFree(TBuffer *buf)
236
+{
237
+    if (buf->staticid)
238
+    {
239
+        /* ************** Implement the static buffers ***/
240
+    }
241
+    else
242
+        free(buf->data);
243
+
244
+    buf->size=0;
245
+    buf->staticid=0;
246
+}
247
+
248
+abyss_bool BufferRealloc(TBuffer *buf,uint32_t memsize)
249
+{
250
+    if (buf->staticid)
251
+    {
252