Working on epoll socket layer
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 4 Jan 2010 12:58:42 +0000 (13:58 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 4 Jan 2010 12:58:42 +0000 (13:58 +0100)
include/yaz/sock_man.h [new file with mode: 0644]
src/Makefile.am
src/nanohttp.c [new file with mode: 0644]
src/sock_man.c [new file with mode: 0644]

diff --git a/include/yaz/sock_man.h b/include/yaz/sock_man.h
new file mode 100644 (file)
index 0000000..75bc841
--- /dev/null
@@ -0,0 +1,66 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2009 Index Data.
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Index Data nor the names of its contributors
+ *       may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ * \brief socket manager
+ */
+#ifndef YAZ_SOCK_MAN_H
+#define YAZ_SOCK_MAN_H
+
+#include <stddef.h>
+#include <yaz/poll.h>
+
+YAZ_BEGIN_CDECL
+
+typedef struct yaz_sock_man_s *yaz_sock_man_t;
+typedef struct yaz_sock_chan_s *yaz_sock_chan_t;
+
+YAZ_EXPORT
+yaz_sock_man_t yaz_sock_man_new(void);
+
+YAZ_EXPORT
+void yaz_sock_man_destroy(yaz_sock_man_t man);
+
+YAZ_EXPORT
+yaz_sock_chan_t yaz_sock_chan_new(yaz_sock_man_t srv, int fd, void *data);
+
+YAZ_EXPORT
+void yaz_sock_chan_destroy(yaz_sock_man_t srv, yaz_sock_chan_t p);
+
+YAZ_END_CDECL
+
+#endif
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 032da2e..0eefdf0 100644 (file)
@@ -102,7 +102,8 @@ libyaz_la_SOURCES=version.c options.c log.c \
   record_conv.c retrieval.c elementset.c snprintf.c query-charset.c \
   copy_types.c match_glob.c poll.c daemon.c \
   iconv_encode_marc8.c iconv_encode_iso_8859_1.c iconv_encode_wchar.c \
-  iconv_decode_marc8.c iconv_decode_iso5426.c iconv_decode_danmarc.c sc.c
+  iconv_decode_marc8.c iconv_decode_iso5426.c iconv_decode_danmarc.c sc.c \
+  sock_man.c
 
 libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO)
 
