From d31ca5b6a7790a6b823f30c0f484725b3f948e84 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 15 Oct 2016 12:37:59 -0400 Subject: [PATCH] update dis shit mang --- .../frontends/cpp/nntpchan-daemon/.gitignore | 4 +- .../frontends/cpp/nntpchan-daemon/Makefile | 19 +- .../{src/main.cpp => nntpchan.cpp} | 0 .../cpp/nntpchan-daemon/src/base64.cpp | 234 ++++++++++++++++++ .../cpp/nntpchan-daemon/src/base64.hpp | 17 ++ .../cpp/nntpchan-daemon/src/crypto.cpp | 9 + .../cpp/nntpchan-daemon/src/crypto.hpp | 15 ++ .../cpp/nntpchan-daemon/src/line.cpp | 41 +++ .../cpp/nntpchan-daemon/src/line.hpp | 35 +++ .../cpp/nntpchan-daemon/src/nntp_auth.cpp | 61 +++++ .../cpp/nntpchan-daemon/src/nntp_auth.hpp | 38 +++ .../cpp/nntpchan-daemon/src/nntp_handler.cpp | 74 ++++++ .../cpp/nntpchan-daemon/src/nntp_handler.hpp | 45 ++++ .../cpp/nntpchan-daemon/src/nntp_server.cpp | 73 +++--- .../cpp/nntpchan-daemon/src/nntp_server.hpp | 54 +--- .../cpp/nntpchan-daemon/src/storage.cpp | 4 + .../cpp/nntpchan-daemon/src/storage.hpp | 1 + .../frontends/cpp/nntpchan-daemon/tool.cpp | 18 ++ 18 files changed, 649 insertions(+), 93 deletions(-) rename contrib/frontends/cpp/nntpchan-daemon/{src/main.cpp => nntpchan.cpp} (100%) create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/base64.cpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/base64.hpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/crypto.cpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/crypto.hpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/line.cpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/line.hpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.cpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.hpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.cpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.hpp create mode 100644 contrib/frontends/cpp/nntpchan-daemon/tool.cpp diff --git a/contrib/frontends/cpp/nntpchan-daemon/.gitignore b/contrib/frontends/cpp/nntpchan-daemon/.gitignore index 299a962..f36e035 100644 --- a/contrib/frontends/cpp/nntpchan-daemon/.gitignore +++ b/contrib/frontends/cpp/nntpchan-daemon/.gitignore @@ -1,2 +1,4 @@ *.o -nntpchan \ No newline at end of file +nntpd +nntpchan-tool +.gdb_history \ No newline at end of file diff --git a/contrib/frontends/cpp/nntpchan-daemon/Makefile b/contrib/frontends/cpp/nntpchan-daemon/Makefile index 530acd7..c4cbfe3 100644 --- a/contrib/frontends/cpp/nntpchan-daemon/Makefile +++ b/contrib/frontends/cpp/nntpchan-daemon/Makefile @@ -1,5 +1,7 @@ -EXE = nntpchan +EXE = nntpd + +TOOL = nntpchan-tool CXX = clang++ @@ -9,21 +11,24 @@ SOURCES := $(wildcard $(SRC_PATH)/*.cpp) HEADERS := $(wildcard $(SRC_PATH)/*.hpp) OBJECTS := $(SOURCES:.cpp=.o) -PKGS := libuv +PKGS := libuv libsodium LD_FLAGS := $(shell pkg-config --libs $(PKGS)) INC_FLAGS := -I $(SRC_PATH) $(shell pkg-config --cflags $(PKGS)) -CXXFLAGS := -std=c++14 -Wall -Wextra $(INC_FLAGS) +CXXFLAGS := -std=c++14 -Wall -Wextra $(INC_FLAGS) -g -all: $(EXE) +all: $(EXE) $(TOOL) -$(EXE): $(OBJECTS) - $(CXX) -o $(EXE) $(LD_FLAGS) $(OBJECTS) +$(EXE): $(OBJECTS) + $(CXX) -o $(EXE) $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) nntpchan.cpp + +$(TOOL): $(OBJECTS) + $(CXX) -o $(TOOL) $(LD_FLAGS) $(OBJECTS) $(CXXFLAGS) tool.cpp %.o: src/%.cpp $(CXX) $(CXXFLAGS) -c -o $@ clean: - rm -f $(OBJECTS) $(EXE) + rm -f $(OBJECTS) $(EXE) $(TOOL) diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/main.cpp b/contrib/frontends/cpp/nntpchan-daemon/nntpchan.cpp similarity index 100% rename from contrib/frontends/cpp/nntpchan-daemon/src/main.cpp rename to contrib/frontends/cpp/nntpchan-daemon/nntpchan.cpp diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/base64.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/base64.cpp new file mode 100644 index 0000000..f36a36c --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/base64.cpp @@ -0,0 +1,234 @@ +#include "base64.hpp" + + +// taken from i2pd +namespace i2p +{ +namespace data +{ + static void iT64Build(void); + + /* + * + * BASE64 Substitution Table + * ------------------------- + * + * Direct Substitution Table + */ + + static const char T64[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/' + }; + + + /* + * Reverse Substitution Table (built in run time) + */ + + static char iT64[256]; + static int isFirstTime = 1; + + /* + * Padding + */ + + static char P64 = '='; + + /* + * + * ByteStreamToBase64 + * ------------------ + * + * Converts binary encoded data to BASE64 format. + * + */ + static size_t /* Number of bytes in the encoded buffer */ + ByteStreamToBase64 ( + const uint8_t * InBuffer, /* Input buffer, binary data */ + size_t InCount, /* Number of bytes in the input buffer */ + char * OutBuffer, /* output buffer */ + size_t len /* length of output buffer */ + ) + + { + unsigned char * ps; + unsigned char * pd; + unsigned char acc_1; + unsigned char acc_2; + int i; + int n; + int m; + size_t outCount; + + ps = (unsigned char *)InBuffer; + n = InCount/3; + m = InCount%3; + if (!m) + outCount = 4*n; + else + outCount = 4*(n+1); + if (outCount > len) return 0; + pd = (unsigned char *)OutBuffer; + for ( i = 0; i>= 2; /* base64 digit #1 */ + *pd++ = T64[acc_1]; + acc_1 = *ps++; + acc_2 |= acc_1 >> 4; /* base64 digit #2 */ + *pd++ = T64[acc_2]; + acc_1 &= 0x0f; + acc_1 <<=2; + acc_2 = *ps++; + acc_1 |= acc_2>>6; /* base64 digit #3 */ + *pd++ = T64[acc_1]; + acc_2 &= 0x3f; /* base64 digit #4 */ + *pd++ = T64[acc_2]; + } + if ( m == 1 ){ + acc_1 = *ps++; + acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */ + acc_1 >>= 2; /* base64 digit #1 */ + *pd++ = T64[acc_1]; + *pd++ = T64[acc_2]; + *pd++ = P64; + *pd++ = P64; + + } + else if ( m == 2 ){ + acc_1 = *ps++; + acc_2 = (acc_1<<4)&0x3f; + acc_1 >>= 2; /* base64 digit #1 */ + *pd++ = T64[acc_1]; + acc_1 = *ps++; + acc_2 |= acc_1 >> 4; /* base64 digit #2 */ + *pd++ = T64[acc_2]; + acc_1 &= 0x0f; + acc_1 <<=2; /* base64 digit #3 */ + *pd++ = T64[acc_1]; + *pd++ = P64; + } + + return outCount; + } + + /* + * + * Base64ToByteStream + * ------------------ + * + * Converts BASE64 encoded data to binary format. If input buffer is + * not properly padded, buffer of negative length is returned + * + */ + static + ssize_t /* Number of output bytes */ + Base64ToByteStream ( + const char * InBuffer, /* BASE64 encoded buffer */ + size_t InCount, /* Number of input bytes */ + uint8_t * OutBuffer, /* output buffer length */ + size_t len /* length of output buffer */ + ) + { + unsigned char * ps; + unsigned char * pd; + unsigned char acc_1; + unsigned char acc_2; + int i; + int n; + int m; + size_t outCount; + + if (isFirstTime) iT64Build(); + n = InCount/4; + m = InCount%4; + if (InCount && !m) + outCount = 3*n; + else { + outCount = 0; + return 0; + } + + ps = (unsigned char *)(InBuffer + InCount - 1); + while ( *ps-- == P64 ) outCount--; + ps = (unsigned char *)InBuffer; + + if (outCount > len) return -1; + pd = OutBuffer; + auto endOfOutBuffer = OutBuffer + outCount; + for ( i = 0; i < n; i++ ){ + acc_1 = iT64[*ps++]; + acc_2 = iT64[*ps++]; + acc_1 <<= 2; + acc_1 |= acc_2>>4; + *pd++ = acc_1; + if (pd >= endOfOutBuffer) break; + + acc_2 <<= 4; + acc_1 = iT64[*ps++]; + acc_2 |= acc_1 >> 2; + *pd++ = acc_2; + if (pd >= endOfOutBuffer) break; + + acc_2 = iT64[*ps++]; + acc_2 |= acc_1 << 6; + *pd++ = acc_2; + } + + return outCount; + } + + static size_t Base64EncodingBufferSize (const size_t input_size) + { + auto d = div (input_size, 3); + if (d.rem) d.quot++; + return 4*d.quot; + } + + /* + * + * iT64 + * ---- + * Reverse table builder. P64 character is replaced with 0 + * + * + */ + + static void iT64Build() + { + int i; + isFirstTime = 0; + for ( i=0; i<256; i++ ) iT64[i] = -1; + for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i; + iT64[(int)P64] = 0; + } + + +} +} + +namespace nntpchan +{ + std::string B64Encode(const uint8_t * data, const std::size_t l) + { + std::string out; + out.reserve(i2p::data::Base64EncodingBufferSize(l)); + i2p::data::ByteStreamToBase64(data, l, &out[0], out.capacity()); + return out; + } + + bool B64Decode(const std::string & data, std::vector & out) + { + out.resize(data.size()); + if(i2p::data::Base64ToByteStream(data.c_str(), data.size(), &out[0], out.size()) == -1) return false; + out.shrink_to_fit(); + return true; + } +} diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/base64.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/base64.hpp new file mode 100644 index 0000000..be51346 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/base64.hpp @@ -0,0 +1,17 @@ +#ifndef NNTPCHAN_BASE64_HPP +#define NNTPCHAN_BASE64_HPP +#include +#include + +namespace nntpchan +{ + /** returns base64 encoded string */ + std::string B64Encode(const uint8_t * data, const std::size_t l); + + /** @brief returns true if decode was successful */ + bool B64Decode(const std::string & data, std::vector & out); + +} + + +#endif diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/crypto.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/crypto.cpp new file mode 100644 index 0000000..5ca5c0b --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/crypto.cpp @@ -0,0 +1,9 @@ +#include "crypto.hpp" + +namespace nntpchan +{ + void SHA512(const uint8_t * d, const std::size_t l, SHA512Digest & h) + { + crypto_hash(h.data(), d, l); + } +} diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/crypto.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/crypto.hpp new file mode 100644 index 0000000..fd529f7 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/crypto.hpp @@ -0,0 +1,15 @@ +#ifndef NNTPCHAN_CRYPTO_HPP +#define NNTPCHAN_CRYPTO_HPP + +#include +#include + +namespace nntpchan +{ + typedef std::array SHA512Digest; + + void SHA512(const uint8_t * d, std::size_t l, SHA512Digest & h); +} + + +#endif diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/line.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/line.cpp new file mode 100644 index 0000000..5eebbf5 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/line.cpp @@ -0,0 +1,41 @@ +#include "line.hpp" +#include + +namespace nntpchan { + + void LineReader::OnData(const char * d, ssize_t l) + { + if(l <= 0) return; + std::size_t idx = 0; + while(l-- > 0) { + char c = d[idx++]; + if(c == '\n') { + OnLine(d, idx-2); + d += idx; + } + } + } + + void LineReader::OnLine(const char *d, const size_t l) + { + std::string line(d, l); + HandleLine(line); + } + + bool LineReader::HasNextLine() + { + return m_sendlines.size() > 0; + } + + std::string LineReader::GetNextLine() + { + std::string line = m_sendlines[0]; + m_sendlines.pop_front(); + return line; + } + + void LineReader::QueueLine(const std::string & line) + { + m_sendlines.push_back(line); + } +} diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/line.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/line.hpp new file mode 100644 index 0000000..d838371 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/line.hpp @@ -0,0 +1,35 @@ +#ifndef NNTPCHAN_LINE_HPP +#define NNTPCHAN_LINE_HPP +#include +#include +namespace nntpchan +{ + + /** @brief a buffered line reader */ + class LineReader + { + public: + + + /** @brief queue inbound data from connection */ + void OnData(const char * data, ssize_t s); + + /** @brief do we have line to send to the client? */ + bool HasNextLine(); + /** @brief get the next line to send to the client, does not check if it exists */ + std::string GetNextLine(); + + protected: + /** @brief handle a line from the client */ + virtual void HandleLine(const std::string & line) = 0; + /** @brief queue the next line to send to the client */ + void QueueLine(const std::string & line); + + private: + void OnLine(const char * d, const size_t l); + // lines to send + std::deque m_sendlines; + }; +} + +#endif diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.cpp new file mode 100644 index 0000000..dfedab8 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.cpp @@ -0,0 +1,61 @@ +#include "nntp_auth.hpp" +#include "crypto.hpp" +#include "base64.hpp" +#include +#include +#include + +namespace nntpchan +{ + HashedCredDB::HashedCredDB(std::istream & i) : + m_instream(i) {} + + bool HashedCredDB::CheckLogin(const std::string & user, const std::string & passwd) + { + std::unique_lock lock(m_access); + m_found = false; + m_user = user; + m_passwd = passwd; + m_instream.seekg(0, std::ios::end); + const auto l = m_instream.tellg(); + m_instream.seekg(0, std::ios::beg); + char * buff = new char[l]; + // read file + m_instream.read(buff, l); + OnData(buff, l); + delete [] buff; + return m_found; + } + + bool HashedCredDB::ProcessLine(const std::string & line) + { + // strip comments + auto comment = line.find("#"); + std::string part = line; + for (; comment != std::string::npos; comment = part.find("#")) { + if(comment) + part = part.substr(0, comment); + else break; + } + if(!part.size()) return false; // empty line after comments + auto idx = part.find(":"); + if (idx == std::string::npos) return false; // bad format + if (m_user != part.substr(0, idx)) return false; // username mismatch + part = part.substr(idx+1); + + idx = part.find(":"); + if (idx == std::string::npos) return false; // bad format + std::string cred = part.substr(0, idx); + std::string salt = part.substr(idx+1); + return Hash(m_passwd, salt) == cred; + } + + std::string HashedCredDB::Hash(const std::string & data, const std::string & salt) + { + SHA512Digest h; + std::string d = data + salt; + SHA512((const uint8_t*)d.c_str(), d.size(), h); + return B64Encode(h.data(), h.size()); + } +} + diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.hpp new file mode 100644 index 0000000..8eccf6b --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_auth.hpp @@ -0,0 +1,38 @@ +#ifndef NNTPCHAN_NNTP_AUTH_HPP +#define NNTPCHAN_NNTP_AUTH_HPP +#include +#include +#include +#include "line.hpp" + +namespace nntpchan +{ + /** @brief nntp credential db interface */ + class NNTPCredentialDB + { + public: + /** @brief return true if username password combo is correct */ + virtual bool CheckLogin(const std::string & user, const std::string & passwd) = 0; + }; + + /** @brief nntp credential db using hashed+salted passwords */ + class HashedCredDB : public NNTPCredentialDB, public LineReader + { + public: + HashedCredDB(std::istream & i); + bool CheckLogin(const std::string & user, const std::string & passwd); + protected: + std::string Hash(const std::string & data, const std::string & salt); + private: + + bool ProcessLine(const std::string & line); + + std::mutex m_access; + std::string m_user, m_passwd; + bool m_found; + /** return true if we have a line that matches this username / password combo */ + std::istream & m_instream; + }; +} + +#endif diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.cpp new file mode 100644 index 0000000..269b692 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.cpp @@ -0,0 +1,74 @@ +#include "nntp_handler.hpp" +#include +#include +#include +#include +#include + +namespace nntpchan +{ + NNTPServerHandler::NNTPServerHandler(const std::string & storage) : + m_store(storage), + m_authed(false), + m_state(eStateReadCommand) + { + } + + void NNTPServerHandler::HandleLine(const std::string &line) + { + if(m_state == eStateReadCommand) { + std::deque command; + std::istringstream s; + s.str(line); + for (std::string part; std::getline(s, part, ' '); ) { + if(part.size()) command.push_back(std::string(part)); + } + if(command.size()) + HandleCommand(command); + else + QueueLine("501 Syntax error"); + } + } + + void NNTPServerHandler::HandleCommand(const std::deque & command) + { + auto cmd = command[0]; + std::transform(cmd.begin(), cmd.end(), cmd.begin(), + [](unsigned char ch) { return std::toupper(ch); }); + std::size_t cmdlen = command.size(); + std::cerr << "handle command [" << cmd << "] " << (int) cmdlen << std::endl; + if (cmd == "QUIT") { + Quit(); + return; + } else if (cmd == "MODE" ) { + if(cmdlen == 1) { + // set mode + SwitchMode(command[1]); + } else if(cmdlen) { + // too many arguments + } else { + // get mode + } + + } else { + // unknown command + QueueLine("500 Unknown Command"); + } + } + + void NNTPServerHandler::SwitchMode(const std::string & mode) + { + } + + void NNTPServerHandler::Quit() + { + std::cerr << "quitting" << std::endl; + m_state = eStateQuit; + QueueLine("205 quitting"); + } + + bool NNTPServerHandler::Done() + { + return m_state == eStateQuit; + } +} diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.hpp new file mode 100644 index 0000000..46554f8 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_handler.hpp @@ -0,0 +1,45 @@ +#ifndef NNTPCHAN_NNTP_HANDLER_HPP +#define NNTPCHAN_NNTP_HANDLER_HPP +#include +#include +#include "line.hpp" +#include "storage.hpp" + +namespace nntpchan +{ + class NNTPServerHandler : public LineReader + { + public: + NNTPServerHandler(const std::string & storage); + + bool Done(); + + protected: + void HandleLine(const std::string & line); + void HandleCommand(const std::deque & command); + private: + + enum State { + eStateReadCommand, + eStateStoreArticle, + eStateQuit + }; + + private: + // handle quit command, this queues a reply + void Quit(); + + // switch nntp modes, this queues a reply + void SwitchMode(const std::string & mode); + + private: + + ArticleStorage m_store; + std::string m_mode; + bool m_authed; + State m_state; + }; +} + + +#endif diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.cpp index 353e2f9..0867366 100644 --- a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.cpp +++ b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.cpp @@ -39,7 +39,7 @@ namespace nntpchan return; } NNTPServerConn * conn = new NNTPServerConn(m_loop, s, m_storagePath); - conn->SendCode(200, "Posting Allowed"); + conn->Greet(); } @@ -56,6 +56,7 @@ namespace nntpchan uv_accept(s, (uv_stream_t*) &m_conn); uv_read_start((uv_stream_t*) &m_conn, [] (uv_handle_t * h, size_t s, uv_buf_t * b) { NNTPServerConn * self = (NNTPServerConn*) h->data; + if(self == nullptr) return; b->base = self->m_readbuff; if (s > sizeof(self->m_readbuff)) b->len = sizeof(self->m_readbuff); @@ -63,70 +64,56 @@ namespace nntpchan b->len = s; }, [] (uv_stream_t * s, ssize_t nread, const uv_buf_t * b) { NNTPServerConn * self = (NNTPServerConn*) s->data; + if(self == nullptr) return; if(nread > 0) { - self->ProcessData(b->base, nread); + self->m_handler.OnData(b->base, nread); self->SendNextReply(); + if(self->m_handler.Done()) + self->Close(); } else { if (nread != UV_EOF) { std::cerr << "error in nntp server conn alloc: "; std::cerr << uv_strerror(nread); std::cerr << std::endl; } - - delete self; - s->data = nullptr; - + // got eof or error + self->Close(); } }); } - NNTPServerConn::~NNTPServerConn() - { - uv_close((uv_handle_t*)&m_conn, [] (uv_handle_t *) {}); - } - - void NNTPServerConn::ProcessData(const char *d, ssize_t l) - { - m_handler.OnData(d, l); - } - void NNTPServerConn::SendNextReply() { if(m_handler.HasNextLine()) { auto line = m_handler.GetNextLine(); - SendLine(line); + SendString(line+"\n"); } } - - void NNTPServerConn::SendCode(const int code, const std::string & msg) - { - std::stringstream ss; - ss << code << " " << msg << std::endl; - SendString(ss.str()); - } - void NNTPServerConn::SendString(const std::string & line) - { - WriteBuffer * b = new WriteBuffer(line); - uv_write(&b->w, *this, &b->b, 1, [](uv_write_t * w, int status) { - WriteBuffer * wb = (WriteBuffer *) w->data; - delete wb; - }); - } - NNTPServerHandler::NNTPServerHandler(const std::string & storagepath) : - m_state(eNNTPStateGreet) - { - m_storage.SetPath(storagepath); - } - - NNTPServerHandler::~NNTPServerHandler() - { - } - - void NNTPServerHandler::OnData(const char * d, ssize_t l) + void NNTPServerConn::Greet() { } + + void NNTPServerConn::SendString(const std::string & str) + { + WriteBuffer * b = new WriteBuffer(str); + uv_write(&b->w, *this, &b->b, 1, [](uv_write_t * w, int status) { + (void) status; + WriteBuffer * wb = (WriteBuffer *) w->data; + if(wb) + delete wb; + }); + } + void NNTPServerConn::Close() + { + uv_close((uv_handle_t*)&m_conn, [] (uv_handle_t * s) { + NNTPServerConn * self = (NNTPServerConn*) s->data; + if(self) + delete self; + s->data = nullptr; + }); + } } diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.hpp index ea2fffe..20be6b4 100644 --- a/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.hpp +++ b/contrib/frontends/cpp/nntpchan-daemon/src/nntp_server.hpp @@ -2,12 +2,14 @@ #define NNTPCHAN_NNTP_SERVER_HPP #include #include -#include +#include #include "storage.hpp" +#include "nntp_auth.hpp" +#include "nntp_handler.hpp" namespace nntpchan { - + class NNTPServerConn; class NNTPServer @@ -31,58 +33,24 @@ namespace nntpchan uv_tcp_t m_server; uv_loop_t * m_loop; - std::vector m_conns; + std::deque m_conns; std::string m_storagePath; }; - - - class NNTPServerHandler - { - public: - - enum State { - eNNTPStateGreet, - eNNTPStateHandshake, - eNNTPStateReader, - eNNTPStateStream, - eNNTPStateTAKETHIS, - eNNTPStateIHAVE, - eNNTPStateARTICLE, - eNNTPStatePOST - }; - - NNTPServerHandler(const std::string & storagepath); - ~NNTPServerHandler(); - - void OnData(const char * data, ssize_t s); - - bool HasNextLine(); - std::string GetNextLine(); - - private: - State m_state; - ArticleStorage m_storage; - }; - class NNTPServerConn { public: NNTPServerConn(uv_loop_t * l, uv_stream_t * s, const std::string & storage); - virtual ~NNTPServerConn(); + /** @brief close connection, this connection cannot be used after calling this */ void Close(); - - void Quit(); - - void SendLine(const std::string & line); - void SendCode(const int code, const std::string & message); - - void ProcessData(const char * d, ssize_t l); + /** @brief send next queued reply */ void SendNextReply(); + + void Greet(); private: @@ -94,8 +62,10 @@ namespace nntpchan uv_tcp_t m_conn; NNTPServerHandler m_handler; + + NNTPCredentialDB * m_logindb; - char m_readbuff[1024]; + char m_readbuff[1028]; }; } diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/storage.cpp b/contrib/frontends/cpp/nntpchan-daemon/src/storage.cpp index b81e8f5..02e34c7 100644 --- a/contrib/frontends/cpp/nntpchan-daemon/src/storage.cpp +++ b/contrib/frontends/cpp/nntpchan-daemon/src/storage.cpp @@ -9,6 +9,10 @@ namespace nntpchan { } + ArticleStorage::ArticleStorage(const std::string & fpath) { + SetPath(fpath); + } + ArticleStorage::~ArticleStorage() { } diff --git a/contrib/frontends/cpp/nntpchan-daemon/src/storage.hpp b/contrib/frontends/cpp/nntpchan-daemon/src/storage.hpp index 60e2a69..9a7401f 100644 --- a/contrib/frontends/cpp/nntpchan-daemon/src/storage.hpp +++ b/contrib/frontends/cpp/nntpchan-daemon/src/storage.hpp @@ -10,6 +10,7 @@ namespace nntpchan { public: ArticleStorage(); + ArticleStorage(const std::string & fpath); ~ArticleStorage(); void SetPath(const std::string & fpath); diff --git a/contrib/frontends/cpp/nntpchan-daemon/tool.cpp b/contrib/frontends/cpp/nntpchan-daemon/tool.cpp new file mode 100644 index 0000000..7dfbb67 --- /dev/null +++ b/contrib/frontends/cpp/nntpchan-daemon/tool.cpp @@ -0,0 +1,18 @@ +#include "base64.hpp" +#include "crypto.hpp" + +#include +#include + +static void print_help(const std::string & exename) +{ + std::cout << "usage: " << exename << " [help|passwd|genconf]" << std::endl; +} + +int main(int argc, char * argv[]) +{ + if(argc == 1) { + print_help(argv[0]); + return 1; + } +}