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