diff --git a/src/nanohttp.c b/src/nanohttp.c
new file mode 100644 (file)
index 0000000..3c0e945
--- /dev/null
@@ -0,0 +1,175 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2009 Index Data
+ * See the file LICENSE for details.
+ */
+/**
+ * \file 
+ * \brief Small HTTP server
+ */
+
+#include <yaz/zgdu.h>
+#include <yaz/comstack.h>
+#include <yaz/nmem.h>
+#include <yaz/log.h>
+#include <yaz/poll.h>
+#include <assert.h>
+
+typedef struct yaz_nano_srv_s *yaz_nano_srv_t;
+typedef struct yaz_nano_pkg_s *yaz_nano_pkg_t;
+
+struct yaz_nano_pkg_s {
+    void *handle;
+    int listener_id;
+    ODR encode_odr;
+    Z_GDU *request_gdu;
+    Z_GDU *response_gdu;
+};
+
+struct yaz_nano_srv_s {
+    COMSTACK *cs_listeners;
+    size_t num_listeners;
+    NMEM nmem;
+    struct yaz_poll_fd *fds;
+};
+
+void yaz_nano_srv_destroy(yaz_nano_srv_t p)
+{
+    if (p)
+    {
+        size_t i;
+        for (i = 0; i < p->num_listeners; i++)
+            if (p->cs_listeners[i])
+                cs_close(p->cs_listeners[i]);
+        nmem_destroy(p->nmem);
+    }
+}
+
+yaz_nano_srv_t yaz_nano_srv_create(const char **listeners_str)
+{
+    NMEM nmem = nmem_create();
+    yaz_nano_srv_t p = nmem_malloc(nmem, sizeof(*p));
+    size_t i;
+    for (i = 0; listeners_str[i]; i++)
+        ;
+    p->nmem = nmem;
+    p->chan_list = 0;
+    p->free_list = 0;
+    p->num_listeners = i;
+    p->cs_listeners = 
+        nmem_malloc(nmem, p->num_listeners * sizeof(*p->cs_listeners));
+    for (i = 0; i < p->num_listeners; i++)
+    {
+        void *ap;
+        const char *where = listeners_str[i];
+        COMSTACK l = cs_create_host(where, 2, &ap);
+        p->cs_listeners[i] = 0; /* not OK (yet) */
+        if (!l)
+        {
+            yaz_log(YLOG_WARN|YLOG_ERRNO, "cs_create_host(%s) failed", where);
+        }
+        else
+        {
+            if (cs_bind(l, ap, CS_SERVER) < 0)
+            {
+                if (cs_errno(l) == CSYSERR)
+                    yaz_log(YLOG_FATAL|YLOG_ERRNO, "Failed to bind to %s", where);
+                else
+                    yaz_log(YLOG_FATAL, "Failed to bind to %s: %s", where,
+                            cs_strerror(l));
+                cs_close(l);
+            }
+            else
+                p->cs_listeners[i] = l; /* success */
+        }
+    }
+    /* check if all are OK */
+    for (i = 0; i < p->num_listeners; i++)
+        if (!p->cs_listeners[i])
+        {
+            yaz_nano_srv_destroy(p);
+            return 0;
+        }
+
+    for (i = 0; i < p->num_listeners; i++)
+    {
+        struct socket_chan *chan = 
+            socket_chan_new(p, cs_fileno(p->cs_listeners[i]),
+                p->cs_listeners + i);
+        socket_chan_set_mask(chan, yaz_poll_read | yaz_poll_except);
+    }    
+    return p;
+}
+
+Z_GDU *yaz_nano_pkg_req(yaz_nano_pkg_t pkg)
+{
+    return pkg->request_gdu;
+}
+
+Z_GDU *yaz_nano_pkg_response(yaz_nano_pkg_t pkg)
+{
+    return pkg->response_gdu;
+}
+
+ODR yaz_nano_pkg_encode(yaz_nano_pkg_t pkg)
+{
+    return pkg->encode_odr;
+}
+
+int yaz_nano_pkg_listener_id(yaz_nano_pkg_t pkg)
+{
+    return pkg->listener_id;
+}
+
+yaz_nano_pkg_t yaz_nano_srv_get_pkg(yaz_nano_srv_t p)
+{
+    size_t i;
+    int ret;
+    int num_fds = 0;
+    struct yaz_poll_fd *fds;
+    struct socket_chan *chan = p->chan_list;
+    for (chan = p->chan_list; chan; chan = chan->next)
+        num_fds++;
+    fds = xmalloc(num_fds * sizeof(*fds));
+    for (i = 0, chan = p->chan_list; chan; chan = chan->next)
+    {
+        fds[i].input_mask = chan->mask;
+        fds[i].fd = chan->fd;
+        fds[i].client_data = chan;
+    }
+    ret = yaz_poll(fds, num_fds, 0, 0);
+    if (ret == -1)
+    {
+        yaz_log(YLOG_WARN, "yaz_poll error");
+    }
+    else if (ret == 0)
+    {
+        yaz_log(YLOG_LOG, "yaz_poll timeout");
+    }
+    else
+    {
+        for (i = 0, chan = p->chan_list; chan; chan = chan->next)
+        {
+            if (fds[i].output_mask)
+            {
+                yaz_log(YLOG_LOG, "event on chan=%p", chan);
+            }
+        }
+    }
+    xfree(fds);
+    return 0;
+}
+
+void yaz_nano_srv_put_pkg(yaz_nano_srv_t p, yaz_nano_pkg_t pkg)
+{
+
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/src/sock_man.c b/src/sock_man.c
new file mode 100644 (file)
index 0000000..725a901
--- /dev/null
@@ -0,0 +1,122 @@
+
+#include <yaz/sock_man.h>
+#include <yaz/nmem.h>
+#include <assert.h>
+#include <sys/epoll.h>
+
+struct yaz_sock_man_s {
+    yaz_sock_chan_t chan_list;
+    yaz_sock_chan_t free_list;
+    NMEM nmem;
+    int epoll_handle;
+    int maxevents;
+    yaz_sock_chan_t *events;
+};
+
+struct yaz_sock_chan_s {
+    yaz_sock_chan_t next;
+    yaz_sock_chan_t prev;
+    int fd;
+    unsigned mask;
+    void *data;
+};
+
+yaz_sock_man_t yaz_sock_man_new(void)
+{
+    NMEM nmem = nmem_create();
+    yaz_sock_man_t man = nmem_malloc(nmem, sizeof(*man));
+    man->nmem = nmem;
+    man->chan_list = 0;
+    man->free_list = 0;
+    man->epoll_handle = epoll_create(100);
+    man->maxevents = 30;
+    man->events = nmem_malloc(nmem, man->maxevents * sizeof(*man->events));
+    if (man->epoll_handle == -1)
+    {
+        yaz_sock_man_destroy(man);
+        return 0;
+    }
+    return man;
+}
+
+void yaz_sock_man_destroy(yaz_sock_man_t man)
+{
+    if (man)
+    {
+        if (man->epoll_handle != -1)
+            close(man->epoll_handle);
+        assert(man->chan_list == 0);
+        nmem_destroy(man->nmem);
+    }
+}
+
+yaz_sock_chan_t yaz_sock_chan_new(yaz_sock_man_t srv, int fd, void *data)
+{
+    yaz_sock_chan_t p;
+    if (srv->free_list)
+    {
+        p = srv->free_list;
+        srv->free_list = p->next;
+    }
+    else
+        p = nmem_malloc(srv->nmem, sizeof(*p));
+    p->next = srv->chan_list;
+    if (p->next)
+        p->next->prev = p;
+    p->prev = 0;
+    srv->chan_list = p;
+
+    p->fd = fd;
+    p->mask = 0;
+    p->data = data;
+    return p;
+}
+
+void yaz_sock_chan_destroy(yaz_sock_man_t srv, yaz_sock_chan_t p)
+{
+    if (p->prev)
+        p->prev->next = p->next;
+    else
+    {
+        assert(srv->chan_list == p);
+        srv->chan_list = p->next;
+    }
+
+    if (p->next)
+        p->next->prev = p->prev;
+    
+    p->next = srv->free_list;
+    p->prev = 0;
+    srv->free_list = p;
+}
+
+yaz_sock_chan_t yaz_sock_man_wait(yaz_sock_man_t man)
+{
+    return 0;
+}
+
+void yaz_sock_chan_set_mask(yaz_sock_chan_t chan, unsigned mask)
+{
+    chan->mask = mask;
+}
+
+unsigned yaz_sock_get_mask(yaz_sock_chan_t chan)
+{
+    return chan->mask;
+}
+
+void *yaz_sock_chan_get_data(yaz_sock_chan_t chan)
+{
+    return chan->data;
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+