summaryrefslogtreecommitdiffhomepage
path: root/plugins
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-13 17:40:09 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-13 17:40:09 +0100
commitc0d9d61e3330d4f69a9547cc3d0e62970fb7427e (patch)
treeffc906ba3ddbe97dbf1042b14063caa7debe141d /plugins
parentd14582a1d92e036780166a0b5ec0494d7353cc75 (diff)
Added webapp-runner
Diffstat (limited to 'plugins')
-rw-r--r--plugins/fcgi/Makefile8
-rw-r--r--plugins/fcgi/fastcgiprocess.cpp84
-rw-r--r--plugins/fcgi/fastcgiprocess.h3
-rw-r--r--plugins/fcgi/webapp-runner.cpp54
4 files changed, 112 insertions, 37 deletions
diff --git a/plugins/fcgi/Makefile b/plugins/fcgi/Makefile
index e878c5d..81502c4 100644
--- a/plugins/fcgi/Makefile
+++ b/plugins/fcgi/Makefile
@@ -27,11 +27,14 @@ PROGSRC=\
SRC=$(PROGSRC)
-all: $(PROJECTNAME).so
+all: $(PROJECTNAME).so webapp-runner
$(PROJECTNAME).so: $(SRC:.cpp=.o)
$(CXX) $(CXXFLAGS) $^ -shared $(LIBS) -o $@
+webapp-runner: webapp-runner.o fastcgiprocess.o
+ $(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@
+
%.d: %.cpp
$(CXX) $(CXXFLAGS) -MM -MP -MF $@ -c $<
@@ -45,13 +48,14 @@ ADD_DEP=Makefile
install:
mkdir -p $(DESTDIR)/usr/lib/webserver/plugins
cp $(PROJECTNAME).so $(DESTDIR)/usr/lib/webserver/plugins
+ cp webapp-runner $(DESTDIR)/usr/bin
# misc ---------------------------------------------------
debs: $(DISTROS)
clean:
- -rm -f *.o *.so *.d
+ -rm -f *.o *.so *.d webapp-runner
.PHONY: clean install all
diff --git a/plugins/fcgi/fastcgiprocess.cpp b/plugins/fcgi/fastcgiprocess.cpp
index dd51583..d43fa75 100644
--- a/plugins/fcgi/fastcgiprocess.cpp
+++ b/plugins/fcgi/fastcgiprocess.cpp
@@ -61,6 +61,51 @@ FastCGIProcess::~FastCGIProcess()
stop();
}
+void run_fcgi_app(const std::string& command, const std::string& host, unsigned short port)
+{
+ boost::asio::io_context ioc;
+ boost::asio::ip::tcp::resolver resolver(ioc);
+ boost::asio::ip::tcp::acceptor acceptor(ioc);
+ auto const results = resolver.resolve(host.c_str(), std::to_string(port).c_str());
+ if (results.begin() == results.end())
+ std::runtime_error("no resolve result");
+ boost::asio::ip::tcp::endpoint endpoint{*results.begin()};
+ acceptor.open(endpoint.protocol());
+ acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor.bind(endpoint);
+ acceptor.listen();
+ int fd{acceptor.native_handle()};
+ if (fd != FCGI_LISTENSOCK_FILENO) {
+ close(FCGI_LISTENSOCK_FILENO);
+ dup2(fd, FCGI_LISTENSOCK_FILENO);
+ close(fd);
+ }
+
+ execl(command.c_str(), command.c_str(), (const char*)nullptr);
+}
+
+void run_fcgi_app(const std::string& command, const std::filesystem::path& socket_path)
+{
+ boost::asio::io_context ioc;
+ boost::asio::local::stream_protocol::acceptor file_acceptor(ioc);
+ std::error_code ec;
+ fs::remove(socket_path, ec); // otherwise we get: "bind: Address already in use"
+
+ boost::asio::local::stream_protocol::endpoint endpoint(socket_path);
+ file_acceptor.open(endpoint.protocol());
+ file_acceptor.set_option(boost::asio::local::stream_protocol::acceptor::reuse_address(true));
+ file_acceptor.bind(endpoint);
+ file_acceptor.listen();
+ int fd {file_acceptor.native_handle()};
+ if (fd != FCGI_LISTENSOCK_FILENO) {
+ close(FCGI_LISTENSOCK_FILENO);
+ dup2(fd, FCGI_LISTENSOCK_FILENO);
+ close(fd);
+ }
+
+ execl(command.c_str(), command.c_str(), (const char*)nullptr);
+}
+
void FastCGIProcess::start()
{
if (m_pid != 0)
@@ -72,41 +117,10 @@ void FastCGIProcess::start()
if (m_pid == 0) { // child process branch
try {
- int fd{};
- boost::asio::io_context ioc;
- boost::asio::ip::tcp::resolver resolver(ioc);
- boost::asio::ip::tcp::acceptor acceptor(ioc);
- boost::asio::local::stream_protocol::acceptor file_acceptor(ioc);
-
- if (m_socket_path.empty()) { // tcp connection
- auto const results = resolver.resolve(m_host.c_str(), std::to_string(m_port).c_str());
- if (results.begin() == results.end())
- std::runtime_error("no resolve result");
- boost::asio::ip::tcp::endpoint endpoint{*results.begin()};
- acceptor.open(endpoint.protocol());
- acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
- acceptor.bind(endpoint);
- acceptor.listen();
- fd = acceptor.native_handle();
- } else { // unix domain socket
- std::error_code ec;
- fs::remove(m_socket_path, ec); // otherwise we get: "bind: Address already in use"
-
- boost::asio::local::stream_protocol::endpoint endpoint(m_socket_path);
- file_acceptor.open(endpoint.protocol());
- file_acceptor.set_option(boost::asio::local::stream_protocol::acceptor::reuse_address(true));
- file_acceptor.bind(endpoint);
- file_acceptor.listen();
- fd = file_acceptor.native_handle();
- }
-
- if (fd != FCGI_LISTENSOCK_FILENO) {
- close(FCGI_LISTENSOCK_FILENO);
- dup2(fd, FCGI_LISTENSOCK_FILENO);
- close(fd);
- }
-
- execl(m_command.c_str(), m_command.c_str(), (const char*)nullptr);
+ if (m_socket_path.empty())
+ run_fcgi_app(m_command, m_host, m_port);
+ else
+ run_fcgi_app(m_command, m_socket_path);
} catch (const std::exception& ex) {
std::cout << "FastCGI process error: " << ex.what() << std::endl;
}
diff --git a/plugins/fcgi/fastcgiprocess.h b/plugins/fcgi/fastcgiprocess.h
index 07b6539..18a5d5b 100644
--- a/plugins/fcgi/fastcgiprocess.h
+++ b/plugins/fcgi/fastcgiprocess.h
@@ -10,6 +10,9 @@
#include <sys/mman.h>
#include <sys/types.h>
+void run_fcgi_app(const std::string& command, const std::string& host, unsigned short port);
+void run_fcgi_app(const std::string& command, const std::filesystem::path& socket_path);
+
class FastCGIProcess
{
public:
diff --git a/plugins/fcgi/webapp-runner.cpp b/plugins/fcgi/webapp-runner.cpp
new file mode 100644
index 0000000..64268f3
--- /dev/null
+++ b/plugins/fcgi/webapp-runner.cpp
@@ -0,0 +1,54 @@
+#include "plugins/fcgi/fastcgiprocess.h"
+
+#include <iostream>
+#include <string>
+
+namespace {
+ void usage()
+ {
+ std::cout << R"(Usage:
+ webapp-runner <host:port> <executable-command>
+
+ or:
+
+ webapp-runner <unix-domain-socket> <executable-command>
+
+Description:
+
+webapp-runner starts the specified executable FastCGI application and connects
+it to the specified unix domain socket or local host:port address. Addresses
+can be specified in IPv4 or IPv6 format.
+
+Examples:
+
+webapp-runner ::1:6543 ./fcgi1
+webapp-runner fcgi-socket0 ./fcgi1
+)" << std::endl;
+ }
+} // namespace
+
+int main(int argc, char* argv[])
+{
+ try {
+ if (argc == 3) {
+ std::string address{argv[1]};
+ std::string command{argv[2]};
+
+ if (auto pos{address.find_last_of(':')}; pos != std::string::npos) {
+ std::string host{address.substr(0, pos)};
+ unsigned short port{static_cast<unsigned short>(std::stoul(address.substr(pos + 1)))};
+ run_fcgi_app(command, host, port);
+ } else {
+ run_fcgi_app(command, address);
+ }
+ } else {
+ usage();
+ exit(0);
+ }
+ } catch (const std::exception& ex) {
+ std::cout << "webapp-runner caught error: " << ex.what() << std::endl;
+ }
+
+ return 0;
+}
+