Now we're pretty much set for nonblocking I/O.
[yaz-moved-to-github.git] / server / statserv.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: statserv.c,v $
7  * Revision 1.5  1995-03-15 08:37:45  quinn
8  * Now we're pretty much set for nonblocking I/O.
9  *
10  * Revision 1.4  1995/03/14  16:59:48  quinn
11  * Bug-fixes
12  *
13  * Revision 1.3  1995/03/14  11:30:15  quinn
14  * Works better now.
15  *
16  * Revision 1.2  1995/03/14  10:28:03  quinn
17  * More work on demo server.
18  *
19  * Revision 1.1  1995/03/10  18:22:45  quinn
20  * The rudiments of an asynchronous server.
21  *
22  */
23
24 /*
25  * Simple, static server. I wouldn't advise a static server unless you
26  * really have to, but it's great for debugging memory management.  :)
27  */
28
29 #include <stdio.h>
30
31 #include <options.h>
32 #include <eventl.h>
33 #include <session.h>
34 #include <eventl.h>
35 #include <comstack.h>
36 #include <tcpip.h>
37 #include <xmosi.h>
38
39 static char *me = "";
40
41 #define DEFAULT_LISTENER "tcp:localhost:9999"
42
43 /*
44  * handle incoming connect requests.
45  */
46 void listener(IOCHAN h, int event)
47 {
48     COMSTACK line = (COMSTACK) iochan_getdata(h);
49     association *newas;
50
51     if (event == EVENT_INPUT)
52     {
53         if (cs_listen(line, 0, 0) < 0)
54         {
55             if (cs_errno(line) == CSNODATA)
56                 return;
57             fprintf(stderr, "cs_listen failed.\n");
58             exit(1);
59         }
60         iochan_setevent(h, EVENT_OUTPUT);
61         iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */
62     }
63     else if (event == EVENT_OUTPUT)
64     {
65         COMSTACK new_line;
66         IOCHAN new_chan;
67
68         if (!(new_line = cs_accept(line)))
69         {
70             fprintf(stderr, "Accept failed.\n");
71             exit(1);
72         }
73         if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,
74             EVENT_INPUT)))
75         {
76             fprintf(stderr, "Failed to create iochan\n");
77             exit(1);
78         }
79         if (!(newas = create_association(new_chan, new_line)))
80         {
81             fprintf(stderr, "Failed to create new assoc.\n");
82             exit(1);
83         }
84         iochan_setdata(new_chan, newas);
85         iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset for listen */
86     }
87     else
88     {
89         fprintf(stderr, "Bad event on listener.\n");
90         exit(1);
91     }
92 }
93
94 /*
95  * Set up a listening endpoint, and give it to the event-handler.
96  */
97 void add_listener(char *where)
98 {
99     COMSTACK l;
100     CS_TYPE type;
101     char mode[100], addr[100];
102     void *ap;
103     IOCHAN lst;
104
105     fprintf(stderr, "Adding listener on %s\n", where);
106     if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2)
107     {
108         fprintf(stderr, "%s: Address format: ('tcp'|'osi')':'<address>.\n",
109             me);
110         exit(1);
111     }
112     if (!strcmp(mode, "tcp"))
113     {
114         if (!(ap = tcpip_strtoaddr(addr)))
115         {
116             fprintf(stderr, "Address resolution failed for TCP.\n");
117             exit(1);
118         }
119         type = tcpip_type;
120     }
121 #if 0
122     else if (!strcmp(mode, "osi"))
123     {
124         if (!(ap = mosi_strtoaddr(addr)))
125         {
126             fprintf(stderr, "Address resolution failed for TCP.\n");
127             exit(1);
128         }
129         type = mosi_type;
130     }
131 #endif
132     else
133     {
134         fprintf(stderr, "You must specify either 'osi:' or 'tcp:'.\n");
135         exit(1);
136     }
137     if (!(l = cs_create(type, 1)))
138     {
139         fprintf(stderr, "Failed to create listener\n");
140         exit(1);
141     }
142     if (cs_bind(l, ap, CS_SERVER) < 0)
143     {
144         fprintf(stderr, "Failed to bind.\n");
145         perror(where);
146         exit(1);
147     }
148     if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT |
149          EVENT_EXCEPT)))
150     {
151         fprintf(stderr, "Failed to create IOCHAN-type\n");
152         exit(1);
153     }
154     iochan_setdata(lst, l);
155 }
156
157 int main(int argc, char **argv)
158 {
159     int ret, listeners = 0;
160     char *arg;
161
162     me = argv[0];
163     while ((ret = options("l:", argv, argc, &arg)) != -2)
164         switch (ret)
165         {
166             case 0: me = arg; break;
167             case 'l': add_listener(arg); listeners++; break;
168             default:
169                 fprintf(stderr, "Usage: %s [-l <listener-addr>]\n", me);
170                 exit(1);
171         }
172     if (!listeners)
173         add_listener(DEFAULT_LISTENER);
174     return event_loop();
175 }