/[webpac]/trunk2/openisis/lcli.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 /trunk2/openisis/lcli.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 239 - (hide annotations)
Mon Mar 8 17:49:13 2004 UTC (20 years ago) by dpavlin
Original Path: trunk/openisis/lcli.c
File MIME type: text/plain
File size: 9048 byte(s)
including openisis 0.9.0 into webpac tree

1 dpavlin 237 /*
2     openisis - an open implementation of the CDS/ISIS database
3     Version 0.8.x (patchlevel see file Version)
4     Copyright (C) 2001-2003 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. See the GNU
14     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: lcli.c,v 1.13 2003/05/15 19:17:17 mawag Exp $
25     OpenIsis client side of communication
26     */
27    
28     #ifndef WIN32
29     #include <sys/types.h>
30     #include <sys/socket.h> /* socket etc */
31     #include <netinet/in.h> /* IPPROTO_TCP, htons */
32     #include <netdb.h> /* gethostbyname */
33     #endif
34    
35     #include <errno.h>
36     #include <memory.h>
37     #include <unistd.h>
38    
39     #include "openisis.h"
40     #include "loi.h"
41     #include "lio.h"
42     #include "lcli.h"
43    
44     /*
45     gcc -D_MAIN_ -I. -Lsto lcli.c -lopenisis && ./a.out 111 `find .`
46     gcc -D_MAIN_ -DWIN32 -I. lcli.c win/libopenisis.a /mingw/lib/libwsock32.a
47     */
48    
49     #define LF 10 /* LineFeed a.k.a. newline - '\n' isn't really well defined */
50     #define TAB 9 /* horizontal, that is */
51     #define VT 11 /* vertical, used as newline replacement */
52    
53     #define STAT_CONT 0x01 /* not at beginning of line */
54     #define STAT_BIN 0x10 /* binary mode */
55    
56     /* plain protocol
57     * @return done or -err
58     */
59     int cliPlain (Ios *s, int *stat, Rec **rec) {
60     Field *f;
61     int l = s->b.fill - s->b.done;
62     unsigned char *b = s->b.c + s->b.done;
63     unsigned char *end = b+l, *v, *p;
64     if ( ! l ) { /* EOF: done */
65     if ( ! (STAT_CONT & *stat) ) /* ok */
66     return 1;
67     /* last field wasn't closed by LF */
68     return sMsg (ERR_INVAL, "cliPlain(%d): no EOL", LIO_FD & s->file);
69     }
70     if ( STAT_CONT & *stat )
71     RSPACE( *rec, l, !0 );
72     /* add text lines */
73     while ( b<end ) {
74     int conti = 0;
75     switch ( STAT_CONT & *stat ) {
76     case 0: /* at beginning of line -- start new field */
77     if ( LF == *b ) /* empty line */
78     return 1;
79     if ( TAB != *b || ! *rec || ! (*rec)->len ) {
80     RADD( *rec, 0,0,end-b, !0 );
81     }
82     else { /* binary mode continuation line */
83     conti = 1;
84     if ( !(STAT_BIN & *stat)) {
85     sMsg( LOG_INFO, "cliPlain(%d): detected binary mode",
86     LIO_FD & s->file);
87     *stat |= STAT_BIN;
88     }
89     RSPACE( *rec, end-b, !0 );
90     }
91     if ( ! *rec )
92     return -ERR_NOMEM;
93     *stat |= STAT_CONT;
94     case STAT_CONT: /* add to last field */
95     f = (*rec)->field + (*rec)->len-1;
96     v = (unsigned char*)f->val;
97     p = v + f->len;
98     if ( conti ) {
99     *p++ = LF;
100     b++;
101     }
102     if ( STAT_BIN & *stat ) {
103     for ( ; b<end && LF != (*p = *b++); p++ )
104     ;
105     } else {
106     for ( ; b<end && LF != (*p = *b++); p++ )
107     if ( VT == *p ) /* convert VTABs */
108     *p = LF; /* back to newlines */
109     }
110     (*rec)->used += (p - v) - f->len;
111     f->len = p - v;
112     if ( LF == b[-1] ) {
113     int ret = a2il( f->val, f->len, &f->tag );
114     if ( ret ) {
115     if ( ret < f->len && TAB == v[ret] )
116     ret++;
117     if ( ret < f->len )
118     memmove( v, v+ret, f->len - ret );
119     f->len -= ret;
120     }
121     *stat &= ~STAT_CONT;
122     }
123     sMsg (LOG_VERBOSE, "cliPlain(%d): fld[%2d] %3d = '%.*s'",
124     LIO_FD & s->file, (*rec)->len-1, f->tag, f->len, f->val);
125     }
126     }
127     return 0;
128     }
129    
130     Rec* cliRead (CliChnl *ch) {
131     Ios str;
132     Rec *rec;
133     int rt, stat;
134    
135     if (!ch || 0 > ch->sd) {
136     return 0;
137     }
138     memset (&str, 0, sizeof (Ios));
139     str.file = ch->sd | LIO_IN;
140     rec = 0;
141     stat = 0;
142     ch->err = errno = 0;
143    
144     while (1) {
145     str.b.done = str.b.fill;
146     rt = ioStdio (&str, LIO_SFILL);
147     if (0 > rt) {
148     ch->err = errno;
149     if (rec) {
150     mFree (rec);
151     }
152     if (!(LIO_IN & str.file)) {
153     ch->sd = -1;
154     }
155     return 0;
156     }
157     rt = cliPlain (&str, &stat, &rec);
158     if (rt) {
159     if (0 > rt) {
160     if (rec) {
161     mFree (rec);
162     }
163     return 0;
164     }
165     log_rec (LOG_VERBOSE, rec, "cliRead(%d): ", 0);
166     sMsg (LOG_INFO, "cliRead(%d): read #flds %d",
167     ch->sd, (rec ? rec->len : -1));
168     return rec;
169     }
170     }
171     }
172    
173     int cliWrite (CliChnl *ch, Rec *rec) {
174     char buf [4096];
175     char *b;
176     int fd, len, sl, rl, rt;
177     if (!ch || 0 > ch->sd) {
178     return -ERR_BADF;
179     }
180     ch->err = 0;
181     if (!rec || !rec->len) {
182     return 0;
183     }
184     len = sizeof (buf);
185     b = rSerA (rec, buf, &len);
186     if (!b) {
187     return sMsg (ERR_NOMEM, "cliWrite(%d): write (%d)", ch->sd, rec->used);
188     }
189     fd = ch->sd | LIO_OUT;
190     for (sl = rt = errno = 0, rl = len; rl; sl += rt, rl -= rt) {
191     rt = lio_write (&fd, b + sl, (unsigned)rl);
192     ch->err = errno;
193     if (0 > rt) {
194     if (!(LIO_OUT & fd)) {
195     ch->sd = -1;
196     }
197     break;
198     }
199     }
200     if (b != buf) {
201     mFree (b);
202     }
203     if (0 > rt) {
204     return sMsg (ERR_IO, "cliWrite(%d): write (%d) = %d(%d)",
205     len, rt, ch->err);
206     }
207     sMsg (LOG_INFO, "cliWrite(%d): wrote %d,%d", ch->sd, rec->len, len);
208     return 0;
209     }
210    
211     int cliConnect (CliChnl *ch, const char *hname, int port) {
212     #ifdef WIN32
213     return sMsg (ERR_TRASH, "cliConnect: operation not supported");
214     #else
215     struct sockaddr_in addr;
216     struct hostent *hostp;
217     int rt;
218     if (!ch) {
219     return sMsg (ERR_IDIOT, "cliConnect: null channel");
220     }
221     memset (ch, 0, sizeof (CliChnl));
222     rt = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
223     if (0 > rt) {
224     ch->err = errno;
225     return sMsg (ERR_IO, "cliConnect: cannot create socket: %d", errno);
226     }
227     ch->sd = rt;
228     memset (&addr, 0, sizeof (addr));
229     if (hname) {
230     hostp = gethostbyname (hname);
231     if (! hostp) {
232     ch->err = errno;
233     return sMsg (ERR_INVAL, "cliConnect: unknown host <%s>: %d",
234     hname, errno);
235     }
236     addr.sin_family = hostp->h_addrtype; /* already network-byte-order */
237     addr.sin_addr.s_addr = *(long*)(*(hostp->h_addr_list)); /* dto */
238     }
239     else {
240     addr.sin_family = AF_INET;
241     addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
242     }
243     addr.sin_port = htons (port);
244     rt = connect (ch->sd, &addr, sizeof (addr));
245     if (0 > rt) {
246     ch->err = errno;
247     return sMsg (ERR_IO, "cliConnect: cannot connect to %s:%d: %d",
248     (hname ? hname : "localhost"), port, errno);
249     }
250     return 0;
251     #endif
252     }
253    
254     void cliClose (CliChnl *ch) {
255     if (ch && 0 <= ch->sd) {
256     close (ch->sd);
257     ch->sd = -1;
258     }
259     }
260    
261     /* -----------------------------------------------------------------------
262     * test
263     */
264     #ifdef _MAIN_
265    
266     #include <stdio.h> /* printf */
267     #include <stdlib.h> /* atoi */
268     #include <string.h> /* strerror */
269     #include "luti.h" /* log_rec */
270    
271     void cmp (Rec *in, Rec *out) {
272     Field *F1, *F2;
273     int l1 = in->len;
274     int l2 = out->len;
275     int j, k;
276     for (j = k = 0, F1 = in->field, F2 = out->field; l2 > k; ++k, ++F2) {
277     if (0 > F2->tag) {
278     continue;
279     }
280     if (l1 <= j) {
281     printf ("ERR too many answers %d %d\n", j, k);
282     log_rec (0, in, "ERR IN ", 0);
283     log_rec (0, out, "ERR OUT ", 0);
284     exit (1);
285     }
286     if (F1->tag != F2->tag) {
287     printf ("ERR tag %d mismatch %d %d\n", j, F1->tag, F2->tag);
288     log_rec (0, in, "ERR IN ", 0);
289     log_rec (0, out, "ERR OUT ", 0);
290     exit (1);
291     }
292     if (F1->len != F2->len) {
293     printf ("ERR len %d mismatch %d %d\n", j, F1->tag, F2->tag);
294     log_rec (0, in, "ERR IN ", 0);
295     log_rec (0, out, "ERR OUT ", 0);
296     exit (1);
297     }
298     if (memcmp (F1->val, F2->val, F1->len)) {
299     printf ("ERR val %d mismatch\n", j);
300     log_rec (0, in, "ERR IN ", 0);
301     log_rec (0, out, "ERR OUT ", 0);
302     exit (1);
303     }
304     ++j;
305     ++F1;
306     }
307     }
308    
309     int loop (CliChnl *ch, Rec *demo, int fail) {
310     Rec *rsp;
311     int rt;
312     rt = cliWrite (ch, demo);
313     if (0 > rt) {
314     printf ("%s write %d %s\n", (fail ? "ERR":"WARN"),
315     ch->err, strerror (ch->err));
316     if (!fail) {
317     return -1;
318     }
319     exit (1);
320     }
321     rsp = cliRead (ch);
322     if (! rsp) {
323     printf ("%s read %d %s\n", (fail ? "ERR":"WARN"),
324     ch->err, strerror (ch->err));
325     if (!fail) {
326     return -1;
327     }
328     exit (1);
329     }
330     cmp (demo, rsp);
331     mFree (rsp);
332     return 0;
333     }
334    
335     int main (int argc, char **argv) {
336     CliChnl ch;
337     char *hname = 0;
338     int port = 0;
339     Rec *demo = 0;
340     int num = 0;
341     int j;
342    
343     for (j = 1; argc > j; ++j) {
344     if (*argv[j] == '-') {
345     if (argv[j][1] == 'h') {
346     hname = argv[j] + 2;
347     continue;
348     }
349     if (argv[j][1] == 'p') {
350     port = atoi (argv[j] + 2);
351     continue;
352     }
353     }
354     num = atoi (argv[j]);
355     break;
356     }
357    
358     if (0 >= num) {
359     num = 1;
360     }
361    
362     for (j = argc; 0 <= --j; ) {
363     RADDS (demo, j, argv[j], !0);
364     }
365    
366     if (0 >= port) {
367     port = 8080;
368     }
369     if (cliConnect (&ch, hname, port)) {
370     printf ("ERR connect %d %s\n", ch.err, strerror (ch.err));
371     exit (1);
372     }
373    
374     j = num;
375     while (1) {
376     if (loop (&ch, demo, 0)) {
377     sleep (15);
378     if (cliConnect (&ch, hname, port)) {
379     printf ("ERR reconnect %d %s\n", ch.err, strerror (ch.err));
380     exit (1);
381     }
382     loop (&ch, demo, !0);
383     }
384     if (! --j) {
385     break;
386     }
387     if (! (j % 10)) {
388     printf ("loop %d ...\n", j);
389     }
390     }
391    
392     cliClose (&ch);
393     printf ("ok.\n");
394     return 0;
395     }
396    
397     #endif /* _MAIN_ */
398    

  ViewVC Help
Powered by ViewVC 1.1.26