summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile37
-rw-r--r--httpd/Makefile35
-rw-r--r--httpd/dispatcher.cpp109
-rw-r--r--httpd/job.cpp240
-rw-r--r--httpd/listener.cpp167
-rw-r--r--httpd/poller.cpp190
-rw-r--r--httpd/regex.cpp175
-rw-r--r--httpd/tnt/dispatcher.h121
-rw-r--r--httpd/tnt/gcryptinit.h37
-rw-r--r--httpd/tnt/gnutls.h146
-rw-r--r--httpd/tnt/job.h201
-rw-r--r--httpd/tnt/listener.h78
-rw-r--r--httpd/tnt/openssl.h121
-rw-r--r--httpd/tnt/poller.h61
-rw-r--r--httpd/tnt/regex.h79
-rw-r--r--httpd/tnt/ssl.h52
-rw-r--r--httpd/tnt/tntnet.h99
-rw-r--r--httpd/tnt/worker.h91
-rw-r--r--httpd/tntnet.cpp832
-rw-r--r--httpd/worker.cpp364
20 files changed, 2 insertions, 3233 deletions
diff --git a/Makefile b/Makefile
index 44a88ce..84e8b23 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
#
-# Makefile for a Video Disk Recorder plugin
+# Makefile for the 'LIVE' Video Disk Recorder plugin
#
# The official name of this plugin.
@@ -64,18 +64,8 @@ PACKAGE = vdr-$(ARCHIVE)
SOFILE = libvdr-$(PLUGIN).so
### Includes and Defines (add further entries here):
-ifneq ($(TNTVERS7),yes)
- INCLUDES += -Ihttpd
- LIBS += httpd/libhttpd.a
-endif
-
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -DTNTVERSION=$(TNTVERSION) -DCXXTOOLVER=$(CXXTOOLVER)
-
SUBDIRS = pages css javascript
-ifneq ($(TNTVERS7),yes)
- SUBDIRS += httpd
-endif
-
VERSIONSUFFIX = gen_version_suffix.h
### The object files (add further files here):
@@ -142,36 +132,13 @@ $(SOFILE): $(VERSIONSUFFIX) $(SUBDIRS) $(PLUGINOBJS)
for SUBDIR in $(SUBDIRS); \
do $(MAKE) -C $${SUBDIR} PLUGINFEATURES="$(PLUGINFEATURES)" all; \
done
- $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGINOBJS) -Wl,--whole-archive $(WEBLIBS) -Wl,--no-whole-archive $(LIBS) -o $@
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGINOBJS) -Wl,--whole-archive $(WEBLIBS) -Wl,--no-whole-archive $(LIBS) -o $@
install-lib: $(SOFILE)
install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
install: install-lib install-i18n
-ifneq ($(TNTVERS7),yes)
- @echo ""
- @echo "LIVE was built successfully and you can try to use it!"
- @echo ""
- @echo ""
- @echo ""
- @echo ""
- @echo "IMPORTANT INFORMATION:"
- @echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
- @echo "+ This is one of the *last* CVS versions of LIVE which will +"
- @echo "+ work with versions of tntnet *less* than 1.6.0.6! +"
- @echo "+ +"
- @echo "+ This version of LIVE already supports tntnet >= 1.6.0.6. +"
- @echo "+ +"
- @echo "+ Please upgrade tntnet to at least version 1.6.0.6 soon, if +"
- @echo "+ you want to keep track of bleeding edge LIVE development. +"
- @echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
- @echo ""
- @echo ""
- @echo ""
- @echo ""
-endif
-
dist: $(I18Npo) clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
diff --git a/httpd/Makefile b/httpd/Makefile
deleted file mode 100644
index d21eb2f..0000000
--- a/httpd/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-### The official name of this plugin.
-PLUGIN = live
-
-### Includes and Defines (add further entries here):
-INCLUDES += -I.
-
-### The object files (add further files here):
-OBJS = dispatcher.o job.o regex.o worker.o \
- listener.o poller.o tntnet.o
-
-### The main target:
-all: libhttpd.a
-
-### Implicit rules:
-
-%.o: %.cpp
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
-
-### Dependencies:
-MAKEDEP = $(CXX) -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): Makefile
- @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.cpp) > $@
-
--include $(DEPFILE)
-
-### Targets:
-libhttpd.a: $(OBJS)
- $(AR) r $@ $^
-
-clean:
- @rm -f *~ *.o core* libhttpd.a proctest $(DEPFILE)
-
-dist: clean
- @echo "Nothing to do for distribution here ..."
diff --git a/httpd/dispatcher.cpp b/httpd/dispatcher.cpp
deleted file mode 100644
index 8620e76..0000000
--- a/httpd/dispatcher.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/* dispatcher.cpp
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/dispatcher.h"
-#include <tnt/httperror.h>
-#include <functional>
-#include <iterator>
-#include <algorithm>
-#include <cxxtools/log.h>
-
-log_define("tntnet.dispatcher")
-
-namespace tnt
-{
-
-void Dispatcher::addUrlMapEntry(const std::string& url, const CompidentType& ci)
-{
- cxxtools::WrLock lock(rwlock);
-
- urlmap.push_back(urlmap_type::value_type(regex(url), ci));
-}
-
-Compident Dispatcher::mapComp(const std::string& compUrl) const
-{
- urlmap_type::const_iterator pos = urlmap.begin();
- return mapCompNext(compUrl, pos);
-}
-
-namespace {
- class regmatch_formatter : public std::unary_function<const std::string&, std::string>
- {
- public:
- regex_smatch what;
- std::string operator() (const std::string& s) const
- { return what.format(s); }
- };
-}
-
-Dispatcher::urlMapCacheType::size_type Dispatcher::maxUrlMapCache = 8192;
-
-Dispatcher::CompidentType Dispatcher::mapCompNext(const std::string& compUrl,
- Dispatcher::urlmap_type::const_iterator& pos) const
-{
- // check cache
- urlMapCacheType::key_type cacheKey = urlMapCacheType::key_type(compUrl, pos);
- urlMapCacheType::const_iterator um = urlMapCache.find(cacheKey);
- if (um != urlMapCache.end())
- return um->second;
-
- // no cache hit
- regmatch_formatter formatter;
-
- for (; pos != urlmap.end(); ++pos)
- {
- if (pos->first.match(compUrl, formatter.what))
- {
- const CompidentType& src = pos->second;
-
- CompidentType ci;
- ci.libname = formatter(src.libname);
- ci.compname = formatter(src.compname);
- if (src.hasPathInfo())
- ci.setPathInfo(formatter(src.getPathInfo()));
- std::transform(src.getArgs().begin(), src.getArgs().end(),
- std::back_inserter(ci.getArgsRef()), formatter);
-
- // clear cache after maxUrlMapCache distict requests
- if (urlMapCache.size() >= maxUrlMapCache)
- {
- log_warn("clear url-map-cache");
- urlMapCache.clear();
- }
-
- urlMapCache.insert(urlMapCacheType::value_type(cacheKey, ci));
-
- return ci;
- }
- }
-
- throw NotFoundException(compUrl);
-}
-
-Dispatcher::CompidentType Dispatcher::PosType::getNext()
-{
- if (first)
- first = false;
- else
- ++pos;
-
- return dis.mapCompNext(url, pos);
-}
-
-}
diff --git a/httpd/job.cpp b/httpd/job.cpp
deleted file mode 100644
index 49ecba6..0000000
--- a/httpd/job.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-/* job.cpp
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/job.h"
-#include <tnt/httpreply.h>
-#include <cxxtools/log.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-log_define("tntnet.job")
-
-namespace tnt
-{
- unsigned Job::socket_read_timeout = 200;
- unsigned Job::socket_write_timeout = 10000;
- unsigned Job::keepalive_max = 1000;
- unsigned Job::socket_buffer_size = 16384;
-
- Job::~Job()
- { }
-
- void Job::clear()
- {
- parser.reset();
- request.clear();
- touch();
- }
-
- int Job::msecToTimeout(time_t currentTime) const
- {
- return (lastAccessTime - currentTime + 1) * 1000
- + getKeepAliveTimeout()
- - getSocketReadTimeout();
- }
-
- unsigned Job::getKeepAliveTimeout()
- {
- return HttpReply::getKeepAliveTimeout();
- }
-
- ////////////////////////////////////////////////////////////////////////
- // Tcpjob
- //
- void Tcpjob::accept(const cxxtools::net::Server& listener)
- {
- log_debug("accept");
- socket.accept(listener);
-
- struct sockaddr_storage s = socket.getSockAddr();
- struct sockaddr_storage sockaddr;
- memcpy(&sockaddr, &s, sizeof(sockaddr));
-
- char buffer[INET6_ADDRSTRLEN];
- log_debug("connection accepted from "
- << inet_ntop(AF_INET6, &(socket.getPeeraddr()), buffer, sizeof(buffer)));
-
- getRequest().setPeerAddr(socket.getPeeraddr());
- getRequest().setServerAddr(sockaddr);
- getRequest().setSsl(false);
- }
-
- std::iostream& Tcpjob::getStream()
- {
- return socket;
- }
-
- int Tcpjob::getFd() const
- {
- return socket.getFd();
- }
-
- void Tcpjob::setRead()
- {
- socket.setTimeout(getSocketReadTimeout());
- }
-
- void Tcpjob::setWrite()
- {
- socket.setTimeout(getSocketWriteTimeout());
- }
-
-#ifdef USE_SSL
- ////////////////////////////////////////////////////////////////////////
- // SslTcpjob
- //
- void SslTcpjob::accept(const SslServer& listener)
- {
- log_debug("accept (ssl)");
- socket.accept(listener);
- log_debug("connection accepted (ssl)");
-
- struct sockaddr_storage s = socket.getSockAddr();
- struct sockaddr_storage sockaddr;
- memcpy(&sockaddr, &s, sizeof(sockaddr));
-
- getRequest().setPeerAddr(socket.getPeeraddr());
- getRequest().setServerAddr(sockaddr);
- getRequest().setSsl(true);
-
- setRead();
- }
-
- std::iostream& SslTcpjob::getStream()
- {
- return socket;
- }
-
- int SslTcpjob::getFd() const
- {
- return socket.getFd();
- }
-
- void SslTcpjob::setRead()
- {
- socket.setTimeout(getSocketReadTimeout());
- }
-
- void SslTcpjob::setWrite()
- {
- socket.setTimeout(getSocketWriteTimeout());
- }
-
-#endif // USE_SSL
-
-#ifdef USE_GNUTLS
- ////////////////////////////////////////////////////////////////////////
- // GnuTlsTcpjob
- //
- void GnuTlsTcpjob::accept(const GnuTlsServer& listener)
- {
- log_debug("accept (ssl)");
- socket.accept(listener);
- log_debug("connection accepted (ssl)");
-
- struct sockaddr_storage s = socket.getSockAddr();
- struct sockaddr_storage sockaddr;
- memcpy(&sockaddr, &s, sizeof(sockaddr));
-
- getRequest().setPeerAddr(socket.getPeeraddr());
- getRequest().setServerAddr(sockaddr);
- getRequest().setSsl(true);
-
- setRead();
- }
-
- std::iostream& GnuTlsTcpjob::getStream()
- {
- return socket;
- }
-
- int GnuTlsTcpjob::getFd() const
- {
- return socket.getFd();
- }
-
- void GnuTlsTcpjob::setRead()
- {
- socket.setTimeout(getSocketReadTimeout());
- }
-
- void GnuTlsTcpjob::setWrite()
- {
- socket.setTimeout(getSocketWriteTimeout());
- }
-
-#endif // USE_GNUTLS
-
- //////////////////////////////////////////////////////////////////////
- // Jobqueue
- //
- void Jobqueue::put(JobPtr j)
- {
- log_debug("Jobqueue::put");
- j->touch();
-
- cxxtools::MutexLock lock(mutex);
-
- if (capacity > 0)
- {
- while (jobs.size() >= capacity)
- {
- log_warn("Jobqueue full");
- notFull.wait(lock);
- }
- }
-
- jobs.push_back(j);
-
- if (waitThreads == 0)
- {
- log_info("no waiting threads left");
- noWaitThreads.signal();
- }
-
- notEmpty.signal();
- }
-
- Jobqueue::JobPtr Jobqueue::get()
- {
- // wait, until a job is available
- ++waitThreads;
-
- cxxtools::MutexLock lock(mutex);
- while (jobs.empty())
- notEmpty.wait(lock);
-
- --waitThreads;
-
- log_debug("Jobqueue: fetch job " << waitThreads << " waiting threads left");
-
- // take next job (queue is locked)
- JobPtr j = jobs.front();
- jobs.pop_front();
-
- // if there are more jobs, wake onther thread
- if (!jobs.empty())
- notEmpty.signal();
- notFull.signal();
-
- return j;
- }
-
-}
diff --git a/httpd/listener.cpp b/httpd/listener.cpp
deleted file mode 100644
index 57c334d..0000000
--- a/httpd/listener.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/* listener.cpp
- * Copyright (C) 2003 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/listener.h"
-#include "tnt/tntnet.h"
-#include <cxxtools/log.h>
-#include <errno.h>
-#include <unistd.h>
-
-#ifdef WITH_GNUTLS
-# include "tnt/gnutls.h"
-#endif
-
-#ifdef WITH_OPENSSL
-# include "tnt/openssl.h"
-#endif
-
-log_define("tntnet.listener")
-
-static void doListenRetry(cxxtools::net::Server& server,
- const char* ipaddr, unsigned short int port)
-{
- for (unsigned n = 1; true; ++n)
- {
- try
- {
- log_debug("listen " << ipaddr << ':' << port);
- server.listen(ipaddr, port, tnt::Listener::getBacklog());
- return;
- }
- catch (const cxxtools::net::Exception& e)
- {
- log_debug("cxxtools::net::Exception caught: errno=" << e.getErrno() << " msg=" << e.what());
- if (e.getErrno() != EADDRINUSE || n > tnt::Listener::getListenRetry())
- {
- log_debug("rethrow exception");
- throw;
- }
- log_warn("address " << ipaddr << ':' << port << " in use - retry; n = " << n);
- ::sleep(1);
- }
- }
-}
-
-namespace tnt
-{
- void ListenerBase::doStop()
- {
- log_warn("stop listener " << ipaddr << ':' << port);
- try
- {
- // connect once to wake up listener, so it will check stop-flag
- cxxtools::net::Stream(ipaddr, port);
- }
- catch (const std::exception& e)
- {
- log_warn("error waking up listener: " << e.what() << " try 127.0.0.1");
- cxxtools::net::Stream("127.0.0.1", port);
- }
- }
-
- int Listener::backlog = 16;
- unsigned Listener::listenRetry = 5;
-
- Listener::Listener(const std::string& ipaddr, unsigned short int port, Jobqueue& q)
- : ListenerBase(ipaddr, port),
- queue(q)
- {
- log_info("listen ip=" << ipaddr << " port=" << port);
- doListenRetry(server, ipaddr.c_str(), port);
- }
-
- void Listener::run()
- {
- // accept-loop
- log_debug("enter accept-loop");
- while (!Tntnet::shouldStop())
- {
- try
- {
- Tcpjob* j = new Tcpjob;
- Jobqueue::JobPtr p(j);
- j->accept(server);
- log_debug("connection accepted");
-
- if (Tntnet::shouldStop())
- break;
-
- queue.put(p);
- }
- catch (const std::exception& e)
- {
- log_error("error in accept-loop: " << e.what());
- }
- }
-
- log_debug("stop listener");
- }
-
-#ifdef WITH_GNUTLS
-#define USE_SSL
-
-#endif
-
-#ifdef WITH_OPENSSL
-#define USE_SSL
-
-#endif
-
-#ifdef USE_SSL
- Ssllistener::Ssllistener(const char* certificateFile,
- const char* keyFile,
- const std::string& ipaddr, unsigned short int port,
- Jobqueue& q)
- : ListenerBase(ipaddr, port),
- server(certificateFile, keyFile),
- queue(q)
- {
- log_info("listen ip=" << ipaddr << " port=" << port << " (ssl)");
- doListenRetry(server, ipaddr.c_str(), port);
- }
-
- void Ssllistener::run()
- {
- // accept-loop
- log_debug("enter accept-loop (ssl)");
- while (!Tntnet::shouldStop())
- {
- try
- {
- SslTcpjob* j = new SslTcpjob;
- Jobqueue::JobPtr p(j);
- j->accept(server);
-
- if (Tntnet::shouldStop())
- break;
-
- queue.put(p);
- }
- catch (const std::exception& e)
- {
- log_error("error in ssl-accept-loop: " << e.what());
- }
- }
-
- log_debug("stop ssl-listener");
- }
-
-#endif // USE_SSL
-
-}
diff --git a/httpd/poller.cpp b/httpd/poller.cpp
deleted file mode 100644
index c604f55..0000000
--- a/httpd/poller.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/* poller.cpp
- * Copyright (C) 2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/poller.h"
-#include "tnt/tntnet.h"
-#include <cxxtools/log.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-log_define("tntnet.poller")
-
-namespace tnt
-{
- Poller::Poller(Jobqueue& q)
- : queue(q),
- poll_timeout(-1)
- {
- pipe(notify_pipe);
- fcntl(notify_pipe[0], F_SETFL, O_NONBLOCK);
-
- pollfds.reserve(16);
- pollfds[0].fd = notify_pipe[0];
- pollfds[0].events = POLLIN;
- pollfds[0].revents = 0;
- }
-
- void Poller::append_new_jobs()
- {
- cxxtools::MutexLock lock(mutex);
- if (!new_jobs.empty())
- {
- // append new jobs to current
- log_debug("add " << new_jobs.size() << " new jobs to poll-list");
-
- pollfds.reserve(current_jobs.size() + new_jobs.size() + 1);
-
- time_t currentTime;
- time(&currentTime);
- for (jobs_type::iterator it = new_jobs.begin();
- it != new_jobs.end(); ++it)
- {
- append(*it);
- int msec;
- if (poll_timeout < 0)
- poll_timeout = (*it)->msecToTimeout(currentTime);
- else if ((msec = (*it)->msecToTimeout(currentTime)) < poll_timeout)
- poll_timeout = msec;
- }
-
- new_jobs.clear();
- }
- }
-
- void Poller::append(Jobqueue::JobPtr& job)
- {
- current_jobs.push_back(job);
-
- pollfd& p = *(pollfds.data() + current_jobs.size());
- p.fd = job->getFd();
- p.events = POLLIN;
- }
-
- void Poller::run()
- {
- while (!Tntnet::shouldStop())
- {
- append_new_jobs();
-
- try
- {
- log_debug("poll timeout=" << poll_timeout);
- ::poll(pollfds.data(), current_jobs.size() + 1, poll_timeout);
- if (Tntnet::shouldStop())
- {
- log_warn("stop poller");
- break;
- }
-
- poll_timeout = -1;
-
- if (pollfds[0].revents != 0)
- {
- log_debug("read notify-pipe");
- char ch;
- ::read(notify_pipe[0], &ch, 1);
- pollfds[0].revents = 0;
- }
-
- dispatch();
- }
- catch (const std::exception& e)
- {
- log_error("error in poll-loop: " << e.what());
- }
- }
- }
-
- void Poller::doStop()
- {
- log_debug("notify stop");
- char ch = 'A';
- ::write(notify_pipe[1], &ch, 1);
- }
-
- void Poller::dispatch()
- {
- log_debug("dispatch " << current_jobs.size() << " jobs");
-
- time_t currentTime;
- time(&currentTime);
- for (unsigned i = 0; i < current_jobs.size(); )
- {
- if (pollfds[i + 1].revents & POLLIN)
- {
- log_debug("job found " << pollfds[i + 1].fd);
-
- // put job into work-queue
- queue.put(current_jobs[i]);
- remove(i);
- }
- else if (pollfds[i + 1].revents != 0)
- {
- log_debug("pollevent " << std::hex << pollfds[i + 1].revents << " on fd " << pollfds[i + 1].fd);
- remove(i);
- }
- else
- {
- // check timeout
- int msec = current_jobs[i]->msecToTimeout(currentTime);
- if (msec <= 0)
- {
- log_debug("keep-alive-timeout reached");
- remove(i);
- }
- else if (poll_timeout < 0 || msec < poll_timeout)
- poll_timeout = msec;
-
- ++i;
- }
- }
- }
-
- void Poller::remove(jobs_type::size_type n)
- {
- // replace job with last job in poller-list
- jobs_type::size_type last = current_jobs.size() - 1;
-
- if (n != last)
- {
- pollfds[n + 1] = pollfds[last + 1];
- current_jobs[n] = current_jobs[last];
- }
-
- current_jobs.pop_back();
- }
-
- void Poller::addIdleJob(Jobqueue::JobPtr job)
- {
- log_debug("addIdleJob " << job->getFd());
-
- {
- cxxtools::MutexLock lock(mutex);
- new_jobs.push_back(job);
- }
-
- log_debug("notify " << job->getFd());
-
- char ch = 'A';
- ::write(notify_pipe[1], &ch, 1);
-
- log_debug("addIdleJob ready");
- }
-
-}
diff --git a/httpd/regex.cpp b/httpd/regex.cpp
deleted file mode 100644
index a9f52fc..0000000
--- a/httpd/regex.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/* regex.cpp
- * Copyright (C) 2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/regex.h"
-#include <stdexcept>
-#include <locale>
-
-namespace tnt
-{
- static inline bool isdigit(char ch)
- {
- return ch >= '0' && ch <= '9';
- }
-
- unsigned regex_smatch::size() const
- {
- unsigned n;
- for (n = 0; n < 10 && matchbuf[n].rm_so >= 0; ++n)
- ;
-
- return n;
- }
-
- std::string regex_smatch::get(unsigned n) const
- {
- return str.substr(matchbuf[n].rm_so, matchbuf[n].rm_eo - matchbuf[n].rm_so);
- }
-
- std::string regex_smatch::format(const std::string& s) const
- {
- enum state_type
- {
- state_0,
- state_esc,
- state_var0,
- state_var1,
- state_1
- } state;
-
- state = state_0;
- std::string ret;
-
- for (std::string::const_iterator it = s.begin(); it != s.end(); ++it)
- {
- char ch = *it;
-
- switch (state)
- {
- case state_0:
- if (ch == '$')
- state = state_var0;
- else if (ch == '\\')
- {
- ret = std::string(s.begin(), it);
- state = state_esc;
- }
- break;
-
- case state_esc:
- ret += ch;
- state = state_1;
- break;
-
- case state_var0:
- if (isdigit(ch))
- {
- ret = std::string(s.begin(), it - 1);
- regoff_t s = matchbuf[ch - '0'].rm_so;
- regoff_t e = matchbuf[ch - '0'].rm_eo;
- if (s >= 0 && e >= 0)
- ret.append(str, s, e-s);
- state = state_1;
- }
- else
- state = state_0;
- break;
-
- case state_1:
- if (ch == '$')
- state = state_var1;
- else if (state == '\\')
- state = state_esc;
- else
- ret += ch;
- break;
-
- case state_var1:
- if (isdigit(ch))
- {
- unsigned s = matchbuf[ch - '0'].rm_so;
- unsigned e = matchbuf[ch - '0'].rm_eo;
- if (s >= 0 && e >= 0)
- ret.append(str, s, e-s);
- state = state_1;
- }
- else if (ch == '$')
- ret += '$';
- else
- {
- ret += '$';
- ret += ch;
- }
- break;
- }
- }
-
- switch (state)
- {
- case state_0:
- case state_var0:
- return s;
-
- case state_esc:
- return ret + '\\';
-
- case state_var1:
- return ret + '$';
-
- case state_1:
- return ret;
- }
-
- return ret;
- }
-
- void regex::checkerr(int ret) const
- {
- if (ret != 0)
- {
- char errbuf[256];
- regerror(ret, &expr, errbuf, sizeof(errbuf));
- throw std::runtime_error(errbuf);
- }
- }
-
- bool regex::match(const std::string& str_, int eflags) const
- {
- regex_smatch smatch;
- return match(str_, smatch, eflags);
- }
-
- bool regex::match(const std::string& str_, regex_smatch& smatch, int eflags) const
- {
- smatch.str = str_;
- int ret = regexec(&expr, str_.c_str(),
- sizeof(smatch.matchbuf) / sizeof(regmatch_t), smatch.matchbuf, eflags);
-
- if (ret ==REG_NOMATCH)
- return false;
-
- checkerr(ret);
- return true;
- }
-
- void regex::free()
- {
- regfree(&expr);
- }
-}
diff --git a/httpd/tnt/dispatcher.h b/httpd/tnt/dispatcher.h
deleted file mode 100644
index 218efcb..0000000
--- a/httpd/tnt/dispatcher.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* tnt/dispatcher.h
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_DISPATCHER_H
-#define TNT_DISPATCHER_H
-
-#include <cxxtools/thread.h>
-#include <tnt/urlmapper.h>
-#include <vector>
-#include <map>
-#include "tnt/regex.h"
-
-namespace tnt
-{
- // Dispatcher - one per host
- class Dispatcher : public Urlmapper
- {
- public:
- class CompidentType : public Compident
- {
- public:
- typedef std::vector<std::string> args_type;
-
- private:
- std::string pathinfo;
- args_type args;
- bool pathinfo_set;
-
- public:
- CompidentType()
- : pathinfo_set(false)
- { }
-
- explicit CompidentType(const std::string& ident)
- : Compident(ident),
- pathinfo_set(false)
- { }
-
- bool hasPathInfo() const
- { return pathinfo_set; }
- void setPathInfo(const std::string& p)
- { pathinfo = p; pathinfo_set = true; }
- void setArgs(const args_type& a)
- { args = a; }
- const std::string& getPathInfo() const
- { return pathinfo; }
- const args_type& getArgs() const
- { return args; }
- args_type& getArgsRef()
- { return args; }
- };
-
- private:
- typedef std::vector<std::pair<regex, CompidentType> > urlmap_type;
- urlmap_type urlmap; // map url to soname/compname
- mutable cxxtools::RWLock rwlock;
-
- typedef std::map<std::pair<std::string, urlmap_type::const_iterator>,
- CompidentType> urlMapCacheType;
- mutable urlMapCacheType urlMapCache;
- static urlMapCacheType::size_type maxUrlMapCache;
-
- // don't make this public - it's not threadsafe:
- CompidentType mapCompNext(const std::string& compUrl,
- urlmap_type::const_iterator& pos) const;
-
- public:
- virtual ~Dispatcher() { }
-
- void addUrlMapEntry(const std::string& url, const CompidentType& ci);
-
- Compident mapComp(const std::string& compUrl) const;
-
- static urlMapCacheType::size_type getMaxUrlMapCache()
- { return maxUrlMapCache; }
- static void setMaxUrlMapCache(urlMapCacheType::size_type s)
- { maxUrlMapCache = s; }
-
- friend class PosType;
-
- class PosType
- {
- const Dispatcher& dis;
- cxxtools::RdLock lock;
- urlmap_type::const_iterator pos;
- std::string url;
- bool first;
-
- public:
- PosType(const Dispatcher& d, const std::string& u)
- : dis(d),
- lock(dis.rwlock),
- pos(dis.urlmap.begin()),
- url(u),
- first(true)
- { }
-
- CompidentType getNext();
- };
- };
-
-}
-
-#endif // TNT_DISPATCHER_H
-
diff --git a/httpd/tnt/gcryptinit.h b/httpd/tnt/gcryptinit.h
deleted file mode 100644
index 3b6ee33..0000000
--- a/httpd/tnt/gcryptinit.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* tnt/gcryptinit.h
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_GCRYPTINIT_H
-#define TNT_GCRYPTINIT_H
-
-#include <gcrypt.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-gcry_error_t gcrypt_init();
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // TNT_GCRYPTINIT_H
-
diff --git a/httpd/tnt/gnutls.h b/httpd/tnt/gnutls.h
deleted file mode 100644
index 8d8811c..0000000
--- a/httpd/tnt/gnutls.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* tnt/gnutls.h
- * Copyright (C) 2006 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_GNUTLS_H
-#define TNT_GNUTLS_H
-
-#include <cxxtools/tcpstream.h>
-#include <gnutls/gnutls.h>
-
-namespace tnt
-{
- class GnuTlsException : public std::runtime_error
- {
- unsigned long code;
- static std::string formatMessage(const std::string& function, int code_);
-
- public:
- GnuTlsException(const std::string& function, int code_)
- : std::runtime_error(formatMessage(function, code_)),
- code(code_)
- { }
-
- unsigned long getCode() const
- { return code; }
- };
-
- class GnuTlsInit
- {
- static unsigned initCount;
- static gnutls_dh_params dhParams;
-
- public:
- GnuTlsInit();
- ~GnuTlsInit();
-
- gnutls_dh_params getDhParams() const { return dhParams; }
- };
-
- class GnuTlsX509Cred
- {
- gnutls_certificate_credentials x509_cred;
- GnuTlsInit init;
-
- public:
- GnuTlsX509Cred(const char* certificateFile, const char* privateKeyFile);
- ~GnuTlsX509Cred();
-
- operator gnutls_certificate_credentials() const { return x509_cred; }
- };
-
- class GnuTlsServer : public cxxtools::net::Server
- {
- GnuTlsX509Cred cred;
-
- public:
- GnuTlsServer(const char* certificateFile, const char* privateKeyFile);
-
- gnutls_certificate_credentials getCred() const { return cred; }
- };
-
- class GnuTlsStream : public cxxtools::net::Stream
- {
- gnutls_session session;
-
- public:
- GnuTlsStream()
- : session(0)
- { }
-
- explicit GnuTlsStream(int fd)
- : cxxtools::net::Stream(fd)
- { }
-
- explicit GnuTlsStream(const GnuTlsServer& server)
- { accept(server); }
-
- ~GnuTlsStream();
-
- void accept(const GnuTlsServer& server);
- int sslRead(char* buffer, int bufsize) const;
- int sslWrite(const char* buffer, int bufsize) const;
- void shutdown() const;
- };
-
- class GnuTls_streambuf : public std::streambuf
- {
- GnuTlsStream& m_stream;
- char_type* m_buffer;
- unsigned m_bufsize;
-
- public:
- explicit GnuTls_streambuf(GnuTlsStream& stream, unsigned bufsize = 256, int timeout = -1);
- ~GnuTls_streambuf()
- { delete[] m_buffer; }
-
- void setTimeout(int t) { m_stream.setTimeout(t); }
- int getTimeout() const { return m_stream.getTimeout(); }
-
- /// overload std::streambuf
- int_type overflow(int_type c);
- /// overload std::streambuf
- int_type underflow();
- /// overload std::streambuf
- int sync();
- };
-
- class GnuTls_iostream : public GnuTlsStream, public std::iostream
- {
- GnuTls_streambuf m_buffer;
-
- public:
- explicit GnuTls_iostream(unsigned bufsize = 256, int timeout = -1)
- : GnuTlsStream(-1),
- std::iostream(&m_buffer),
- m_buffer(*this, bufsize, timeout)
- { }
-
- explicit GnuTls_iostream(const GnuTlsServer& server, unsigned bufsize = 256, int timeout = -1)
- : GnuTlsStream(server),
- std::iostream(&m_buffer),
- m_buffer(*this, bufsize, timeout)
- { }
-
- void setTimeout(int timeout) { m_buffer.setTimeout(timeout); }
- int getTimeout() const { return m_buffer.getTimeout(); }
- };
-}
-
-#endif // TNT_GNUTLS_H
-
diff --git a/httpd/tnt/job.h b/httpd/tnt/job.h
deleted file mode 100644
index 5e839fd..0000000
--- a/httpd/tnt/job.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/* tnt/job.h
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_JOB_H
-#define TNT_JOB_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <deque>
-#include <cxxtools/thread.h>
-#include <cxxtools/tcpstream.h>
-#include <tnt/httprequest.h>
-#include <tnt/httpparser.h>
-#include <tnt/pointer.h>
-#include <time.h>
-#include "tnt/ssl.h"
-
-/**
-// in tntnet (mainthread):
-Jobqueue queue;
-void mainloop()
-{
- while (1)
- {
- Jobqueue::JobPtr j = new Tcpjob();
- j->accept(poller.get());
- queue.put(j);
- }
-}
-
-// in server (workerthread):
-void Server::run()
-{
- while (1)
- {
- Jobqueue::JobPtr j = queue.get();
- std::iostream& socket = j->getStream();
- processRequest(socket);
- }
-}
-*/
-
-namespace tnt
-{
- /** Job - one per request */
- class Job
- {
- unsigned keepAliveCounter;
-
- HttpRequest request;
- HttpMessage::Parser parser;
- time_t lastAccessTime;
-
- unsigned refs;
-
- static unsigned socket_read_timeout;
- static unsigned socket_write_timeout;
- static unsigned keepalive_max;
- static unsigned socket_buffer_size;
-
- public:
- Job()
- : keepAliveCounter(keepalive_max),
- parser(request),
- lastAccessTime(0),
- refs(0)
- { }
-
- protected:
- virtual ~Job();
-
- public:
- unsigned addRef() { return ++refs; }
- unsigned release()
- {
- if (--refs == 0)
- {
- delete this;
- return 0;
- }
- else
- return refs;
- }
-
- virtual std::iostream& getStream() = 0;
- virtual int getFd() const = 0;
- virtual void setRead() = 0;
- virtual void setWrite() = 0;
-
- HttpRequest& getRequest() { return request; }
- HttpMessage::Parser& getParser() { return parser; }
-
- unsigned decrementKeepAliveCounter()
- { return keepAliveCounter > 0 ? --keepAliveCounter : 0; }
- void clear();
- void touch() { time(&lastAccessTime); }
- int msecToTimeout(time_t currentTime) const;
-
- static void setSocketReadTimeout(unsigned ms) { socket_read_timeout = ms; }
- static void setSocketWriteTimeout(unsigned ms) { socket_write_timeout = ms; }
- static void setKeepAliveMax(unsigned n) { keepalive_max = n; }
- static void setSocketBufferSize(unsigned b) { socket_buffer_size = b; }
-
- static unsigned getSocketReadTimeout() { return socket_read_timeout; }
- static unsigned getSocketWriteTimeout() { return socket_write_timeout; }
- static unsigned getKeepAliveTimeout();
- static unsigned getKeepAliveMax() { return keepalive_max; }
- static unsigned getSocketBufferSize() { return socket_buffer_size; }
- };
-
- class Tcpjob : public Job
- {
- cxxtools::net::iostream socket;
-
- public:
- Tcpjob()
- : socket(getSocketBufferSize(), getSocketReadTimeout())
- { }
-
- void accept(const cxxtools::net::Server& listener);
-
- std::iostream& getStream();
- int getFd() const;
- void setRead();
- void setWrite();
- };
-
-#ifdef USE_SSL
- class SslTcpjob : public Job
- {
- ssl_iostream socket;
-
- public:
- SslTcpjob()
- : socket(getSocketBufferSize(), getSocketReadTimeout())
- { }
-
- void accept(const SslServer& listener);
-
- std::iostream& getStream();
- int getFd() const;
- void setRead();
- void setWrite();
- };
-#endif // USE_SSL
-
- /** Jobqueue - one per process */
- class Jobqueue
- {
- public:
- typedef Pointer<Job> JobPtr;
-
- cxxtools::Condition noWaitThreads;
-
- private:
- std::deque<JobPtr> jobs;
- cxxtools::Mutex mutex;
- cxxtools::Condition notEmpty;
- cxxtools::Condition notFull;
- unsigned waitThreads;
- unsigned capacity;
-
- public:
- explicit Jobqueue(unsigned capacity_)
- : waitThreads(0),
- capacity(capacity_)
- { }
-
- void put(JobPtr j);
- JobPtr get();
-
- void setCapacity(unsigned c)
- { capacity = c; }
- unsigned getCapacity() const
- { return capacity; }
- unsigned getWaitThreadCount() const
- { return waitThreads; }
- bool empty() const
- { return jobs.empty(); }
- };
-}
-
-#endif // TNT_JOB_H
-
diff --git a/httpd/tnt/listener.h b/httpd/tnt/listener.h
deleted file mode 100644
index 4991763..0000000
--- a/httpd/tnt/listener.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* tnt/listener.h
- * Copyright (C) 2003 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_LISTENER_H
-#define TNT_LISTENER_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <cxxtools/thread.h>
-#include "tnt/job.h"
-
-namespace tnt
-{
- class ListenerBase : public cxxtools::AttachedThread
- {
- std::string ipaddr;
- unsigned short int port;
-
- public:
- ListenerBase(const std::string& ipaddr_, unsigned short int port_)
- : ipaddr(ipaddr_),
- port(port_)
- { }
-
- void doStop();
- };
-
- class Listener : public ListenerBase
- {
- cxxtools::net::Server server;
- Jobqueue& queue;
- static int backlog;
- static unsigned listenRetry;
-
- public:
- Listener(const std::string& ipaddr, unsigned short int port, Jobqueue& q);
- virtual void run();
-
- static void setBacklog(int backlog_) { backlog = backlog_; }
- static int getBacklog() { return backlog; }
- static void setListenRetry(unsigned listenRetry_) { listenRetry = listenRetry_; }
- static unsigned getListenRetry() { return listenRetry; }
- };
-
-#ifdef USE_SSL
- class Ssllistener : public ListenerBase
- {
- SslServer server;
- Jobqueue& queue;
-
- public:
- Ssllistener(const char* certificateFile, const char* keyFile,
- const std::string& ipaddr, unsigned short int port, Jobqueue& q);
- virtual void run();
- };
-#endif // USE_SSL
-
-}
-
-#endif // TNT_LISTENER_H
-
diff --git a/httpd/tnt/openssl.h b/httpd/tnt/openssl.h
deleted file mode 100644
index 863782f..0000000
--- a/httpd/tnt/openssl.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* tnt/openssl.h
- * Copyright (C) 2003 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_OPENSSL_H
-#define TNT_OPENSSL_H
-
-#include <cxxtools/tcpstream.h>
-#include <openssl/ssl.h>
-
-namespace tnt
-{
- class OpensslException : public std::runtime_error
- {
- unsigned long code;
-
- public:
- OpensslException(const std::string& what, unsigned long code_)
- : std::runtime_error(what),
- code(code_)
- { }
-
- unsigned long getCode() const
- { return code; }
- };
-
- class OpensslServer : public cxxtools::net::Server
- {
- SSL_CTX* ctx;
- void installCertificates(const char* certificateFile, const char* privateKeyFile);
-
- public:
- OpensslServer(const char* certificateFile);
- OpensslServer(const char* certificateFile, const char* privateKeyFile);
- ~OpensslServer();
-
- SSL_CTX* getSslContext() const { return ctx; }
- };
-
- class OpensslStream : public cxxtools::net::Stream
- {
- SSL* ssl;
-
- public:
- OpensslStream();
-
- explicit OpensslStream(int fd)
- : cxxtools::net::Stream(fd)
- { }
-
- explicit OpensslStream(const OpensslServer& server);
- ~OpensslStream();
-
- void accept(const OpensslServer& server);
-
- int sslRead(char* buffer, int bufsize) const;
- int sslWrite(const char* buffer, int bufsize) const;
- void shutdown() const;
- };
-
- class openssl_streambuf : public std::streambuf
- {
- OpensslStream& m_stream;
- char_type* m_buffer;
- unsigned m_bufsize;
-
- public:
- explicit openssl_streambuf(OpensslStream& stream, unsigned bufsize = 256, int timeout = -1);
- ~openssl_streambuf()
- { delete[] m_buffer; }
-
- void setTimeout(int t) { m_stream.setTimeout(t); }
- int getTimeout() const { return m_stream.getTimeout(); }
-
- /// overload std::streambuf
- int_type overflow(int_type c);
- /// overload std::streambuf
- int_type underflow();
- /// overload std::streambuf
- int sync();
- };
-
- class openssl_iostream : public OpensslStream, public std::iostream
- {
- openssl_streambuf m_buffer;
-
- public:
- explicit openssl_iostream(unsigned bufsize = 256, int timeout = -1)
- : OpensslStream(-1),
- std::iostream(&m_buffer),
- m_buffer(*this, bufsize, timeout)
- { }
-
- explicit openssl_iostream(const OpensslServer& server, unsigned bufsize = 256, int timeout = -1)
- : OpensslStream(server),
- std::iostream(&m_buffer),
- m_buffer(*this, bufsize, timeout)
- { }
-
- void setTimeout(int timeout) { m_buffer.setTimeout(timeout); }
- int getTimeout() const { return m_buffer.getTimeout(); }
- };
-}
-
-#endif // TNT_OPENSSL_H
-
diff --git a/httpd/tnt/poller.h b/httpd/tnt/poller.h
deleted file mode 100644
index d9b12e9..0000000
--- a/httpd/tnt/poller.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* tnt/poller.h
- * Copyright (C) 2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_POLLER_H
-#define TNT_POLLER_H
-
-#include "tnt/job.h"
-#include <cxxtools/dynbuffer.h>
-#include <cxxtools/thread.h>
-#include <sys/poll.h>
-
-namespace tnt
-{
- class Poller : public cxxtools::AttachedThread
- {
- Jobqueue& queue;
- int notify_pipe[2];
-
- typedef std::deque<Jobqueue::JobPtr> jobs_type;
-
- jobs_type current_jobs;
- cxxtools::Dynbuffer<pollfd> pollfds;
-
- jobs_type new_jobs;
-
- cxxtools::Mutex mutex;
- int poll_timeout;
-
- void append_new_jobs();
- void append(Jobqueue::JobPtr& job);
- void dispatch();
- void remove(jobs_type::size_type n);
-
- public:
- Poller(Jobqueue& q);
-
- virtual void run();
- void doStop();
- void addIdleJob(Jobqueue::JobPtr job);
- };
-
-}
-
-#endif // TNT_POLLER_H
-
diff --git a/httpd/tnt/regex.h b/httpd/tnt/regex.h
deleted file mode 100644
index b2a30e8..0000000
--- a/httpd/tnt/regex.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* tnt/regex.h
- * Copyright (C) 2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_REGEX_H
-#define TNT_REGEX_H
-
-#include <string>
-#include <sys/types.h>
-#include <regex.h>
-
-namespace tnt
-{
- /// collects matches in a regex
- class regex_smatch
- {
- friend class regex;
-
- std::string str;
- regmatch_t matchbuf[10];
-
- public:
- unsigned size() const;
- std::string get(unsigned n) const;
- std::string format(const std::string& s) const;
- };
-
- /// regex(3)-wrapper.
- /// Warning: incomplete, but sufficient for tntnet.
- /// Regular expression is not automatically freed. Tntnet needs to
- /// put regex into a stl-container, so it needs to be copyable.
- /// For this class to be complete, the regex_t needs to be
- /// reference-counted. This is unneeded for tntnet, because the regex is
- /// never freed anyway.
- class regex
- {
- regex_t expr;
-
- void checkerr(int ret) const;
-
- public:
- explicit regex(const char* ex, int cflags = REG_EXTENDED)
- {
- checkerr(::regcomp(&expr, ex, cflags));
- }
-
- explicit regex(const std::string& ex, int cflags = REG_EXTENDED)
- {
- checkerr(::regcomp(&expr, ex.c_str(), cflags));
- }
-
- bool match(const std::string& str_, regex_smatch& smatch, int eflags = 0) const;
- bool match(const std::string& str_, int eflags = 0) const;
-
- void free();
-
- private:
- friend class value_type;
- };
-
-}
-
-#endif // TNT_REGEX_H
-
diff --git a/httpd/tnt/ssl.h b/httpd/tnt/ssl.h
deleted file mode 100644
index 6660d2f..0000000
--- a/httpd/tnt/ssl.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* tnt/ssl.h
- * Copyright (C) 2006 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_SSL_H
-#define TNT_SSL_H
-
-#ifdef WITH_GNUTLS
-# include "tnt/gnutls.h"
-# define USE_SSL
-#endif
-
-#ifdef WITH_OPENSSL
-# include "tnt/openssl.h"
-# define USE_SSL
-#endif
-
-namespace tnt
-{
-#ifdef WITH_GNUTLS
-
- typedef GnuTlsServer SslServer;
- typedef GnuTls_iostream ssl_iostream;
-
-#endif
-
-#ifdef WITH_OPENSSL
-
- typedef OpensslServer SslServer;
- typedef openssl_iostream ssl_iostream;
-
-#endif
-
-}
-
-#endif // TNT_SSL_H
-
diff --git a/httpd/tnt/tntnet.h b/httpd/tnt/tntnet.h
deleted file mode 100644
index a83784e..0000000
--- a/httpd/tnt/tntnet.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* tnt/tntnet.h
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_TNTNET_H
-#define TNT_TNTNET_H
-
-#include <cxxtools/arg.h>
-#include "tnt/tntconfig.h"
-#include "tnt/job.h"
-#include "tnt/poller.h"
-#include "tnt/dispatcher.h"
-#include <tnt/scopemanager.h>
-#include <set>
-
-namespace tnt
-{
- class ListenerBase;
-
- class Tntnet
- {
- std::string configFile;
- Tntconfig config;
- cxxtools::Arg<const char*> propertyfilename;
- cxxtools::Arg<bool> debug;
- bool isDaemon;
-
- unsigned minthreads;
- unsigned maxthreads;
- unsigned long threadstartdelay;
-
- Jobqueue queue;
-
- static bool stop;
- static int ret;
- typedef std::set<ListenerBase*> listeners_type;
- listeners_type listeners;
-
- Poller pollerthread;
- Dispatcher d_dispatcher;
-
- static std::string pidFileName;
-
- ScopeManager scopemanager;
-
- // helper methods
- void setUser() const;
- void setGroup() const;
- void setDir(const char* def) const;
- int mkDaemon() const; // returns pipe
- void closeStdHandles() const;
-
- // noncopyable
- Tntnet(const Tntnet&);
- Tntnet& operator= (const Tntnet&);
-
- void initLogging();
- void writePidfile(int pid);
- void monitorProcess(int workerPid);
- void initWorkerProcess();
- void workerProcess(int filedes = -1);
-
- void timerTask();
- void loadConfiguration();
-
- public:
- Tntnet(int& argc, char* argv[]);
- int run();
-
- static void shutdown();
- static void restart();
- static bool shouldStop() { return stop; }
-
- Jobqueue& getQueue() { return queue; }
- Poller& getPoller() { return pollerthread; }
- const Dispatcher& getDispatcher() const { return d_dispatcher; }
- const Tntconfig& getConfig() const { return config; }
- ScopeManager& getScopemanager() { return scopemanager; }
- };
-
-}
-
-#endif // TNT_TNTNET_H
-
diff --git a/httpd/tnt/worker.h b/httpd/tnt/worker.h
deleted file mode 100644
index be42841..0000000
--- a/httpd/tnt/worker.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* tnt/worker.h
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef TNT_WORKER_H
-#define TNT_WORKER_H
-
-#include <string>
-#include <cxxtools/tcpstream.h>
-#include <cxxtools/thread.h>
-#include <cxxtools/pool.h>
-#include <tnt/comploader.h>
-#include <tnt/tntnet.h>
-#include <tnt/scope.h>
-
-namespace tnt
-{
- class HttpRequest;
- class HttpReply;
-
- class Worker : public cxxtools::DetachedThread
- {
- static cxxtools::Mutex mutex;
- static unsigned nextThreadNumber;
-
- Tntnet& application;
-
- typedef cxxtools::Pool<Comploader> ComploaderPoolType;
- static ComploaderPoolType comploaderPool;
-
- ComploaderPoolType::objectptr_type comploaderObject;
- Comploader& comploader;
-
- Scope threadScope;
-
- pthread_t threadId;
- const char* state;
- time_t lastWaitTime;
-
- typedef std::set<Worker*> workers_type;
- static workers_type workers;
-
- static unsigned maxRequestTime;
- static unsigned minThreads;
- static bool enableCompression;
-
- bool processRequest(HttpRequest& request, std::iostream& socket,
- unsigned keepAliveCount);
- void healthCheck(time_t currentTime);
-
- ~Worker();
-
- public:
- Worker(Tntnet& app);
-
- virtual void run();
-
- void dispatch(HttpRequest& request, HttpReply& reply);
-
- static void timer();
-
- /// Sets a hard limit for request-time.
- /// When the time is exceeded, this process exits.
- static void setMaxRequestTime(unsigned sec) { maxRequestTime = sec; }
- static unsigned getMaxRequestTime() { return maxRequestTime; }
-
- static workers_type::size_type getCountThreads();
- static void setMinThreads(unsigned n) { minThreads = n; }
-
- static void setEnableCompression(bool sw = true) { enableCompression = sw; }
- static unsigned getEnableCompression() { return enableCompression; }
- };
-}
-
-#endif // TNT_WORKER_H
-
diff --git a/httpd/tntnet.cpp b/httpd/tntnet.cpp
deleted file mode 100644
index 98f2ac9..0000000
--- a/httpd/tntnet.cpp
+++ /dev/null
@@ -1,832 +0,0 @@
-/* tntnet.cpp
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/worker.h"
-#include "tnt/tntnet.h"
-#include "tnt/listener.h"
-#include "tnt/http.h"
-#include "tnt/httpreply.h"
-#include "tnt/sessionscope.h"
-
-#include <cxxtools/tcpstream.h>
-#include <cxxtools/log.h>
-#include <cxxtools/loginit.h>
-
-#include <iostream>
-#include <fstream>
-#include <vector>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <grp.h>
-#include <pwd.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <errno.h>
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifndef TNTNET_CONF
-# define TNTNET_CONF "/etc/tntnet.conf"
-#endif
-
-#ifndef TNTNET_PID
-# define TNTNET_PID "/var/run/tntnet.pid"
-#endif
-
-log_define("tntnet.tntnet")
-
-#define log_error_master(expr) \
- do { \
- std::cout << "ERROR: " << expr << std::endl; \
- } while(false)
-
-#define log_warn_master(expr) \
- do { \
- std::cout << "WARN: " << expr << std::endl; \
- } while(false)
-
-#define log_info_master(expr) \
- do { \
- std::cout << "INFO: " << expr << std::endl; \
- } while(false)
-
-#define log_debug_master(expr) \
- do { \
- std::cout << "DEBUG: " << expr << std::endl; \
- } while(false)
-
-namespace
-{
- void sigEnd(int)
- {
- tnt::Tntnet::shutdown();
- }
-
- void sigReload(int)
- {
- // stopping child with 111 signals monitor-process to restart child
- tnt::Tntnet::restart();
- }
-
- void configureDispatcher(tnt::Dispatcher& dis, const tnt::Tntconfig& config)
- {
- typedef tnt::Dispatcher::CompidentType CompidentType;
-
- const tnt::Tntconfig::config_entries_type& params = config.getConfigValues();
-
- tnt::Tntconfig::config_entries_type::const_iterator vi;
- for (vi = params.begin(); vi != params.end(); ++vi)
- {
- const tnt::Tntconfig::config_entry_type& v = *vi;
- const tnt::Tntconfig::params_type& args = v.params;
- if (v.key == "MapUrl")
- {
- if (args.size() < 2)
- {
- std::ostringstream msg;
- msg << "invalid number of parameters (" << args.size() << ") in MapUrl";
- throw std::runtime_error(msg.str());
- }
-
- std::string url = args[0];
-
- CompidentType ci = CompidentType(args[1]);
- if (args.size() > 2)
- {
- ci.setPathInfo(args[2]);
- if (args.size() > 3)
- ci.setArgs(CompidentType::args_type(args.begin() + 3, args.end()));
- }
-
- dis.addUrlMapEntry(url, ci);
- }
- }
- }
-
- bool checkChildSuccess(int fd)
- {
- log_debug("checkChildSuccess");
-
- char buffer;
- int ret = ::read(fd, &buffer, 1);
- if (ret < 0)
- throw std::runtime_error(
- std::string("error in read: ") + strerror(errno));
- close(fd);
- return ret > 0;
- }
-
- void signalParentSuccess(int fd)
- {
- log_debug("signalParentSuccess");
-
- ssize_t s = write(fd, "1", 1);
- if (s < 0)
- throw std::runtime_error(
- std::string("error in write(): ") + strerror(errno));
- close(fd);
- }
-
-}
-
-namespace tnt
-{
- ////////////////////////////////////////////////////////////////////////
- // Tntnet
- //
- bool Tntnet::stop = false;
- int Tntnet::ret = 0;
- std::string Tntnet::pidFileName;
-
- Tntnet::Tntnet(int& argc, char* argv[])
- : propertyfilename(argc, argv, 'P'),
- debug(argc, argv, 'd'),
- queue(1000),
- pollerthread(queue)
- {
- // check for argument -c
- cxxtools::Arg<const char*> conf(argc, argv, 'c');
- if (conf.isSet())
- configFile = conf;
- else
- {
- // read 1st parameter from argument-list
- cxxtools::Arg<const char*> conf(argc, argv);
- if (conf.isSet())
- configFile = conf;
- else
- {
- // check environment-variable TNTNET_CONF
- const char* tntnetConf = ::getenv("TNTNET_CONF");
- if (tntnetConf)
- configFile = tntnetConf;
- else
- configFile = TNTNET_CONF; // take default
- }
- }
- }
-
- void Tntnet::setGroup() const
- {
- Tntconfig::params_type group = config.getConfigValue("Group");
- if (group.size() >= 1)
- {
- struct group * gr = getgrnam(group.begin()->c_str());
- if (gr == 0)
- throw std::runtime_error("unknown group " + *group.begin());
-
- log_debug("change group to " << *group.begin() << '(' << gr->gr_gid << ')');
-
- int ret = setgid(gr->gr_gid);
- if (ret != 0)
- {
- std::ostringstream msg;
- msg << "cannot change group to " << *group.begin()
- << '(' << gr->gr_gid << "): " << strerror(errno);
- throw std::runtime_error(msg.str());
- }
- }
- }
-
- void Tntnet::setDir(const char* def) const
- {
- std::string dir = config.getValue("Dir", def);
-
- if (!dir.empty())
- {
- log_debug("chdir(" << dir << ')');
- if (chdir(dir.c_str()) == -1)
- {
- throw std::runtime_error(
- std::string("error in chdir(): ")
- + strerror(errno));
- }
- }
-
- std::string chrootdir = config.getValue("Chroot");
- if (!chrootdir.empty() && chroot(chrootdir.c_str()) == -1)
- throw std::runtime_error(
- std::string("error in chroot(): ")
- + strerror(errno));
- }
-
- void Tntnet::setUser() const
- {
- Tntconfig::params_type user = config.getConfigValue("User");
- if (user.size() >= 1)
- {
- struct passwd * pw = getpwnam(user.begin()->c_str());
- if (pw == 0)
- throw std::runtime_error("unknown user " + *user.begin());
-
- log_debug("change user to " << *user.begin() << '(' << pw->pw_uid << ')');
-
- int ret = setuid(pw->pw_uid);
- if (ret != 0)
- {
- std::ostringstream msg;
- msg << "cannot change user to " << *user.begin()
- << '(' << pw->pw_uid << "): " << strerror(errno);
- throw std::runtime_error(msg.str());
- }
- }
- }
-
- int Tntnet::mkDaemon() const
- {
- log_info("start daemon-mode");
-
- int filedes[2];
-
- if (pipe(filedes) != 0)
- throw std::runtime_error(
- std::string("error in pipe(int[2]): ") + strerror(errno));
-
- int pid = fork();
- if (pid > 0)
- {
- // parent
-
- close(filedes[1]); // close write-fd
-
- // exit with error, when nothing read
- ::exit (checkChildSuccess(filedes[0]) ? 0 : 1);
- }
- else if (pid < 0)
- throw std::runtime_error(
- std::string("error in fork(): ") + strerror(errno));
-
- // child
-
- close(filedes[0]); // close read-fd
-
- // setsid
- if (setsid() == -1)
- throw std::runtime_error(
- std::string("error in setsid(): ")
- + strerror(errno));
-
- // return write-fd
- return filedes[1];
- }
-
- void Tntnet::closeStdHandles() const
- {
- // close stdin, stdout and stderr
- bool noclosestd = config.getBoolValue("NoCloseStdout", false);
- if (noclosestd)
- {
- log_debug("not closing stdout");
- return;
- }
-
- if (freopen("/dev/null", "r", stdin) == 0)
- throw std::runtime_error(
- std::string("unable to replace stdin with /dev/null: ")
- + strerror(errno));
-
- if (freopen("/dev/null", "w", stdout) == 0)
- throw std::runtime_error(
- std::string("unable to replace stdout with /dev/null: ")
- + strerror(errno));
-
- if (freopen("/dev/null", "w", stderr) == 0)
- throw std::runtime_error(
- std::string("unable to replace stderr with /dev/null: ")
- + strerror(errno));
- }
-
- int Tntnet::run()
- {
- loadConfiguration();
-
- if (debug)
- {
- log_init_debug();
- log_warn("Debugmode");
- isDaemon = false;
- }
- else
- {
- isDaemon = config.getBoolValue("Daemon", false);
- }
-
- if (isDaemon)
- {
- int filedes = mkDaemon();
-
- setDir("");
-
- bool nomonitor = config.getBoolValue("NoMonitor", false);
- if (nomonitor)
- {
- log_debug("start worker-process without monitor");
- writePidfile(getpid());
- initWorkerProcess();
-
- // change group and user
- setGroup();
- setUser();
-
- initLogging();
- workerProcess(filedes);
- }
- else
- {
- initWorkerProcess();
- do
- {
- int filedes_monitor[2];
-
- if (pipe(filedes_monitor) != 0)
- throw std::runtime_error(
- std::string("error in pipe(int[2]): ") + strerror(errno));
-
- // fork workerprocess
- int pid = fork();
- if (pid < 0)
- throw std::runtime_error(
- std::string("error in forking workerprocess: ")
- + strerror(errno));
-
- if (pid == 0)
- {
- // workerprocess
-
- close(filedes_monitor[0]); // close read-fd
-
- // change group and user
- setGroup();
- setUser();
-
- initLogging();
- workerProcess(filedes_monitor[1]);
- return ret;
- }
- else
- {
- close(filedes_monitor[1]); // close write-fd
-
- // write child-pid
- writePidfile(pid);
-
- // wait for worker to signal success
- if (!checkChildSuccess(filedes_monitor[0]))
- ::exit(1);
- if (filedes >= 0)
- {
- signalParentSuccess(filedes);
- filedes = -1;
- }
-
- monitorProcess(pid);
- if (!stop)
- sleep(1);
- }
-
- } while (!stop);
- }
- }
- else
- {
- log_info("no daemon-mode");
- initLogging();
- initWorkerProcess();
- workerProcess();
- }
-
- return 0;
- }
-
- void Tntnet::initLogging()
- {
- if (debug)
- return; // logging already initialized
-
- std::string pf;
- if (propertyfilename.isSet())
- pf = propertyfilename.getValue();
- else
- pf = config.getValue("PropertyFile");
-
- if (pf.empty())
- log_init();
- else
- {
- struct stat properties_stat;
- if (stat(pf.c_str(), &properties_stat) != 0)
- throw std::runtime_error("propertyfile " + pf + " not found");
-
- log_init(pf.c_str());
- }
- }
-
- void Tntnet::writePidfile(int pid)
- {
- pidFileName = config.getValue("PidFile", TNTNET_PID);
-
- log_debug("pidfile=" << pidFileName);
-
- if (!pidFileName.empty())
- {
- if (pidFileName[0] != '/')
- {
- // prepend current working-directory to pidfilename if not absolute
- std::vector<char> buf(256);
- const char* cwd;
- while (true)
- {
- cwd = ::getcwd(&buf[0], buf.size());
- if (cwd)
- break;
- else if (errno == ERANGE)
- buf.resize(buf.size() * 2);
- else
- throw std::runtime_error(
- std::string("error in getcwd: ") + strerror(errno));
- }
- pidFileName = std::string(cwd) + '/' + pidFileName;
- log_debug("pidfile=" << pidFileName);
- }
-
- std::ofstream pidfile(pidFileName.c_str());
- if (!pidfile)
- throw std::runtime_error("unable to open pid-file " + pidFileName);
- pidfile << pid;
- }
- }
-
- void Tntnet::monitorProcess(int workerPid)
- {
- setDir("");
-
- // close stdin, stdout and stderr
- closeStdHandles();
-
- int status;
- waitpid(workerPid, &status, 0);
-
- if (WIFSIGNALED(status))
- {
- // SIGTERM means normal exit
- if (WTERMSIG(status) == SIGTERM)
- {
- log_info_master("child terminated normally");
- stop = true;
- }
- else
- {
- log_warn_master("child terminated with signal "
- << WTERMSIG(status) << " - restart child");
- }
- }
- else if (WEXITSTATUS(status) == 111)
- {
- log_info_master("child requested restart");
- }
- else
- {
- log_info_master("child exited with exitcode " << WEXITSTATUS(status));
- stop = true;
- }
-
- if (unlink(pidFileName.c_str()) != 0)
- log_error_master("failed to remove pidfile \"" << pidFileName << "\" error " << errno);
- }
-
- void Tntnet::initWorkerProcess()
- {
- log_debug("init workerprocess");
-
- //signal(SIGPIPE, SIG_IGN);
- //signal(SIGABRT, SIG_IGN);
- //signal(SIGTERM, sigEnd);
- //signal(SIGHUP, sigReload);
-
- configureDispatcher(d_dispatcher, config);
-
- // create listener-threads
- Tntconfig::config_entries_type configListen;
- config.getConfigValues("Listen", configListen);
-
- if (configListen.empty())
- {
- log_warn("no listeners defined - using 0.0.0.0:80");
- ListenerBase* s = new tnt::Listener("0.0.0.0", 80, queue);
- listeners.insert(s);
- }
- else
- {
- for (Tntconfig::config_entries_type::const_iterator it = configListen.begin();
- it != configListen.end(); ++it)
- {
- if (it->params.empty())
- throw std::runtime_error("empty Listen-entry");
-
- unsigned short int port = 80;
- if (it->params.size() >= 2)
- {
- std::istringstream p(it->params[1]);
- p >> port;
- if (!p)
- {
- std::ostringstream msg;
- msg << "invalid port " << it->params[1];
- throw std::runtime_error(msg.str());
- }
- }
-
- std::string ip(it->params[0]);
- log_debug("create listener ip=" << ip << " port=" << port);
- ListenerBase* s = new tnt::Listener(ip, port, queue);
- listeners.insert(s);
- }
- }
-
-#ifdef USE_SSL
- // create ssl-listener-threads
- std::string defaultCertificateFile = config.getValue("SslCertificate");
- std::string defaultCertificateKey = config.getValue("SslKey");
- configListen.clear();
- config.getConfigValues("SslListen", configListen);
-
- for (Tntconfig::config_entries_type::const_iterator it = configListen.begin();
- it != configListen.end(); ++it)
- {
- if (it->params.empty())
- throw std::runtime_error("empty SslListen-entry");
-
- unsigned short int port = 443;
- if (it->params.size() >= 2)
- {
- std::istringstream p(it->params[1]);
- p >> port;
- if (!p)
- {
- std::ostringstream msg;
- msg << "invalid port " << it->params[1];
- throw std::runtime_error(msg.str());
- }
- }
-
- std::string certificateFile =
- it->params.size() >= 3 ? it->params[2]
- : defaultCertificateFile;
- std::string certificateKey =
- it->params.size() >= 4 ? it->params[3] :
- it->params.size() >= 3 ? it->params[2] : defaultCertificateKey;
-
- if (certificateFile.empty())
- throw std::runtime_error("Ssl-certificate not configured");
-
- std::string ip(it->params[0]);
- log_debug("create ssl-listener ip=" << ip << " port=" << port);
- ListenerBase* s = new Ssllistener(certificateFile.c_str(),
- certificateKey.c_str(), ip, port, queue);
- listeners.insert(s);
- }
-#endif // USE_SSL
-
- // configure worker (static)
- Comploader::configure(config);
-
- // configure http
- HttpMessage::setMaxRequestSize(
- config.getValue("MaxRequestSize", HttpMessage::getMaxRequestSize()));
- Job::setSocketReadTimeout(
- config.getValue("SocketReadTimeout", Job::getSocketReadTimeout()));
- Job::setSocketWriteTimeout(
- config.getValue("SocketWriteTimeout", Job::getSocketWriteTimeout()));
- Job::setKeepAliveMax(
- config.getValue("KeepAliveMax", Job::getKeepAliveMax()));
- Job::setSocketBufferSize(
- config.getValue("BufferSize", Job::getSocketBufferSize()));
- HttpReply::setMinCompressSize(
- config.getValue("MinCompressSize", HttpReply::getMinCompressSize()));
- HttpReply::setKeepAliveTimeout(
- config.getValue("KeepAliveTimeout", HttpReply::getKeepAliveTimeout()));
- HttpReply::setDefaultContentType(
- config.getValue("DefaultContentType", HttpReply::getDefaultContentType()));
-
- log_debug("listeners.size()=" << listeners.size());
- }
-
- void Tntnet::workerProcess(int filedes)
- {
- log_debug("worker-process");
-
- // reload configuration
- config = Tntconfig();
- loadConfiguration();
-
- // initialize worker-process
- minthreads = config.getValue<unsigned>("MinThreads", 5);
- maxthreads = config.getValue<unsigned>("MaxThreads", 100);
- threadstartdelay = config.getValue<unsigned>("ThreadStartDelay", 10);
- Worker::setMinThreads(minthreads);
- Worker::setMaxRequestTime(config.getValue<unsigned>("MaxRequestTime", Worker::getMaxRequestTime()));
- Worker::setEnableCompression(config.getBoolValue("EnableCompression", Worker::getEnableCompression()));
- queue.setCapacity(config.getValue<unsigned>("QueueSize", queue.getCapacity()));
- Sessionscope::setDefaultTimeout(config.getValue<unsigned>("SessionTimeout", Sessionscope::getDefaultTimeout()));
- Listener::setBacklog(config.getValue<int>("ListenBacklog", Listener::getBacklog()));
- Listener::setListenRetry(config.getValue<int>("ListenRetry", Listener::getListenRetry()));
- Dispatcher::setMaxUrlMapCache(config.getValue<unsigned>("MaxUrlMapCache", Dispatcher::getMaxUrlMapCache()));
-
- Tntconfig::config_entries_type configSetEnv;
- config.getConfigValues("SetEnv", configSetEnv);
- for (Tntconfig::config_entries_type::const_iterator it = configSetEnv.begin();
- it != configSetEnv.end(); ++it)
- {
- if (it->params.size() >= 2)
- {
-#ifdef HAVE_SETENV
- log_debug("setenv " << it->params[0] << "=\"" << it->params[1] << '"');
- ::setenv(it->params[0].c_str(), it->params[1].c_str(), 1);
-#else
- std::string name = it->params[0];
- std::string value = it->params[1];
-
- char* env = new char[name.size() + value.size() + 2];
- name.copy(env, name.size());
- env[name.size()] = '=';
- value.copy(env + name.size() + 1, value.size());
- env[name.size() + value.size() + 1] = '\0';
-
- log_debug("putenv(" << env);
- ::putenv(env);
-#endif
- }
- }
-
- // create worker-threads
- log_info("create " << minthreads << " worker threads");
- for (unsigned i = 0; i < minthreads; ++i)
- {
- log_debug("create worker " << i);
- Worker* s = new Worker(*this);
- s->create();
- }
-
- // create poller-thread
- log_debug("start poller thread");
- pollerthread.create();
-
- // launch listener-threads
- log_info("create " << listeners.size() << " listener threads");
- for (listeners_type::iterator it = listeners.begin();
- it != listeners.end(); ++it)
- (*it)->create();
-
- log_debug("start timer thread");
- cxxtools::MethodThread<Tntnet, cxxtools::AttachedThread> timerThread(*this, &Tntnet::timerTask);
- timerThread.create();
-
- if (filedes >= 0)
- {
- signalParentSuccess(filedes);
- closeStdHandles();
- }
-
- // mainloop
- cxxtools::Mutex mutex;
- while (!stop)
- {
- {
- cxxtools::MutexLock lock(mutex);
- queue.noWaitThreads.wait(lock);
- }
-
- if (stop)
- break;
-
- if (Worker::getCountThreads() < maxthreads)
- {
- log_info("create workerthread");
- Worker* s = new Worker(*this);
- s->create();
- }
- else
- log_warn("max worker-threadcount " << maxthreads << " reached");
-
- if (threadstartdelay > 0)
- usleep(threadstartdelay);
- }
-
- log_warn("stopping Tntnet");
-
- // join-loop
- while (!listeners.empty())
- {
- listeners_type::value_type s = *listeners.begin();
- log_debug("remove listener from listener-list");
- listeners.erase(s);
-
- log_debug("request listener to stop");
- s->doStop();
-
- log_debug("join listener-thread");
- s->join();
- delete s;
-
- log_debug("listener stopped");
- }
-
- log_info("listeners stopped");
- }
-
- void Tntnet::timerTask()
- {
- log_debug("timer thread");
-
- while (!stop)
- {
- sleep(1);
-
- log_debug("check sessiontimeout");
- getScopemanager().checkSessionTimeout();
-
- log_debug("worker-timer");
- Worker::timer();
- }
-
- log_warn("stopping Tntnet");
-
- if (!pidFileName.empty())
- unlink(pidFileName.c_str());
-
- queue.noWaitThreads.signal();
- Worker::setMinThreads(0);
- pollerthread.doStop();
- }
-
- void Tntnet::loadConfiguration()
- {
- config = Tntconfig();
- config.load(configFile.c_str());
- }
-
- void Tntnet::shutdown()
- {
- stop = true;
- }
-
- void Tntnet::restart()
- {
- // stopping child with 111 signals monitor-process to restart child
- stop = true;
- ret = 111;
- }
-
-}
-
-////////////////////////////////////////////////////////////////////////
-// main
-//
-#ifdef HAVE_TNTNET_MAIN
-int main(int argc, char* argv[])
-{
- signal(SIGPIPE, SIG_IGN);
- signal(SIGABRT, SIG_IGN);
- signal(SIGTERM, sigEnd);
- std::ios::sync_with_stdio(false);
-
- try
- {
- tnt::Tntnet app(argc, argv);
- if (argc != 1)
- {
- std::cout << PACKAGE_STRING "\n\n" <<
- "usage: " << argv[0] << " {options}\n\n"
- " -c file configurationfile (default: " TNTNET_CONF ")\n"
- " -d enable all debug output (ignoring properties-file)\n";
- return -1;
- }
-
- return app.run();
- }
- catch(const std::exception& e)
- {
- log_fatal(e.what());
- std::cerr << e.what() << std::endl;
- return -1;
- }
-}
-#endif
diff --git a/httpd/worker.cpp b/httpd/worker.cpp
deleted file mode 100644
index 7552db9..0000000
--- a/httpd/worker.cpp
+++ /dev/null
@@ -1,364 +0,0 @@
-/* worker.cpp
- * Copyright (C) 2003-2005 Tommi Maekitalo
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
- * NON-INFRINGEMENT. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#include "tnt/worker.h"
-#include "tnt/dispatcher.h"
-#include "tnt/job.h"
-#include <tnt/httprequest.h>
-#include <tnt/httpreply.h>
-#include <tnt/httperror.h>
-#include <tnt/http.h>
-#include <tnt/poller.h>
-#include <cxxtools/log.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <locale>
-#include <errno.h>
-
-log_define("tntnet.worker")
-
-namespace
-{
- static const char stateStarting[] = "0 starting";
- static const char stateWaitingForJob[] = "1 waiting for job";
- static const char stateParsing[] = "2 parsing request";
- static const char statePostParsing[] = "3 post parsing";
- static const char stateDispatch[] = "4 dispatch";
- static const char stateProcessingRequest[] = "5 processing request";
- static const char stateFlush[] = "6 flush";
- static const char stateSendReply[] = "7 send reply";
- static const char stateSendError[] = "8 send error";
- static const char stateStopping[] = "9 stopping";
-}
-
-namespace tnt
-{
- cxxtools::Mutex Worker::mutex;
- unsigned Worker::nextThreadNumber = 0;
- Worker::workers_type Worker::workers;
- unsigned Worker::maxRequestTime = 600;
- unsigned Worker::minThreads = 5;
- bool Worker::enableCompression = true;
-
- Worker::ComploaderPoolType Worker::comploaderPool;
-
- Worker::Worker(Tntnet& app)
- : application(app),
- comploaderObject(comploaderPool.get()),
- comploader(comploaderObject),
- threadId(0),
- state(stateStarting),
- lastWaitTime(0)
- {
- log_debug("initialize thread " << threadId);
-
- cxxtools::MutexLock lock(mutex);
- workers.insert(this);
- }
-
- Worker::~Worker()
- {
- cxxtools::MutexLock lock(mutex);
- workers.erase(this);
-
- log_debug("delete worker " << threadId << " - " << workers.size() << " threads left - " << application.getQueue().getWaitThreadCount() << " waiting threads");
- }
-
- void Worker::run()
- {
- threadId = pthread_self();
- Jobqueue& queue = application.getQueue();
- log_debug("start thread " << threadId);
- while (queue.getWaitThreadCount() < minThreads)
- {
- log_debug("waiting for job");
- state = stateWaitingForJob;
- Jobqueue::JobPtr j = queue.get();
- if (Tntnet::shouldStop())
- {
- log_warn("stop worker");
- break;
- }
- log_debug("got job - fd=" << j->getFd());
-
- std::iostream& socket = j->getStream();
-
- try
- {
- bool keepAlive;
- do
- {
- time(&lastWaitTime);
-
- log_debug("read request");
-
- keepAlive = false;
- state = stateParsing;
- j->getParser().parse(socket);
- state = statePostParsing;
-
- if (socket.eof())
- log_debug("eof");
- else if (j->getParser().failed())
- {
- state = stateSendError;
- log_warn("bad request");
- socket << "HTTP/1.0 500 bad request\r\n"
- "Content-Type: text/html\r\n"
- "\r\n"
- "<html><body><h1>Error</h1><p>bad request</p></body></html>"
- << std::endl;
- }
- else if (socket.fail())
- log_error("socket failed");
- else
- {
- j->getRequest().doPostParse();
-
- j->setWrite();
- keepAlive = processRequest(j->getRequest(), socket,
- j->decrementKeepAliveCounter());
-
- if (keepAlive)
- {
- j->setRead();
- j->clear();
-
- // if there is something to do and no threads waiting, we take
- // the next job just to improve resposiveness.
- if (queue.getWaitThreadCount() == 0
- && !queue.empty())
- {
- application.getPoller().addIdleJob(j);
- keepAlive = false;
- }
- else
- {
- struct pollfd fd;
- fd.fd = j->getFd();
- fd.events = POLLIN;
- if (::poll(&fd, 1, Job::getSocketReadTimeout()) == 0)
- {
- application.getPoller().addIdleJob(j);
- keepAlive = false;
- }
- }
- }
- }
- } while (keepAlive);
- }
- catch (const cxxtools::net::Timeout& e)
- {
- log_debug("timeout - put job in poller");
- application.getPoller().addIdleJob(j);
- }
- catch (const cxxtools::net::Exception& e)
- {
- if (e.getErrno() != ENOENT)
- log_warn("unexpected exception: " << e.what());
- }
- catch (const std::exception& e)
- {
- log_warn("unexpected exception: " << e.what());
- }
- }
-
- time(&lastWaitTime);
-
- log_debug("end worker-thread " << threadId);
-
- state = stateStopping;
- }
-
- bool Worker::processRequest(HttpRequest& request, std::iostream& socket,
- unsigned keepAliveCount)
- {
- // log message
- log_info("process request: " << request.getMethod() << ' ' << request.getQuery()
- << " from client " << request.getPeerIp() << " user-Agent \"" << request.getUserAgent()
- << '"');
-
- // create reply-object
- HttpReply reply(socket);
- reply.setVersion(request.getMajorVersion(), request.getMinorVersion());
- reply.setMethod(request.getMethod());
-
- std::locale loc = request.getLocale();
- reply.out().imbue(loc);
- reply.sout().imbue(loc);
-
- if (request.keepAlive())
- reply.setKeepAliveCounter(keepAliveCount);
-
- if (enableCompression)
- reply.setAcceptEncoding(request.getEncoding());
-
- // process request
- try
- {
- try
- {
- dispatch(request, reply);
-
- if (!request.keepAlive() || !reply.keepAlive())
- keepAliveCount = 0;
-
- if (keepAliveCount > 0)
- log_debug("keep alive");
- else
- {
- log_debug("no keep alive request/reply="
- << request.keepAlive() << '/' << reply.keepAlive());
- }
- }
- catch (const HttpError& e)
- {
- throw;
- }
- catch (const std::exception& e)
- {
- throw HttpError(HTTP_INTERNAL_SERVER_ERROR, e.what());
- }
- }
- catch (const HttpError& e)
- {
- state = stateSendError;
- log_warn("http-Error: " << e.what());
- HttpReply reply(socket);
- reply.setVersion(request.getMajorVersion(), request.getMinorVersion());
- if (request.keepAlive())
- reply.setKeepAliveCounter(keepAliveCount);
- else
- keepAliveCount = 0;
- reply.out() << "<html><body><h1>Error</h1><p>"
- << e.what() << "</p></body></html>" << std::endl;
- reply.sendReply(e.getErrcode(), e.getErrmsg());
- }
-
- return keepAliveCount > 0;
- }
-
- void Worker::dispatch(HttpRequest& request, HttpReply& reply)
- {
- state = stateDispatch;
- const std::string& url = request.getUrl();
-
- log_debug("dispatch " << request.getQuery());
-
- if (!HttpRequest::checkUrl(url))
- throw HttpError(HTTP_BAD_REQUEST, "illegal url");
-
- request.setThreadScope(threadScope);
-
- Dispatcher::PosType pos(application.getDispatcher(), request.getUrl());
- while (true)
- {
- state = stateDispatch;
-
- // pos.getNext() throws NotFoundException at end
- Dispatcher::CompidentType ci = pos.getNext();
- try
- {
- log_debug("load component " << ci);
- Component& comp = comploader.fetchComp(ci, application.getDispatcher());
- request.setPathInfo(ci.hasPathInfo() ? ci.getPathInfo() : url);
- request.setArgs(ci.getArgs());
-
- application.getScopemanager().preCall(request, ci.libname);
-
- log_debug("call component " << ci << " path " << request.getPathInfo());
- state = stateProcessingRequest;
- unsigned http_return = comp(request, reply, request.getQueryParams());
- if (http_return != DECLINED)
- {
- if (reply.isDirectMode())
- {
- log_info("request ready, returncode " << http_return);
- state = stateFlush;
- reply.out().flush();
- }
- else
- {
- log_info("request ready, returncode " << http_return << " - ContentSize: " << reply.getContentSize());
-
- application.getScopemanager().postCall(request, reply, ci.libname);
-
- state = stateSendReply;
- reply.sendReply(http_return);
- }
-
- if (reply.out())
- log_debug("reply sent");
- else
- log_warn("stream error");
-
- return;
- }
- else
- log_debug("component " << ci << " returned DECLINED");
- }
- catch (const cxxtools::dl::DlopenError& e)
- {
- log_warn("DlopenError catched - libname " << e.getLibname());
- }
- catch (const cxxtools::dl::SymbolNotFound& e)
- {
- log_warn("SymbolNotFound catched - symbol " << e.getSymbol());
- }
- }
-
- throw NotFoundException(request.getUrl());
- }
-
- void Worker::timer()
- {
- time_t currentTime;
- time(&currentTime);
-
- cxxtools::MutexLock lock(mutex);
- for (workers_type::iterator it = workers.begin();
- it != workers.end(); ++it)
- {
- (*it)->healthCheck(currentTime);
- }
- }
-
- void Worker::healthCheck(time_t currentTime)
- {
- if (state == stateProcessingRequest
- && lastWaitTime != 0
- && maxRequestTime > 0)
- {
- if (static_cast<unsigned>(currentTime - lastWaitTime) > maxRequestTime)
- {
- log_fatal("requesttime " << maxRequestTime << " seconds in thread "
- << threadId << " exceeded - exit process");
- log_info("current state: " << state);
- exit(111);
- }
- }
- }
-
- Worker::workers_type::size_type Worker::getCountThreads()
- {
- cxxtools::MutexLock lock(mutex);
- return workers.size();
- }
-}