compiles
This commit is contained in:
parent
07e62d2057
commit
dba185c6aa
@ -6,7 +6,7 @@ namespace nntpchan
|
|||||||
{
|
{
|
||||||
|
|
||||||
/** @brief a buffered line reader */
|
/** @brief a buffered line reader */
|
||||||
class LineReader : public IConnHandler
|
class LineReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -21,6 +21,11 @@ namespace nntpchan
|
|||||||
if(m_auth) delete m_auth;
|
if(m_auth) delete m_auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NNTPServerHandler::OnData(const char * data, ssize_t sz)
|
||||||
|
{
|
||||||
|
LineReader::OnData(data, sz);
|
||||||
|
}
|
||||||
|
|
||||||
void NNTPServerHandler::HandleLine(const std::string &line)
|
void NNTPServerHandler::HandleLine(const std::string &line)
|
||||||
{
|
{
|
||||||
if(m_state == eStateReadCommand) {
|
if(m_state == eStateReadCommand) {
|
||||||
@ -92,7 +97,7 @@ namespace nntpchan
|
|||||||
QueueLine("205 quitting");
|
QueueLine("205 quitting");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NNTPServerHandler::Done()
|
bool NNTPServerHandler::ShouldClose()
|
||||||
{
|
{
|
||||||
return m_state == eStateQuit;
|
return m_state == eStateQuit;
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,25 @@
|
|||||||
|
|
||||||
namespace nntpchan
|
namespace nntpchan
|
||||||
{
|
{
|
||||||
class NNTPServerHandler : public LineReader
|
class NNTPServerHandler : public LineReader, public IConnHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NNTPServerHandler(const std::string & storage);
|
NNTPServerHandler(const std::string & storage);
|
||||||
~NNTPServerHandler();
|
~NNTPServerHandler();
|
||||||
|
|
||||||
bool Done();
|
virtual bool ShouldClose();
|
||||||
|
|
||||||
|
virtual void OnData(const char * data, ssize_t sz);
|
||||||
|
|
||||||
void SetAuth(NNTPCredentialDB * creds);
|
void SetAuth(NNTPCredentialDB * creds);
|
||||||
|
|
||||||
void Greet();
|
void Greet();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void HandleLine(const std::string & line);
|
void HandleLine(const std::string & line);
|
||||||
void HandleCommand(const std::deque<std::string> & command);
|
void HandleCommand(const std::deque<std::string> & command);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
eStateReadCommand,
|
eStateReadCommand,
|
||||||
eStateStoreArticle,
|
eStateStoreArticle,
|
||||||
@ -39,7 +41,7 @@ namespace nntpchan
|
|||||||
void SwitchMode(const std::string & mode);
|
void SwitchMode(const std::string & mode);
|
||||||
|
|
||||||
bool PostingAllowed();
|
bool PostingAllowed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NNTPCredentialDB * m_auth;
|
NNTPCredentialDB * m_auth;
|
||||||
ArticleStorage m_store;
|
ArticleStorage m_store;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "buffer.hpp"
|
|
||||||
#include "nntp_server.hpp"
|
#include "nntp_server.hpp"
|
||||||
#include "nntp_auth.hpp"
|
#include "nntp_auth.hpp"
|
||||||
|
#include "nntp_handler.hpp"
|
||||||
#include "net.hpp"
|
#include "net.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -8,56 +9,29 @@
|
|||||||
|
|
||||||
namespace nntpchan
|
namespace nntpchan
|
||||||
{
|
{
|
||||||
NNTPServer::NNTPServer(uv_loop_t * loop)
|
|
||||||
{
|
NNTPServer::NNTPServer(uv_loop_t * loop) : Server(loop), m_frontend(nullptr) {}
|
||||||
uv_tcp_init(loop, &m_server);
|
|
||||||
m_loop = loop;
|
|
||||||
m_server.data = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
NNTPServer::~NNTPServer()
|
NNTPServer::~NNTPServer()
|
||||||
{
|
{
|
||||||
if (m_frontend) delete m_frontend;
|
if (m_frontend) delete m_frontend;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NNTPServer::Close()
|
IServerConn * NNTPServer::CreateConn(uv_stream_t * s)
|
||||||
{
|
{
|
||||||
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)
|
|
||||||
{
|
|
||||||
auto saddr = ParseAddr(addr);
|
|
||||||
assert(uv_tcp_bind(*this, saddr, 0) == 0);
|
|
||||||
std::cerr << "nntp server bound to " << saddr.to_string() << std::endl;
|
|
||||||
auto cb = [] (uv_stream_t * s, int status) {
|
|
||||||
NNTPServer * self = (NNTPServer *) s->data;
|
|
||||||
self->OnAccept(s, status);
|
|
||||||
};
|
|
||||||
|
|
||||||
assert(uv_listen(*this, 5, cb) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NNTPServer::OnAccept(uv_stream_t * s, int status)
|
|
||||||
{
|
|
||||||
if(status < 0) {
|
|
||||||
std::cerr << "nntp server OnAccept fail: " << uv_strerror(status) << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NNTPCredentialDB * creds = nullptr;
|
NNTPCredentialDB * creds = nullptr;
|
||||||
|
|
||||||
std::ifstream i;
|
std::ifstream i;
|
||||||
i.open(m_logindbpath);
|
i.open(m_logindbpath);
|
||||||
if(i.is_open()) creds = new HashedFileDB(m_logindbpath);
|
if(i.is_open()) creds = new HashedFileDB(m_logindbpath);
|
||||||
|
|
||||||
NNTPServerConn * conn = new NNTPServerConn(m_loop, s, m_storagePath, creds);
|
NNTPServerHandler * handler = new NNTPServerHandler(m_storagePath);
|
||||||
conn->Greet();
|
if(creds)
|
||||||
}
|
handler->SetAuth(creds);
|
||||||
|
|
||||||
|
NNTPServerConn * conn = new NNTPServerConn(GetLoop(), s, this, handler);
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
void NNTPServer::SetLoginDB(const std::string path)
|
void NNTPServer::SetLoginDB(const std::string path)
|
||||||
{
|
{
|
||||||
@ -76,74 +50,28 @@ namespace nntpchan
|
|||||||
m_frontend = f;
|
m_frontend = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
NNTPServerConn::NNTPServerConn(uv_loop_t * l, uv_stream_t * s, const std::string & storage, NNTPCredentialDB * creds) :
|
void NNTPServer::OnAcceptError(int status)
|
||||||
m_handler(storage)
|
|
||||||
{
|
{
|
||||||
m_handler.SetAuth(creds);
|
std::cerr << "nntpserver::accept() " << uv_strerror(status) << std::endl;
|
||||||
uv_tcp_init(l, &m_conn);
|
|
||||||
m_conn.data = this;
|
|
||||||
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);
|
|
||||||
else
|
|
||||||
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->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;
|
|
||||||
}
|
|
||||||
// got eof or error
|
|
||||||
self->Close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NNTPServerConn::SendNextReply()
|
void NNTPServerConn::SendNextReply()
|
||||||
{
|
{
|
||||||
if(m_handler.HasNextLine()) {
|
IConnHandler * handler = GetHandler();
|
||||||
auto line = m_handler.GetNextLine();
|
if(handler->HasNextLine()) {
|
||||||
SendString(line+"\n");
|
auto line = handler->GetNextLine();
|
||||||
|
SendString(line + "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NNTPServerConn::Greet()
|
void NNTPServerConn::Greet()
|
||||||
{
|
{
|
||||||
m_handler.Greet();
|
IConnHandler * handler = GetHandler();
|
||||||
|
handler->Greet();
|
||||||
SendNextReply();
|
SendNextReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,25 +3,19 @@
|
|||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include "storage.hpp"
|
|
||||||
#include "frontend.hpp"
|
#include "frontend.hpp"
|
||||||
#include "nntp_auth.hpp"
|
#include "server.hpp"
|
||||||
#include "nntp_handler.hpp"
|
|
||||||
|
|
||||||
namespace nntpchan
|
namespace nntpchan
|
||||||
{
|
{
|
||||||
|
|
||||||
class NNTPServerConn;
|
class NNTPServer : public Server
|
||||||
|
|
||||||
class NNTPServer
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NNTPServer(uv_loop_t * loop);
|
NNTPServer(uv_loop_t * loop);
|
||||||
~NNTPServer();
|
|
||||||
|
|
||||||
void Bind(const std::string & addr);
|
virtual ~NNTPServer();
|
||||||
|
|
||||||
void OnAccept(uv_stream_t * s, int status);
|
|
||||||
|
|
||||||
void SetStoragePath(const std::string & path);
|
void SetStoragePath(const std::string & path);
|
||||||
|
|
||||||
@ -30,50 +24,33 @@ namespace nntpchan
|
|||||||
void SetFrontend(Frontend * f);
|
void SetFrontend(Frontend * f);
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
virtual IServerConn * CreateConn(uv_stream_t * s);
|
||||||
|
|
||||||
|
virtual void OnAcceptError(int status);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
operator uv_handle_t * () { return (uv_handle_t*) &m_server; }
|
|
||||||
operator uv_tcp_t * () { return &m_server; }
|
|
||||||
operator uv_stream_t * () { return (uv_stream_t *) &m_server; }
|
|
||||||
|
|
||||||
uv_tcp_t m_server;
|
|
||||||
uv_loop_t * m_loop;
|
|
||||||
|
|
||||||
std::deque<NNTPServerConn *> m_conns;
|
|
||||||
|
|
||||||
std::string m_logindbpath;
|
std::string m_logindbpath;
|
||||||
std::string m_storagePath;
|
std::string m_storagePath;
|
||||||
|
|
||||||
Frontend * m_frontend;
|
Frontend * m_frontend;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NNTPServerConn
|
class NNTPServerConn : public IServerConn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NNTPServerConn(uv_loop_t * l, uv_stream_t * s, const std::string & storage, NNTPCredentialDB * creds);
|
|
||||||
/** @brief close connection, this connection cannot be used after calling this */
|
NNTPServerConn(uv_loop_t * l, uv_stream_t * s, Server * parent, IConnHandler * h) : IServerConn(l, s, parent, h) {}
|
||||||
void Close();
|
|
||||||
|
virtual bool IsTimedOut() { return false; };
|
||||||
|
|
||||||
/** @brief send next queued reply */
|
/** @brief send next queued reply */
|
||||||
void SendNextReply();
|
virtual void SendNextReply();
|
||||||
|
|
||||||
void Greet();
|
virtual void Greet();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void SendString(const std::string & line);
|
|
||||||
|
|
||||||
|
|
||||||
operator uv_stream_t * () { return (uv_stream_t *) &m_conn; }
|
|
||||||
|
|
||||||
uv_tcp_t m_conn;
|
|
||||||
|
|
||||||
NNTPServerHandler m_handler;
|
|
||||||
|
|
||||||
char m_readbuff[1028];
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
#include "buffer.hpp"
|
||||||
#include "server.hpp"
|
#include "server.hpp"
|
||||||
#include "net.hpp"
|
#include "net.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace nntpchan
|
namespace nntpchan
|
||||||
{
|
{
|
||||||
@ -42,6 +44,18 @@ namespace nntpchan
|
|||||||
conn->Greet();
|
conn->Greet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::RemoveConn(IServerConn * conn)
|
||||||
|
{
|
||||||
|
auto itr = m_conns.begin();
|
||||||
|
while(itr != m_conns.end())
|
||||||
|
{
|
||||||
|
if(*itr == conn)
|
||||||
|
itr = m_conns.erase(itr);
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IConnHandler::QueueLine(const std::string & line)
|
void IConnHandler::QueueLine(const std::string & line)
|
||||||
{
|
{
|
||||||
m_sendlines.push_back(line);
|
m_sendlines.push_back(line);
|
||||||
@ -58,4 +72,68 @@ namespace nntpchan
|
|||||||
m_sendlines.pop_front();
|
m_sendlines.pop_front();
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IServerConn::IServerConn(uv_loop_t * l, uv_stream_t * s, Server * parent, IConnHandler * h)
|
||||||
|
{
|
||||||
|
m_loop = l;
|
||||||
|
m_stream = s;
|
||||||
|
m_parent = parent;
|
||||||
|
m_handler = h;
|
||||||
|
uv_tcp_init(l, &m_conn);
|
||||||
|
m_conn.data = this;
|
||||||
|
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) {
|
||||||
|
IServerConn * self = (IServerConn*) h->data;
|
||||||
|
if(self == nullptr) return;
|
||||||
|
b->base = self->m_readbuff;
|
||||||
|
if (s > sizeof(self->m_readbuff))
|
||||||
|
b->len = sizeof(self->m_readbuff);
|
||||||
|
else
|
||||||
|
b->len = s;
|
||||||
|
}, [] (uv_stream_t * s, ssize_t nread, const uv_buf_t * b) {
|
||||||
|
IServerConn * self = (IServerConn*) s->data;
|
||||||
|
if(self == nullptr) return;
|
||||||
|
if(nread > 0) {
|
||||||
|
self->m_handler->OnData(b->base, nread);
|
||||||
|
self->SendNextReply();
|
||||||
|
if(self->m_handler->ShouldClose())
|
||||||
|
self->Close();
|
||||||
|
} else {
|
||||||
|
if (nread != UV_EOF) {
|
||||||
|
std::cerr << "error in nntp server conn alloc: ";
|
||||||
|
std::cerr << uv_strerror(nread);
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
// got eof or error
|
||||||
|
self->Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
IServerConn::~IServerConn()
|
||||||
|
{
|
||||||
|
delete m_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IServerConn::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 IServerConn::Close()
|
||||||
|
{
|
||||||
|
m_parent->RemoveConn(this);
|
||||||
|
uv_close((uv_handle_t*)&m_conn, [] (uv_handle_t * s) {
|
||||||
|
IServerConn * self = (IServerConn*) s->data;
|
||||||
|
if(self)
|
||||||
|
delete self;
|
||||||
|
s->data = nullptr;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace nntpchan
|
namespace nntpchan
|
||||||
{
|
{
|
||||||
@ -14,6 +13,9 @@ namespace nntpchan
|
|||||||
|
|
||||||
struct IConnHandler
|
struct IConnHandler
|
||||||
{
|
{
|
||||||
|
|
||||||
|
virtual ~IConnHandler() {};
|
||||||
|
|
||||||
/** got inbound data */
|
/** got inbound data */
|
||||||
virtual void OnData(const char * data, ssize_t s) = 0;
|
virtual void OnData(const char * data, ssize_t s) = 0;
|
||||||
|
|
||||||
@ -29,6 +31,9 @@ namespace nntpchan
|
|||||||
/** queue a data send */
|
/** queue a data send */
|
||||||
void QueueLine(const std::string & line);
|
void QueueLine(const std::string & line);
|
||||||
|
|
||||||
|
virtual void Greet() = 0;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::deque<std::string> m_sendlines;
|
std::deque<std::string> m_sendlines;
|
||||||
};
|
};
|
||||||
@ -37,20 +42,23 @@ namespace nntpchan
|
|||||||
struct IServerConn
|
struct IServerConn
|
||||||
{
|
{
|
||||||
IServerConn(uv_loop_t * l, uv_stream_t * s, Server * parent, IConnHandler * h);
|
IServerConn(uv_loop_t * l, uv_stream_t * s, Server * parent, IConnHandler * h);
|
||||||
virtual ~IServerConn() = 0;
|
virtual ~IServerConn();
|
||||||
virtual void Close() = 0;
|
virtual void Close();
|
||||||
virtual void Greet() = 0;
|
virtual void Greet() = 0;
|
||||||
virtual void SendNextReply() = 0;
|
virtual void SendNextReply() = 0;
|
||||||
virtual bool IsTimedOut() = 0;
|
virtual bool IsTimedOut() = 0;
|
||||||
|
void SendString(const std::string & str);
|
||||||
Server * Parent() { return m_parent; };
|
Server * Parent() { return m_parent; };
|
||||||
IConnHandler * GetHandler() { return m_handler; };
|
IConnHandler * GetHandler() { return m_handler; };
|
||||||
operator uv_stream_t * () { return m_stream; };
|
operator uv_stream_t * () { return m_stream; };
|
||||||
uv_loop_t * GetLoop() { return m_loop; };
|
uv_loop_t * GetLoop() { return m_loop; };
|
||||||
private:
|
private:
|
||||||
|
uv_tcp_t m_conn;
|
||||||
uv_stream_t * m_stream;
|
uv_stream_t * m_stream;
|
||||||
uv_loop_t * m_loop;
|
uv_loop_t * m_loop;
|
||||||
Server * m_parent;
|
Server * m_parent;
|
||||||
IConnHandler * m_handler;
|
IConnHandler * m_handler;
|
||||||
|
char m_readbuff[4096];
|
||||||
};
|
};
|
||||||
|
|
||||||
class Server
|
class Server
|
||||||
@ -83,7 +91,7 @@ namespace nntpchan
|
|||||||
operator uv_stream_t * () { return (uv_stream_t *) &m_server; }
|
operator uv_stream_t * () { return (uv_stream_t *) &m_server; }
|
||||||
|
|
||||||
void OnAccept(uv_stream_t * s, int status);
|
void OnAccept(uv_stream_t * s, int status);
|
||||||
std::vector<IServerConn *> m_conns;
|
std::deque<IServerConn *> m_conns;
|
||||||
uv_tcp_t m_server;
|
uv_tcp_t m_server;
|
||||||
uv_loop_t * m_loop;
|
uv_loop_t * m_loop;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user