more
This commit is contained in:
parent
3c4ad2fe50
commit
fde7ed3d3b
1
contrib/backends/nntpchan-daemon/.gitignore
vendored
1
contrib/backends/nntpchan-daemon/.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
*.o
|
*.o
|
||||||
nntpd
|
nntpd
|
||||||
nntpchan-tool
|
nntpchan-tool
|
||||||
|
test
|
||||||
.gdb_history
|
.gdb_history
|
@ -27,8 +27,14 @@ $(EXE): $(OBJECTS)
|
|||||||
$(TOOL): $(OBJECTS)
|
$(TOOL): $(OBJECTS)
|
||||||
$(CXX) -o $(TOOL) $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) tool.cpp
|
$(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
|
%.o: src/%.cpp
|
||||||
$(CXX) $(CXXFLAGS) -c -o $@
|
$(CXX) $(CXXFLAGS) -c -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJECTS) $(EXE) $(TOOL)
|
rm -f $(OBJECTS) $(EXE) $(TOOL) test
|
||||||
|
2
contrib/backends/nntpchan-daemon/contrib/nntpchan.sh
Executable file
2
contrib/backends/nntpchan-daemon/contrib/nntpchan.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
exit 0
|
@ -60,18 +60,18 @@ int main(int argc, char * argv[]) {
|
|||||||
|
|
||||||
if ( level.sections.find("frontend") != level.sections.end()) {
|
if ( level.sections.find("frontend") != level.sections.end()) {
|
||||||
// frontend enabled
|
// frontend enabled
|
||||||
auto & frontconf = level.sections["frontend"];
|
auto & frontconf = level.sections["frontend"].values;
|
||||||
if (frontconf.find("type") == frontconf.end()) {
|
if (frontconf.find("type") == frontconf.end()) {
|
||||||
std::cerr << "frontend section provided but 'type' value not provided" << std::endl;
|
std::cerr << "frontend section provided but 'type' value not provided" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
auto & ftype = frontconf.find("type");
|
auto ftype = frontconf["type"];
|
||||||
if (ftype == "exec") {
|
if (ftype == "exec") {
|
||||||
if (frontconf.find("exec") == frontconf.end()) {
|
if (frontconf.find("exec") == frontconf.end()) {
|
||||||
std::cerr << "exec frontend specified but no 'exec' value provided" << std::endl;
|
std::cerr << "exec frontend specified but no 'exec' value provided" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
nntp.SetFrontend(new nntpchan::ExecFrontend(loop, frontconf["exec"]));
|
nntp.SetFrontend(new nntpchan::ExecFrontend(frontconf["exec"]));
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "unknown frontend type '" << ftype << "'" << std::endl;
|
std::cerr << "unknown frontend type '" << ftype << "'" << std::endl;
|
||||||
}
|
}
|
||||||
|
57
contrib/backends/nntpchan-daemon/src/exec_frontend.cpp
Normal file
57
contrib/backends/nntpchan-daemon/src/exec_frontend.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "exec_frontend.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
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<std::string> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,30 @@
|
|||||||
#ifndef NNTPCHAN_EXEC_FRONTEND_HPP
|
#ifndef NNTPCHAN_EXEC_FRONTEND_HPP
|
||||||
#define NNTPCHAN_EXEC_FRONTEND_HPP
|
#define NNTPCHAN_EXEC_FRONTEND_HPP
|
||||||
|
#include "frontend.hpp"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
namespace nntpchan
|
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<std::string> args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_exec;
|
||||||
|
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#ifndef NNTPCHAN_FRONTEND_HPP
|
#ifndef NNTPCHAN_FRONTEND_HPP
|
||||||
#define NNTPCHAN_FRONTEND_HPP
|
#define NNTPCHAN_FRONTEND_HPP
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace nntpchan
|
namespace nntpchan
|
||||||
{
|
{
|
||||||
@ -10,14 +11,13 @@ namespace nntpchan
|
|||||||
virtual ~Frontend() {}
|
virtual ~Frontend() {}
|
||||||
|
|
||||||
/** @brief process an inbound message stored at fpath that we have accepted. */
|
/** @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 */
|
/** @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 */
|
/** @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;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,21 @@ namespace nntpchan
|
|||||||
{
|
{
|
||||||
uv_tcp_init(loop, &m_server);
|
uv_tcp_init(loop, &m_server);
|
||||||
m_loop = loop;
|
m_loop = loop;
|
||||||
|
m_server.data = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
NNTPServer::~NNTPServer()
|
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)
|
void NNTPServer::Bind(const std::string & addr)
|
||||||
@ -24,7 +34,6 @@ namespace nntpchan
|
|||||||
auto saddr = ParseAddr(addr);
|
auto saddr = ParseAddr(addr);
|
||||||
assert(uv_tcp_bind(*this, saddr, 0) == 0);
|
assert(uv_tcp_bind(*this, saddr, 0) == 0);
|
||||||
std::cerr << "nntp server bound to " << saddr.to_string() << std::endl;
|
std::cerr << "nntp server bound to " << saddr.to_string() << std::endl;
|
||||||
m_server.data = this;
|
|
||||||
auto cb = [] (uv_stream_t * s, int status) {
|
auto cb = [] (uv_stream_t * s, int status) {
|
||||||
NNTPServer * self = (NNTPServer *) s->data;
|
NNTPServer * self = (NNTPServer *) s->data;
|
||||||
self->OnAccept(s, status);
|
self->OnAccept(s, status);
|
||||||
@ -61,6 +70,12 @@ namespace nntpchan
|
|||||||
m_storagePath = path;
|
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) :
|
NNTPServerConn::NNTPServerConn(uv_loop_t * l, uv_stream_t * s, const std::string & storage, NNTPCredentialDB * creds) :
|
||||||
m_handler(storage)
|
m_handler(storage)
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
|
#include "frontend.hpp"
|
||||||
#include "nntp_auth.hpp"
|
#include "nntp_auth.hpp"
|
||||||
#include "nntp_handler.hpp"
|
#include "nntp_handler.hpp"
|
||||||
|
|
||||||
@ -26,6 +27,10 @@ namespace nntpchan
|
|||||||
|
|
||||||
void SetLoginDB(const std::string path);
|
void SetLoginDB(const std::string path);
|
||||||
|
|
||||||
|
void SetFrontend(Frontend * f);
|
||||||
|
|
||||||
|
void Close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
operator uv_handle_t * () { return (uv_handle_t*) &m_server; }
|
operator uv_handle_t * () { return (uv_handle_t*) &m_server; }
|
||||||
@ -40,6 +45,8 @@ namespace nntpchan
|
|||||||
std::string m_logindbpath;
|
std::string m_logindbpath;
|
||||||
std::string m_storagePath;
|
std::string m_storagePath;
|
||||||
|
|
||||||
|
Frontend * m_frontend;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NNTPServerConn
|
class NNTPServerConn
|
||||||
|
13
contrib/backends/nntpchan-daemon/test.cpp
Normal file
13
contrib/backends/nntpchan-daemon/test.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "exec_frontend.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int , char * [])
|
||||||
|
{
|
||||||
|
nntpchan::Frontend * f = new nntpchan::ExecFrontend("./contrib/nntpchan.sh");
|
||||||
|
assert(f->AcceptsMessage("<test@server>"));
|
||||||
|
assert(f->AcceptsNewsgroup("overchan.test"));
|
||||||
|
std::cout << "all good" << std::endl;
|
||||||
|
}
|
0
contrib/frontends/py/frontend.py
Normal file → Executable file
0
contrib/frontends/py/frontend.py
Normal file → Executable file
@ -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
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user