From 6d35f7e470b8eb2a8024deb9e343582e20292de5 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 10 Feb 2012 02:06:46 +0900 Subject: [PATCH] Added kqueue support in spdyd. --- configure.ac | 14 +++-- examples/EventPoll.h | 4 +- examples/EventPoll_kqueue.cc | 113 +++++++++++++++++++++++++++++++++++ examples/EventPoll_kqueue.h | 62 +++++++++++++++++++ examples/Makefile.am | 14 +++-- examples/spdylay_ssl.cc | 5 +- 6 files changed, 200 insertions(+), 12 deletions(-) create mode 100644 examples/EventPoll_kqueue.cc create mode 100644 examples/EventPoll_kqueue.h diff --git a/configure.ac b/configure.ac index 100104a8..61509a35 100644 --- a/configure.ac +++ b/configure.ac @@ -77,11 +77,6 @@ if test "x${have_cunit}" = "xyes"; then fi AM_CONDITIONAL([HAVE_CUNIT], [ test "x${have_cunit}" = "xyes" ]) -AX_HAVE_EPOLL([have_epoll=yes], [have_epoll=no]) -if test "x${have_epoll}" = "xyes"; then - AC_DEFINE([HAVE_EPOLL], [1], [Define to 1 if you have the `epoll`.]) -fi -AM_CONDITIONAL([HAVE_EPOLL], [ test "x${have_epoll}" = "xyes" ]) # openssl (for examples) PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.0.1]) @@ -114,6 +109,15 @@ AC_CHECK_FUNCS([ \ memset \ ]) +AX_HAVE_EPOLL([have_epoll=yes], [have_epoll=no]) +if test "x${have_epoll}" = "xyes"; then + AC_DEFINE([HAVE_EPOLL], [1], [Define to 1 if you have the `epoll`.]) +fi +AM_CONDITIONAL([HAVE_EPOLL], [ test "x${have_epoll}" = "xyes" ]) + +AC_CHECK_FUNCS([kqueue], [have_kqueue=yes]) +AM_CONDITIONAL([HAVE_KQUEUE], [test "x${have_kqueue}" = "xyes"]) + AC_CONFIG_FILES([ Makefile lib/Makefile diff --git a/examples/EventPoll.h b/examples/EventPoll.h index 8b6930de..7f1e5cba 100644 --- a/examples/EventPoll.h +++ b/examples/EventPoll.h @@ -31,6 +31,8 @@ #ifdef HAVE_EPOLL # include "EventPoll_epoll.h" -#endif // HAVE_EPOLL +#elif HAVE_KQUEUE +# include "EventPoll_kqueue.h" +#endif // HAVE_KQUEUE #endif // EVENT_POLL_H diff --git a/examples/EventPoll_kqueue.cc b/examples/EventPoll_kqueue.cc new file mode 100644 index 00000000..e95d73f9 --- /dev/null +++ b/examples/EventPoll_kqueue.cc @@ -0,0 +1,113 @@ +/* + * Spdylay - SPDY Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "EventPoll_kqueue.h" + +#include + +#include +#include + +namespace spdylay { + +EventPoll::EventPoll(size_t max_events) + : max_events_(max_events), num_events_(0) +{ + kq_ = kqueue(); + assert(kq_ != -1); + evlist_ = new struct kevent[max_events_]; +} + +EventPoll::~EventPoll() +{ + if(kq_ != -1) { + close(kq_); + } + delete [] evlist_; +} + +int EventPoll::poll(int timeout) +{ + timespec ts, *ts_ptr; + if(timeout == -1) { + ts_ptr = 0; + } else { + ts.tv_sec = timeout/1000; + ts.tv_nsec = (timeout%1000)*1000000; + ts_ptr = &ts; + } + num_events_ = 0; + int n; + while((n = kevent(kq_, evlist_, 0, evlist_, max_events_, ts_ptr)) == -1 && + errno == EINTR); + if(n > 0) { + num_events_ = n; + } + return n; +} + +int EventPoll::get_num_events() +{ + return num_events_; +} + +void* EventPoll::get_user_data(size_t p) +{ + return evlist_[p].udata; +} + +int EventPoll::get_events(size_t p) +{ + int events = 0; + short filter = evlist_[p].filter; + if(filter == EVFILT_READ) { + events |= EP_POLLIN; + } + if(filter == EVFILT_WRITE) { + events |= EP_POLLOUT; + } + return events; +} + +namespace { +int update_event(int kq, int fd, int events, void *user_data) +{ + struct kevent changelist[2]; + EV_SET(&changelist[0], fd, EVFILT_READ, + EV_ADD | ((events & EP_POLLIN) ? EV_ENABLE : EV_DISABLE), + 0, 0, user_data); + EV_SET(&changelist[1], fd, EVFILT_WRITE, + EV_ADD | ((events & EP_POLLOUT) ? EV_ENABLE : EV_DISABLE), + 0, 0, user_data); + timespec ts = { 0, 0 }; + return kevent(kq, changelist, 2, changelist, 0, &ts); +} +} // namespace + +int EventPoll::ctl_event(int op, int fd, int events, void *user_data) +{ + return update_event(kq_, fd, events, user_data); +} + +} // namespace spdylay diff --git a/examples/EventPoll_kqueue.h b/examples/EventPoll_kqueue.h new file mode 100644 index 00000000..15138b8f --- /dev/null +++ b/examples/EventPoll_kqueue.h @@ -0,0 +1,62 @@ +/* + * Spdylay - SPDY Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef EVENT_POLL_KQUEUE_H +#define EVENT_POLL_KQUEUE_H + +#include + +#include +#include +#include + +#include "EventPollEvent.h" + +namespace spdylay { + +class EventPoll { +public: + EventPoll(size_t max_events); + ~EventPoll(); + // Returns 0 if this function succeeds, or -1. + // On success + int poll(int timeout); + // Returns number of events detected in previous call of poll(). + int get_num_events(); + // Returns events of p-eth event. + int get_events(size_t p); + // Returns user data of p-th event. + void* get_user_data(size_t p); + // Adds/Modifies event to watch. + int ctl_event(int op, int fd, int events, void *user_data); +private: + int kq_; + size_t max_events_; + struct kevent *evlist_; + size_t num_events_; +}; + +} // namespace spdylay + +#endif // EVENT_POLL_KQUEUE_H diff --git a/examples/Makefile.am b/examples/Makefile.am index 36ec1380..93cd6667 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -27,20 +27,24 @@ AM_CPPFLAGS = -I$(srcdir)/../lib/includes -I$(builddir)/../lib/includes \ AM_LDFLAGS = @OPENSSL_LIBS@ LDADD = $(top_builddir)/lib/libspdylay.la -bin_PROGRAMS = spdycat +bin_PROGRAMS = spdycat spdyd HELPER_OBJECTS = uri.cc util.cc spdylay_ssl.cc HELPER_HFILES = uri.h util.h spdylay_ssl.h spdycat_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} spdycat.cc -if HAVE_EPOLL - spdyd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} spdyd.cc EventPoll.h \ EventPollEvent.h +if HAVE_EPOLL + spdyd_SOURCES += EventPoll_epoll.cc EventPoll_epoll.h -bin_PROGRAMS += spdyd - endif # HAVE_EPOLL + +if HAVE_KQUEUE + +spdyd_SOURCES += EventPoll_kqueue.cc EventPoll_kqueue.h + +endif # HAVE_KQUEUE diff --git a/examples/spdylay_ssl.cc b/examples/spdylay_ssl.cc index 71345367..3e1ddc40 100644 --- a/examples/spdylay_ssl.cc +++ b/examples/spdylay_ssl.cc @@ -169,7 +169,10 @@ int make_listen_socket(uint16_t port) memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif // AI_ADDRCONFIG addrinfo *res, *rp; r = getaddrinfo(0, service, &hints, &res); if(r != 0) {