New function p_query_attset to define default attribute set.
[yaz-moved-to-github.git] / comstack / xmosi.c
1 /*
2  * Copyright (c) 1995, Index Data
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: xmosi.c,v $
7  * Revision 1.14  1996-07-26 12:34:07  quinn
8  * Porting.
9  *
10  * Revision 1.13  1996/07/06  19:58:30  quinn
11  * System headerfiles gathered in yconfig
12  *
13  * Revision 1.12  1996/05/22  08:34:44  adam
14  * Added ifdef USE_XTIMOSI; so that 'make depend' works.
15  *
16  * Revision 1.11  1996/02/23 10:00:41  quinn
17  * WAIS Work
18  *
19  * Revision 1.10  1996/02/10  12:23:13  quinn
20  * Enablie inetd operations fro TCP/IP stack
21  *
22  * Revision 1.9  1996/01/02  08:57:28  quinn
23  * Changed enums in the ASN.1 .h files to #defines. Changed oident.class to oclass
24  *
25  * Revision 1.8  1995/11/01  13:54:29  quinn
26  * Minor adjustments
27  *
28  * Revision 1.7  1995/10/30  12:41:17  quinn
29  * Added hostname lookup for server.
30  *
31  * Revision 1.6  1995/09/29  17:12:00  quinn
32  * Smallish
33  *
34  * Revision 1.5  1995/09/28  10:24:32  quinn
35  * Windows changes
36  *
37  * Revision 1.4  1995/09/27  15:02:45  quinn
38  * Modified function heads & prototypes.
39  *
40  * Revision 1.3  1995/06/16  10:30:38  quinn
41  * Added REUSEADDR.
42  *
43  * Revision 1.2  1995/06/15  12:30:07  quinn
44  * Added @ as hostname alias for INADDR ANY.
45  *
46  * Revision 1.1  1995/06/14  09:58:20  quinn
47  * Renamed yazlib to comstack.
48  *
49  * Revision 1.15  1995/05/29  08:12:33  quinn
50  * Updates to aynch. operations.
51  *
52  * Revision 1.14  1995/05/16  09:37:31  quinn
53  * Fixed bug
54  *
55  * Revision 1.13  1995/05/16  08:51:19  quinn
56  * License, documentation, and memory fixes
57  *
58  * Revision 1.12  1995/05/02  08:53:24  quinn
59  * Trying in vain to fix comm with ISODE
60  *
61  * Revision 1.11  1995/04/21  16:32:08  quinn
62  * *** empty log message ***
63  *
64  * Revision 1.10  1995/03/27  08:36:14  quinn
65  * Some work on nonblocking operation in xmosi.c and rfct.c.
66  * Added protocol parameter to cs_create()
67  *
68  * Revision 1.9  1995/03/20  09:47:23  quinn
69  * Added server-side support to xmosi.c
70  * Fixed possible problems in rfct
71  * Other little mods
72  *
73  * Revision 1.8  1995/03/16  13:29:30  quinn
74  * Beginning to add server-side functions
75  *
76  * Revision 1.7  1995/03/14  10:28:47  quinn
77  * Adding server-side support to tcpip.c and fixing bugs in nonblocking I/O
78  *
79  * Revision 1.6  1995/03/09  15:22:43  quinn
80  * Fixed two bugs in get/rcv
81  *
82  * Revision 1.5  1995/03/07  16:29:47  quinn
83  * Various fixes.
84  *
85  * Revision 1.4  1995/03/07  10:26:56  quinn
86  * Initialized type field in the comstacks.
87  *
88  * Revision 1.3  1995/03/06  16:48:03  quinn
89  * Smallish changes.
90  *
91  * Revision 1.2  1995/03/06  10:54:41  quinn
92  * Server-side functions (t_bind/t_listen/t_accept) seem to work ok, now.
93  * Nonblocking mode needs work (and testing!)
94  * Added makensap to replace function in mosiutil.c.
95  *
96  * Revision 1.1  1995/03/01  08:40:33  quinn
97  * First working version of rfct. Addressing needs work.
98  *
99  */
100
101 #ifdef USE_XTIMOSI
102 /*
103  * Glue layer for Peter Furniss' xtimosi package.
104  */
105
106 #include <fcntl.h>
107 #include <stdlib.h>
108 #include <string.h>
109 #include <assert.h>
110
111 <<<<<<< 1.13
112 #include <sys/types.h>
113 #include <sys/socket.h>
114 #include <netdb.h>
115 #include <netinet/in.h>
116 #include <arpa/inet.h>
117 =======
118 #define YNETINCLUDE
119 #include <yconfig.h>
120 >>>>>>> /tmp/T4a00144
121
122 #include <comstack.h>
123 #include <xmosi.h>
124
125 #include <oid.h>
126
127 int mosi_connect(COMSTACK h, void *address);
128 int mosi_get(COMSTACK h, char **buf, int *bufsize);
129 int mosi_put(COMSTACK h, char *buf, int size);
130 int mosi_more(COMSTACK h) { return 0; } /* not correct */
131 int mosi_close(COMSTACK h);
132 int mosi_rcvconnect(COMSTACK h);
133 int mosi_bind(COMSTACK h, void *address, int mode);
134 int mosi_listen(COMSTACK h, char *addrp, int *addrlen);
135 COMSTACK mosi_accept(COMSTACK h);
136 char *mosi_addrstr(COMSTACK h);
137
138 typedef struct mosi_state
139 {
140     struct t_info info;        /* data returned by t_open */
141     struct t_call *call;
142     int hasread;               /* how many bytes read of current PDU */
143     int haswrit;               /* how many bytes have we written */
144 } mosi_state;
145
146 static char *oidtostr(int *o)
147 {
148     static char buf[512];
149
150     buf[0] = '\0';
151     while (*o >= 0)
152     {
153         sprintf(buf + strlen(buf), "%d", *o);
154         if (*(++o) >= 0)
155             strcat(buf, " ");
156     }
157     return buf;
158 }
159
160 static int addopt(struct netbuf *optbuf, unsigned long level, unsigned long
161     name, enum oid_proto proto, enum oid_class class, enum oid_value value)
162 {
163     int *oid;
164     oident ent;
165     char *str;
166
167     ent.proto = proto;
168     ent.oclass = class;
169     ent.value = value;
170     if (!(oid = oid_getoidbyent(&ent)))
171         return -1;
172     str = oidtostr(oid);
173     if (addoidoption(optbuf, level, name, str) < 0)
174         return -1;
175     return 0;
176 }
177
178 COMSTACK mosi_type(int s, int blocking, int protocol)
179 {
180     COMSTACK r;
181     mosi_state *state;
182     int flags = O_RDWR;
183
184     if (s >= 0)
185         return 0;
186
187     if (!(r = xmalloc(sizeof(*r))))
188         return 0;
189     if (!(state = r->private = xmalloc(sizeof(*state))))
190         return 0;
191
192     state->call = 0;
193     state->hasread = 0;
194     state->haswrit = 0;
195     r->protocol = protocol;
196     r->state = CS_UNBND;
197     r->type = mosi_type;
198     r->blocking = blocking;
199     r->f_connect = mosi_connect;
200     r->f_put = mosi_put;
201     r->f_get = mosi_get;
202     r->f_close = mosi_close;
203     r->f_more = mosi_more;
204     r->f_rcvconnect = mosi_rcvconnect;
205     r->f_bind = mosi_bind;
206     r->f_listen = mosi_listen;
207     r->f_accept = mosi_accept;
208     r->f_addrstr = mosi_addrstr;
209
210     if (!blocking)
211         flags |= O_NONBLOCK;
212     if ((r->iofile = u_open(CO_MOSI_NAME, flags, &state->info)) < 0)
213         return 0;
214
215     r->timeout = COMSTACK_DEFAULT_TIMEOUT;
216
217     return r;
218 }
219
220 int hex2oct(char *hex, char *oct)
221 {
222     int len = 0;
223     unsigned val;
224
225     while (sscanf(hex, "%2x", &val) == 1)
226     {
227         if (strlen(hex) < 2)
228             return -1;
229         *((unsigned char*) oct++) = (unsigned char) val;
230         len++;
231         hex += 2;
232     }
233     return len;
234 }
235
236 /*
237  * addressing specific to our hack of OSI transport. A sockaddr_in wrapped
238  * up in a t_mosiaddr in a netbuf (on a stick).
239  */
240 struct netbuf MDF *mosi_strtoaddr(const char *str)
241 {
242     struct netbuf *ret = xmalloc(sizeof(struct netbuf));
243     struct sockaddr_in *add = xmalloc(sizeof(struct sockaddr_in));
244     struct t_mosiaddr *mosiaddr = xmalloc(sizeof(struct t_mosiaddr));
245     struct hostent *hp;
246     char *p, *b, buf[512], *nsap;
247     short int port = 102;
248     unsigned long tmpadd;
249     int ll = 0;
250
251     assert(ret && add && mosiaddr);
252 #if 0
253     mosiaddr->osi_ap_inv_id = NO_INVOKEID;
254     mosiaddr->osi_ae_inv_id = NO_INVOKEID;
255 #endif
256     mosiaddr->osi_apt_len = 0;
257     mosiaddr->osi_aeq_len = 0;
258     p = (char*)MOSI_PADDR(mosiaddr);
259     *(p++) = 0; /* No presentation selector */
260     ll++;
261     *(p++) = 0; /* no session selector */
262     ll++;
263     /* do we have a transport selector? */
264     strcpy(buf, str);
265     if ((nsap = strchr(buf, '/')))
266     {
267         *(nsap++) = '\0';
268         if ((*p = hex2oct(buf, p + 1)) < 0)
269             return 0;
270         ll += *p + 1;
271         p += *p + 1;
272     }
273     else
274     {
275         nsap = buf;
276         *(p++) = 0;
277         ll++;
278     }
279     if (nsap && *nsap)
280     {
281         add->sin_family = AF_INET;
282         strcpy(buf, nsap);
283         if ((b = strchr(buf, ':')))
284         {
285             *b = 0;
286             port = atoi(b + 1);
287         }
288         add->sin_port = htons(port);
289         if (!strcmp("@", buf))
290             add->sin_addr.s_addr = INADDR_ANY;
291         else if ((hp = gethostbyname(buf)))
292             memcpy(&add->sin_addr.s_addr, *hp->h_addr_list, sizeof(struct in_addr));
293         else if ((tmpadd = inet_addr(buf)) != 0)
294             memcpy(&add->sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
295         else
296             return 0;
297         *(p++) = (char) sizeof(*add);
298         ll++;
299         memcpy(p, add, sizeof(*add));
300         ll += sizeof(*add);
301     }
302     else
303     {
304         *(p++) = 0;
305         ll++;
306     }
307     mosiaddr->osi_paddr_len = ll;
308     ret->buf = (char*)mosiaddr;
309     ret->len = ret->maxlen = 100 /* sizeof(*mosiaddr) */ ;
310
311     return ret;
312 }
313
314 int mosi_connect(COMSTACK h, void *address)
315 {
316     struct netbuf *addr = address, *local;
317     struct t_call *snd, *rcv;
318     struct t_bind bnd;
319
320     if (!(snd = (struct t_call *) u_alloc(h->iofile, T_CALL, T_ALL)))
321         return -1;
322     if (!(rcv = (struct t_call *) u_alloc(h->iofile, T_CALL, T_ALL)))
323         return -1;
324
325     snd->udata.len = 0;
326     if (addopt(&snd->opt, ISO_APCO, AP_CNTX_NAME, h->protocol, CLASS_APPCTX,
327         VAL_BASIC_CTX) < 0)
328         return -1;
329     if (addopt(&snd->opt, ISO_APCO, AP_ABS_SYN, h->protocol, CLASS_ABSYN,
330         VAL_APDU) < 0)
331         return -1;
332     /*
333      * We don't specify record formats yet.
334      *
335      * Xtimosi adds the oid for BER as transfer syntax automatically.
336      */
337
338     bnd.qlen = 0;
339
340     if (h->state == CS_UNBND)
341     {
342         local = mosi_strtoaddr("");   /* not good in long run */
343         memcpy(&bnd.addr, local, sizeof(*local));
344         if (u_bind(h->iofile, &bnd, 0) < 0)
345             return -1;
346     }
347
348     memcpy(&snd->addr, addr, sizeof(*addr));
349     if (u_connect(h->iofile, snd, rcv) < 0)
350     {
351         if (t_errno == TNODATA)
352             return 1;
353         return -1; 
354     }
355     return 0;
356 }
357
358 int mosi_rcvconnect(COMSTACK h)
359 {
360     if (u_rcvconnect(h->iofile, 0) < 0)
361     {
362         if (t_errno == TNODATA)
363             return 1;
364         return -1;
365     }
366     return 0;
367 }
368
369 int mosi_bind(COMSTACK h, void *address, int mode)
370 {
371     int res;
372     struct t_bind bnd;
373     int one = 1;
374
375     if (setsockopt(h->iofile, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
376     {
377         h->cerrno = CSYSERR;
378         return -1;
379     }
380     if (mode == CS_SERVER)
381         bnd.qlen = 3;
382     else
383         bnd.qlen = 0;
384     memcpy(&bnd.addr, address, sizeof(struct netbuf));
385     if ((res = u_bind(h->iofile, &bnd, 0)) < 0)
386         return -1;
387     h->state = CS_IDLE;
388     return 0;
389 }
390
391 int mosi_listen(COMSTACK h, char *addp, int *addrlen)
392 {
393     int res;
394     mosi_state *st = h->private;
395
396     if (!(st->call = (struct t_call*) t_alloc(h->iofile, T_CALL_STR,
397          T_ALL)))
398         return -1;
399     if ((res = u_listen(h->iofile, st->call)) < 0)
400     {
401         if (t_errno == TNODATA)
402             return 1;
403         return -1;
404     }
405     h->state = CS_INCON;
406     return 0;
407 }
408
409 COMSTACK mosi_accept(COMSTACK h)
410 {
411     COMSTACK new;
412     void *local;
413     struct mosi_state *st = h->private, *ns;
414     int flags = O_RDWR;
415
416     if (h->state != CS_INCON)
417     {
418         h->cerrno = CSOUTSTATE;
419         return 0;
420     }
421     if (!(new = xmalloc(sizeof(*new))))
422         return 0;
423     *new = *h;
424     if (!(new->private = ns = xmalloc(sizeof(*ns))))
425         return 0;
426     *ns = *st;
427     if (!h->blocking)
428         flags |= O_NONBLOCK;
429     if ((new->iofile = u_open_r(CO_MOSI_NAME, flags, &st->info, st->call)) < 0)
430         return 0;
431     if (!(local = mosi_strtoaddr("")))
432         return 0;
433     if (mosi_bind(new, local, CS_CLIENT) < 0) /* CS_CLIENT: qlen == 0 */
434         return 0;
435     memcpy(&st->call->addr, local, sizeof(st->call->addr));
436     if (u_accept(h->iofile, new->iofile, st->call) < 0)
437     {
438         mosi_close(new);
439         return 0;
440     }
441     return new;
442 }
443
444 #define CS_MOSI_BUFCHUNK 4096
445
446 int mosi_get(COMSTACK h, char **buf, int *bufsize)
447 {
448     int flags = 0, res;
449     mosi_state *ct = h->private;
450     int got;
451
452     do
453     {
454         if (!*bufsize)
455         {
456             if (!(*buf = xmalloc(*bufsize = CS_MOSI_BUFCHUNK)))
457                 return -1;
458         }
459         else if (*bufsize - ct->hasread < CS_MOSI_BUFCHUNK)
460             if (!(*buf =xrealloc(*buf, *bufsize *= 2)))
461                 return -1;
462
463         if ((res = u_rcv(h->iofile, *buf + ct->hasread, CS_MOSI_BUFCHUNK,
464             &flags)) <= 0)
465         {
466             if (t_errno == TNODATA)
467                 return 1;
468             return -1;
469         }
470         ct->hasread += res;
471     }
472     while (flags & T_MORE);
473
474     /* all done. Reset hasread */
475     got = ct->hasread;
476     ct->hasread = 0;  
477     return got;
478 }
479
480 int mosi_put(COMSTACK h, char *buf, int size)
481 {
482     mosi_state *ct = h->private;
483     int res = u_snd(h->iofile, buf + ct->haswrit, size - ct->haswrit, 0);
484
485     if (res == size - ct->haswrit)
486     {
487         ct->haswrit = 0;
488         return 0;
489     }
490     else if (res < 0)
491     {
492         if (t_errno == TFLOW)
493             return 1;
494         return -1;
495     }
496     ct->haswrit += res;
497     return 1;
498 }
499
500 int mosi_close(COMSTACK h)
501 {
502     xfree(h->private);
503     if (h->iofile >= 0)
504         u_close(h->iofile);
505    xfree(h);
506     return 0;
507 }    
508
509 char *mosi_addrstr(COMSTACK h)
510 {
511     return "osi:[UNIMPLEMENTED]";
512 }
513
514 #endif