3c0e9457f52001ebb10429fccb9eed66f3bbec1e
[yaz-moved-to-github.git] / src / nanohttp.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2009 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file 
7  * \brief Small HTTP server
8  */
9
10 #include <yaz/zgdu.h>
11 #include <yaz/comstack.h>
12 #include <yaz/nmem.h>
13 #include <yaz/log.h>
14 #include <yaz/poll.h>
15 #include <assert.h>
16
17 typedef struct yaz_nano_srv_s *yaz_nano_srv_t;
18 typedef struct yaz_nano_pkg_s *yaz_nano_pkg_t;
19
20 struct yaz_nano_pkg_s {
21     void *handle;
22     int listener_id;
23     ODR encode_odr;
24     Z_GDU *request_gdu;
25     Z_GDU *response_gdu;
26 };
27
28 struct yaz_nano_srv_s {
29     COMSTACK *cs_listeners;
30     size_t num_listeners;
31     NMEM nmem;
32     struct yaz_poll_fd *fds;
33 };
34
35 void yaz_nano_srv_destroy(yaz_nano_srv_t p)
36 {
37     if (p)
38     {
39         size_t i;
40         for (i = 0; i < p->num_listeners; i++)
41             if (p->cs_listeners[i])
42                 cs_close(p->cs_listeners[i]);
43         nmem_destroy(p->nmem);
44     }
45 }
46
47 yaz_nano_srv_t yaz_nano_srv_create(const char **listeners_str)
48 {
49     NMEM nmem = nmem_create();
50     yaz_nano_srv_t p = nmem_malloc(nmem, sizeof(*p));
51     size_t i;
52     for (i = 0; listeners_str[i]; i++)
53         ;
54     p->nmem = nmem;
55     p->chan_list = 0;
56     p->free_list = 0;
57     p->num_listeners = i;
58     p->cs_listeners = 
59         nmem_malloc(nmem, p->num_listeners * sizeof(*p->cs_listeners));
60     for (i = 0; i < p->num_listeners; i++)
61     {
62         void *ap;
63         const char *where = listeners_str[i];
64         COMSTACK l = cs_create_host(where, 2, &ap);
65         p->cs_listeners[i] = 0; /* not OK (yet) */
66         if (!l)
67         {
68             yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_create_host(%s) failed", where);
69         }
70         else
71         {
72             if (cs_bind(l, ap, CS_SERVER) < 0)
73             {
74                 if (cs_errno(l) == CSYSERR)
75                     yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to bind to %s", where);
76                 else
77                     yaz_log(YLOG_FATAL, "Failed to bind to %s: %s", where,
78                             cs_strerror(l));
79                 cs_close(l);
80             }
81             else
82                 p->cs_listeners[i] = l; /* success */
83         }
84     }
85     /* check if all are OK */
86     for (i = 0; i < p->num_listeners; i++)
87         if (!p->cs_listeners[i])
88         {
89             yaz_nano_srv_destroy(p);
90             return 0;
91         }
92
93     for (i = 0; i < p->num_listeners; i++)
94     {
95         struct socket_chan *chan = 
96             socket_chan_new(p, cs_fileno(p->cs_listeners[i]),
97                 p->cs_listeners + i);
98         socket_chan_set_mask(chan, yaz_poll_read | yaz_poll_except);
99     }    
100     return p;
101 }
102
103 Z_GDU *yaz_nano_pkg_req(yaz_nano_pkg_t pkg)
104 {
105     return pkg->request_gdu;
106 }
107
108 Z_GDU *yaz_nano_pkg_response(yaz_nano_pkg_t pkg)
109 {
110     return pkg->response_gdu;
111 }
112
113 ODR yaz_nano_pkg_encode(yaz_nano_pkg_t pkg)
114 {
115     return pkg->encode_odr;
116 }
117
118 int yaz_nano_pkg_listener_id(yaz_nano_pkg_t pkg)
119 {
120     return pkg->listener_id;
121 }
122
123 yaz_nano_pkg_t yaz_nano_srv_get_pkg(yaz_nano_srv_t p)
124 {
125     size_t i;
126     int ret;
127     int num_fds = 0;
128     struct yaz_poll_fd *fds;
129     struct socket_chan *chan = p->chan_list;
130     for (chan = p->chan_list; chan; chan = chan->next)
131         num_fds++;
132     fds = xmalloc(num_fds * sizeof(*fds));
133     for (i = 0, chan = p->chan_list; chan; chan = chan->next)
134     {
135         fds[i].input_mask = chan->mask;
136         fds[i].fd = chan->fd;
137         fds[i].client_data = chan;
138     }
139     ret = yaz_poll(fds, num_fds, 0, 0);
140     if (ret == -1)
141     {
142         yaz_log(YLOG_WARN, "yaz_poll error");
143     }
144     else if (ret == 0)
145     {
146         yaz_log(YLOG_LOG, "yaz_poll timeout");
147     }
148     else
149     {
150         for (i = 0, chan = p->chan_list; chan; chan = chan->next)
151         {
152             if (fds[i].output_mask)
153             {
154                 yaz_log(YLOG_LOG, "event on chan=%p", chan);
155             }
156         }
157     }
158     xfree(fds);
159     return 0;
160 }
161
162 void yaz_nano_srv_put_pkg(yaz_nano_srv_t p, yaz_nano_pkg_t pkg)
163 {
164
165 }
166
167 /*
168  * Local variables:
169  * c-basic-offset: 4
170  * c-file-style: "Stroustrup"
171  * indent-tabs-mode: nil
172  * End:
173  * vim: shiftwidth=4 tabstop=8 expandtab
174  */
175