/[webpac]/trunk/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

Contents of /trunk/openisis/lcli.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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