diff --git a/contrib/backends/nntpchan-daemon/.gitignore b/contrib/backends/nntpchan-daemon/.gitignore index f36e035..eeeecc2 100644 --- a/contrib/backends/nntpchan-daemon/.gitignore +++ b/contrib/backends/nntpchan-daemon/.gitignore @@ -1,4 +1,5 @@ *.o nntpd nntpchan-tool +test .gdb_history \ No newline at end of file diff --git a/contrib/backends/nntpchan-daemon/Makefile b/contrib/backends/nntpchan-daemon/Makefile index 7151fc6..b1f8a64 100644 --- a/contrib/backends/nntpchan-daemon/Makefile +++ b/contrib/backends/nntpchan-daemon/Makefile @@ -27,8 +27,14 @@ $(EXE): $(OBJECTS) $(TOOL): $(OBJECTS) $(CXX) -o $(TOOL) $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) tool.cpp +build-test: $(OBJECTS) + $(CXX) -o test $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) test.cpp + +test: build-test + ./test + %.o: src/%.cpp $(CXX) $(CXXFLAGS) -c -o $@ clean: - rm -f $(OBJECTS) $(EXE) $(TOOL) + rm -f $(OBJECTS) $(EXE) $(TOOL) test diff --git a/contrib/backends/nntpchan-daemon/contrib/nntpchan.sh b/contrib/backends/nntpchan-daemon/contrib/nntpchan.sh new file mode 100755 index 0000000..039e4d0 --- /dev/null +++ b/contrib/backends/nntpchan-daemon/contrib/nntpchan.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0 diff --git a/contrib/backends/nntpchan-daemon/nntpd.cpp b/contrib/backends/nntpchan-daemon/nntpd.cpp index 339bc30..a338c24 100644 --- a/contrib/backends/nntpchan-daemon/nntpd.cpp +++ b/contrib/backends/nntpchan-daemon/nntpd.cpp @@ -60,18 +60,18 @@ int main(int argc, char * argv[]) { if ( level.sections.find("frontend") != level.sections.end()) { // frontend enabled - auto & frontconf = level.sections["frontend"]; + auto & frontconf = level.sections["frontend"].values; if (frontconf.find("type") == frontconf.end()) { std::cerr << "frontend section provided but 'type' value not provided" << std::endl; return 1; } - auto & ftype = frontconf.find("type"); + auto ftype = frontconf["type"]; if (ftype == "exec") { if (frontconf.find("exec") == frontconf.end()) { std::cerr << "exec frontend specified but no 'exec' value provided" << std::endl; return 1; } - nntp.SetFrontend(new nntpchan::ExecFrontend(loop, frontconf["exec"])); + nntp.SetFrontend(new nntpchan::ExecFrontend(frontconf["exec"])); } else { std::cerr << "unknown frontend type '" << ftype << "'" << std::endl; } diff --git a/contrib/backends/nntpchan-daemon/src/exec_frontend.cpp b/contrib/backends/nntpchan-daemon/src/exec_frontend.cpp new file mode 100644 index 0000000..220fcdd --- /dev/null +++ b/contrib/backends/nntpchan-daemon/src/exec_frontend.cpp @@ -0,0 +1,57 @@ +#include "exec_frontend.hpp" +#include +#include +#include +#include +#include + +namespace nntpchan +{ + ExecFrontend::ExecFrontend(const std::string & fname) : + m_exec(fname) + { + } + + ExecFrontend::~ExecFrontend() {} + + void ExecFrontend::ProcessNewMessage(const std::string & fpath) + { + Exec({"post", fpath}); + } + + bool ExecFrontend::AcceptsNewsgroup(const std::string & newsgroup) + { + return Exec({"newsgroup", newsgroup}) == 0; + } + + bool ExecFrontend::AcceptsMessage(const std::string & msgid) + { + return Exec({"msgid", msgid}) == 0; + } + + int ExecFrontend::Exec(std::deque args) + { + // set up arguments + const char ** cargs = new char const *[args.size() +2]; + std::size_t l = 0; + cargs[l++] = m_exec.c_str(); + while (args.size()) { + cargs[l++] = args.front().c_str(); + args.pop_front(); + } + cargs[l] = 0; + int retcode = 0; + pid_t child = fork(); + if(child) { + waitpid(child, &retcode, 0); + } else { + int r = execvpe(m_exec.c_str(),(char * const *) cargs, environ); + if ( r == -1 ) { + std::cout << strerror(errno) << std::endl; + exit( errno ); + } else + exit(r); + } + return retcode; + } +} diff --git a/contrib/backends/nntpchan-daemon/src/exec_frontend.hpp b/contrib/backends/nntpchan-daemon/src/exec_frontend.hpp index 3cfbd4c..322b6ed 100644 --- a/contrib/backends/nntpchan-daemon/src/exec_frontend.hpp +++ b/contrib/backends/nntpchan-daemon/src/exec_frontend.hpp @@ -1,9 +1,30 @@ #ifndef NNTPCHAN_EXEC_FRONTEND_HPP #define NNTPCHAN_EXEC_FRONTEND_HPP +#include "frontend.hpp" +#include namespace nntpchan { + class ExecFrontend : public Frontend + { + public: + ExecFrontend(const std::string & exe); + + ~ExecFrontend(); + + void ProcessNewMessage(const std::string & fpath); + bool AcceptsNewsgroup(const std::string & newsgroup); + bool AcceptsMessage(const std::string & msgid); + + private: + + int Exec(std::deque args); + + private: + std::string m_exec; + + }; } #endif diff --git a/contrib/backends/nntpchan-daemon/src/frontend.hpp b/contrib/backends/nntpchan-daemon/src/frontend.hpp index 55699a4..fed48f6 100644 --- a/contrib/backends/nntpchan-daemon/src/frontend.hpp +++ b/contrib/backends/nntpchan-daemon/src/frontend.hpp @@ -1,5 +1,6 @@ #ifndef NNTPCHAN_FRONTEND_HPP #define NNTPCHAN_FRONTEND_HPP +#include namespace nntpchan { @@ -10,14 +11,13 @@ namespace nntpchan virtual ~Frontend() {} /** @brief process an inbound message stored at fpath that we have accepted. */ - void ProcessNewMessage(const std::string & fpath) = 0; + virtual void ProcessNewMessage(const std::string & fpath) = 0; /** @brief return true if we take posts in a newsgroup */ - bool AcceptsNewsgroup(const std::string & newsgroup) = 0; + virtual bool AcceptsNewsgroup(const std::string & newsgroup) = 0; /** @brief return true if we will accept a message given its message-id */ - bool AcceptsMessage(const std::string & msgid) = 0; - + virtual bool AcceptsMessage(const std::string & msgid) = 0; }; } diff --git a/contrib/backends/nntpchan-daemon/src/nntp_server.cpp b/contrib/backends/nntpchan-daemon/src/nntp_server.cpp index 351bc6a..2f40f88 100644 --- a/contrib/backends/nntpchan-daemon/src/nntp_server.cpp +++ b/contrib/backends/nntpchan-daemon/src/nntp_server.cpp @@ -12,11 +12,21 @@ namespace nntpchan { uv_tcp_init(loop, &m_server); m_loop = loop; + m_server.data = this; } NNTPServer::~NNTPServer() { - uv_close((uv_handle_t*)&m_server, [](uv_handle_t *) {}); + if (m_frontend) delete m_frontend; + } + + void NNTPServer::Close() + { + uv_close((uv_handle_t*)&m_server, [](uv_handle_t * s) { + NNTPServer * self = (NNTPServer*)s->data; + if (self) delete self; + s->data = nullptr; + }); } void NNTPServer::Bind(const std::string & addr) @@ -24,7 +34,6 @@ namespace nntpchan auto saddr = ParseAddr(addr); assert(uv_tcp_bind(*this, saddr, 0) == 0); std::cerr << "nntp server bound to " << saddr.to_string() << std::endl; - m_server.data = this; auto cb = [] (uv_stream_t * s, int status) { NNTPServer * self = (NNTPServer *) s->data; self->OnAccept(s, status); @@ -60,6 +69,12 @@ namespace nntpchan { m_storagePath = path; } + + void NNTPServer::SetFrontend(Frontend * f) + { + if(m_frontend) delete m_frontend; + m_frontend = f; + } NNTPServerConn::NNTPServerConn(uv_loop_t * l, uv_stream_t * s, const std::string & storage, NNTPCredentialDB * creds) : m_handler(storage) diff --git a/contrib/backends/nntpchan-daemon/src/nntp_server.hpp b/contrib/backends/nntpchan-daemon/src/nntp_server.hpp index e365ff8..5c36ff7 100644 --- a/contrib/backends/nntpchan-daemon/src/nntp_server.hpp +++ b/contrib/backends/nntpchan-daemon/src/nntp_server.hpp @@ -4,6 +4,7 @@ #include #include #include "storage.hpp" +#include "frontend.hpp" #include "nntp_auth.hpp" #include "nntp_handler.hpp" @@ -25,6 +26,10 @@ namespace nntpchan void SetStoragePath(const std::string & path); void SetLoginDB(const std::string path); + + void SetFrontend(Frontend * f); + + void Close(); private: @@ -39,6 +44,8 @@ namespace nntpchan std::string m_logindbpath; std::string m_storagePath; + + Frontend * m_frontend; }; diff --git a/contrib/backends/nntpchan-daemon/test.cpp b/contrib/backends/nntpchan-daemon/test.cpp new file mode 100644 index 0000000..a84c670 --- /dev/null +++ b/contrib/backends/nntpchan-daemon/test.cpp @@ -0,0 +1,13 @@ +#include "exec_frontend.hpp" +#include +#include + + + +int main(int , char * []) +{ + nntpchan::Frontend * f = new nntpchan::ExecFrontend("./contrib/nntpchan.sh"); + assert(f->AcceptsMessage("")); + assert(f->AcceptsNewsgroup("overchan.test")); + std::cout << "all good" << std::endl; +} diff --git a/contrib/frontends/py/frontend.py b/contrib/frontends/py/frontend.py old mode 100644 new mode 100755 diff --git a/contrib/frontends/py/nntpchan/__init__.py b/contrib/frontends/py/nntpchan/__init__.py index 66c9e23..8b13789 100644 --- a/contrib/frontends/py/nntpchan/__init__.py +++ b/contrib/frontends/py/nntpchan/__init__.py @@ -1,42 +1 @@ -from nntpchan import store -from nntpchan import message -from nntpchan import preprocess - - -def addArticle(msgid, group): - """ - add article to system - :return True if we need to regenerate otherwise False: - """ - msg = None - # open message - with store.openArticle(msgid) as f: - # read article header - hdr = message.readHeader(f) - - mclass = message.MultipartMessage - if hdr.isTextOnly: - # treat as text message instead of multipart - mclass = message.TextMessage - elif hdr.isSigned: - # treat as signed message - mclass = message.TripcodeMessage - # create messgae - msg = mclass(hdr, f) - - if msg is not None: - # we got a message that is valid - store.storeMessage(msg) - else: - # invalid message - print("invalid message: {}".format(msgid)) - return msg is not None - - -def regenerate(msgid, group): - """ - regenerate markup - """ - pass -