/[webpac]/openisis/0.9.9e/tool/srv.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /openisis/0.9.9e/tool/srv.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 604 - (hide annotations)
Mon Dec 27 21:49:01 2004 UTC (19 years, 4 months ago) by dpavlin
File MIME type: text/plain
File size: 8764 byte(s)
import of new openisis release, 0.9.9e

1 dpavlin 604 /*
2     The Malete project - the Z39.2/Z39.50 database framework of OpenIsis.
3     Version 0.9.x (patchlevel see file Version)
4     Copyright (C) 2001-2004 by Erik Grziwotz, erik@openisis.org
5    
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10    
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14     See the GNU Lesser General Public License for more details.
15    
16     You should have received a copy of the GNU Lesser General Public
17     License along with this library; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19    
20     see README for more information
21     EOH */
22    
23     /*
24     $Id: srv.c,v 1.7 2004/08/16 12:10:07 kripke Exp $
25     malete server
26     */
27     #ifndef WIN32
28     #include <sys/types.h>
29     #include <sys/time.h>
30     #include <sys/select.h>
31     #include <sys/socket.h>
32     #include <unistd.h>
33     #include <fcntl.h>
34     #include <netinet/in.h>
35     #include <sys/un.h>
36     #include <string.h> /* memcpy et al */
37     #include <signal.h>
38     #include <errno.h>
39     #include <sys/wait.h>
40     #else
41     #define WIN32_LEAN_AND_MEAN
42     #define NONAMELESSUNION
43     /* #include <winsock2.h> -lws2_32 */
44     #include <winsock.h> /* -lwsock32 "good" enough ? */
45     #define close closesocket
46     #endif
47    
48     #include "../tool/tool.h"
49    
50    
51     static void stdsrv ( file f )
52     {
53     List in;
54     FIL_DEFBUF(f);
55     lInit(&in, 0);
56     while ( fGetr(lClr(&in), &fb) ) {
57     dispatch(in.fld);
58     SEOR(env.out);
59     }
60     } /* srv */
61    
62    
63     static char buf[0x2000];
64     static int fill;
65     static int crlf;
66     static int wrotehead;
67     static int broken;
68     static unsigned sock; /* response socket */
69     enum {
70     SOL, /* at start of line */
71     TAG, /* in tag (only digits seen in line) */
72     VAL /* in val (some non-digit seen) */
73     };
74    
75     static int flushsock ()
76     {
77     int got = send(sock, buf, fill, 0);
78     if ( 0 < got ) {
79     if ( !(fill -= got) )
80     return 0;
81     memmove(buf, buf+got, fill);
82     return 0;
83     }
84     fill = 0;
85     return broken = eRr(ERR_NO, "could not send");
86     }
87    
88    
89     static void sinksock (Sink *lo, int eor)
90     {
91     Fld *f = lo->lst.fld, *e = f + RLEN(f);
92    
93     if ( (unsigned)-1 == sock )
94     goto reset;
95     if ( wrotehead )
96     f++;
97     for ( ; f < e; f++ ) {
98     int maxfill = sizeof(buf)-13-f->len, l, n;
99     char *p, *v;
100     if ( 0 > maxfill )
101     maxfill = 0;
102     /* make sure we have enough room */
103     while ( fill > maxfill )
104     if ( flushsock() )
105     goto reset;
106     p = buf+fill;
107     if ( wrotehead ) {
108     p += i2a(p, f->tag);
109     *p++ = TAB;
110     } else {
111     if ( 10>b36val[(unsigned)*f->val] ) {
112     *p++ = 'W';
113     *p++ = TAB;
114     }
115     wrotehead = 1;
116     }
117     v = f->val;
118     l = f->len;
119     /* write field value */
120     while ( l >= (n = buf+sizeof(buf) - p) ) {
121     memcpy(p, v, n);
122     fill = sizeof(buf);
123     if ( flushsock() )
124     goto reset;
125     p = buf+fill;
126     }
127     memcpy(p, v, l);
128     p += l;
129     *p++ = LF;
130     fill = p - buf;
131     } /* for */
132     if ( eor ) { /* add a \n and flush */
133     if ( sizeof(buf) == fill && flushsock() ) /* pathological */
134     goto reset;
135     buf[fill++] = LF;
136     while ( fill && !flushsock() )
137     ;
138     }
139     reset:
140     lReset(&lo->lst);
141     } /* sinksock */
142    
143    
144     /*
145     serve one request on sock
146     */
147     static int srv1 ()
148     {
149     #define CR 13
150     int state = SOL, neg = 0;
151     char *p, *e, *n;
152     unsigned l;
153     List in;
154     Fld *f = 0;
155    
156     crlf = 0;
157     lInit(&in, 0);
158    
159     wantmore: /* really a for, but we need multi-level continue anyway */
160     if ( 0 >= (fill = recv(sock, p = buf, sizeof(buf), 0)) )
161     return eRr(LOG_WARN, "got %d in recv", fill);
162     LOG_DBG(LOG_DEBUG, "got %d bytes", fill);
163     e = p + fill;
164     havemore:
165     switch (state) {
166     case SOL:
167     switch (*p) {
168     case CR:
169     if (e == p+1) goto wantmore; /* ignore */
170     if (LF != p[1]) break; /* weird crap */
171     p++;
172     case LF: /* got blank line */
173     if ( e > ++p )
174     return eRr(ERR_INVAL, "got %d excess bytes", e-p);
175     goto gotit; /* break 2 */
176     }
177     LNEWF(&in, 0, 80);
178     if ( !f && (CT_IS(D,*p) || '-' == *p) ) {
179     eRr(LOG_WARN, "no message name");
180     LNEWF(&in, 0, 80);
181     }
182     f = LLAST(&in);
183     state = TAG;
184     if ( (neg = '-' == *p) && e == ++p ) goto wantmore;
185     case TAG:
186     while ( CT_IS(D,*p) ) {
187     f->tag = f->tag*10 + b36val[(unsigned char)*p];
188     if ( e == ++p ) goto wantmore; /* continue 2 */
189     }
190     if ( neg )
191     f->tag = -f->tag;
192     LOG_DBG(LOG_DEBUG, "got tag %d", f->tag);
193     state = VAL;
194     if ( TAB == *p && e == ++p ) goto wantmore;
195     case VAL:
196     n = memchr(p, LF, e-p);
197     if ( !n )
198     l = e-p;
199     else if ( (l = n-p) && 13 == n[-1] ) {
200     if ( crlf )
201     l--;
202     else if ( f == in.fld ) {
203     l--;
204     crlf = 1;
205     LOG_DBG(LOG_DEBUG, "detected crlf");
206     }
207     }
208     LAPP(&in, p, l);
209     if ( n ) {
210     state = SOL;
211     if ( e > (p = n+1) )
212     goto havemore;
213     }
214     goto wantmore;
215     }
216     gotit:
217     fill = 0;
218     wrotehead = 0;
219     broken = 0;
220     env.out->off = 0;
221     lClr(&env.out->lst);
222     dispatch(in.fld);
223     SEOR(env.out);
224     return broken;
225     } /* srv1 */
226    
227    
228     /* ************************************************************
229     */
230    
231     int server ()
232     {
233     Ses s;
234     Fld opt = { 0, 0, 0 };
235     fd_set lst; /* listening socks */
236     fd_set all;
237     unsigned fdlen = 0;
238     #ifndef WIN32
239     unsigned kids = 0;
240     #endif
241    
242     sInit(ses = &s);
243     FD_ZERO(&lst);
244     FD_ZERO(&all);
245     if ( env.opt ) for ( opt.val = 0; vGet(&opt, env.opt->fld, "S"); )
246     switch (opt.tag) {
247     static const int yes = !0;
248     struct sockaddr_in si;
249     #ifndef WIN32
250     struct sockaddr_un su;
251     #endif
252     struct sockaddr *sa;
253     int sal;
254     Fld info;
255     case 'S': /* socket */
256     info = opt; /* for message */
257     #ifndef WIN32
258     if ( opt.len && '/'==*opt.val ) { /* unix socket */
259     if ( opt.len > sizeof(su.sun_path)-1 ) {
260     eRr(ERR_INVAL, "unix socket name '%.*s' too long", opt.len, opt.val);
261     return 1;
262     }
263     memset(&su, 0, sizeof(su));
264     memcpy(su.sun_path, opt.val, opt.len);
265     su.sun_path[opt.len] = 0;
266     su.sun_family = AF_UNIX;
267     unlink(su.sun_path);
268     sa = (struct sockaddr*)&su;
269     sal = sizeof(su);
270     sock = socket(PF_UNIX, SOCK_STREAM, 0);
271     } else
272     #else
273     {
274     WSADATA wsadata;
275     memset(&wsadata, 0, sizeof(wsadata));
276     if ( WSAStartup(2, &wsadata) ) {
277     /* funny enough, winsock 1 says ok :) */
278     eRr(ERR_INVAL, "could not get winsock");
279     return 1;
280     }
281     }
282     #endif
283     { /* TCP socket */
284     memset(&si, 0, sizeof(si));
285     si.sin_family = AF_INET;
286     si.sin_addr.s_addr = INADDR_ANY;
287     si.sin_port = htons(2042);
288     if ( opt.len ) { /* standard */
289     Fld port = opt;
290     char *end = memchr(opt.val, ':', opt.len);
291     if ( end /* host:port */
292     || CT_D!=lat1ct[(unsigned char)*opt.val] /* hostname */
293     || memchr(opt.val, '.', opt.len)
294     ) {
295     if ( !end ) end = opt.val+opt.len;
296     if ( 9 >= (end - opt.val)
297     && !memcmp("localhost",opt.val,end - opt.val)
298     )
299     si.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
300     else { /* parse dotted decimal */
301     }
302     if ( (port.len = opt.len - (end - opt.val)) ) {
303     port.len--;
304     port.val = end+1;
305     }
306     }
307     if ( port.len )
308     si.sin_port = htons(V2I(&port));
309     } else {
310     info.val = "*:2042";
311     info.len = 6;
312     }
313     sa = (struct sockaddr *)&si;
314     sal = sizeof(si);
315     sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP/*6*/);
316     }
317     if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) ) {
318     eRr(ERR_NO, "setsockopt");
319     return 1;
320     }
321     if ( bind(sock, sa, sal) ) {
322     eRr(ERR_NO, "could not bind to '%.*s'", info.len, info.val);
323     return 1;
324     }
325     if ( listen(sock, 64) ) {
326     eRr(ERR_NO, "listen failed");
327     return 1;
328     }
329     eRr(LOG_INFO, "listening on '%.*s'", info.len, info.val);
330     FD_SET(sock, &lst);
331     FD_SET(sock, &all);
332     if ( fdlen < sock+1 )
333     fdlen = sock+1;
334     }
335     /* done with options */
336     if ( !fdlen ) {
337     stdsrv(env.in);
338     return 0;
339     }
340     env.out->snk = sinksock;
341     for (;;) {
342     fd_set sele = all;
343     int got = select(fdlen, &sele, 0, 0, 0);
344     if ( 0 >= got ) {
345     eRr(ERR_NO, "select said %d", got);
346     continue;
347     }
348     for ( sock=0; got--; ) {
349     while (!FD_ISSET(sock, &sele))
350     sock++;
351     if ( FD_ISSET(sock, &lst) ) {
352     struct sockaddr peer;
353     unsigned /*socklen_t is broken*/ plen = sizeof(peer);
354     unsigned nsock = accept(sock, &peer, &plen);
355     #ifndef WIN32
356     if ( ENV_EXCL != env.wri ) { /* shared or read only */
357     if ( fork() ) {
358     close(nsock);
359     kids++;
360     continue;
361     }
362     sock = nsock;
363     while ( !srv1() )
364     ;
365     exit(0);
366     }
367     #endif
368     FD_SET(nsock, &all);
369     if ( fdlen < nsock+1 )
370     fdlen = nsock+1;
371     continue;
372     }
373     /* else serve a request on this socket */
374     /* TODO: use the socket's session */
375     if ( srv1() ) {
376     close(sock);
377     FD_CLR(sock, &all);
378     }
379     }
380     #ifndef WIN32
381     for ( ;kids && 0 < waitpid(-1, 0, WNOHANG); kids--)
382     ;
383     #endif
384     }
385     return 0;
386     } /* server */

  ViewVC Help
Powered by ViewVC 1.1.26