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