/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
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