2016-10-15 18:12:01 +05:00
|
|
|
#include "buffer.hpp"
|
|
|
|
#include "nntp_server.hpp"
|
2016-10-15 22:53:35 +05:00
|
|
|
#include "nntp_auth.hpp"
|
2016-10-15 18:12:01 +05:00
|
|
|
#include "net.hpp"
|
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
namespace nntpchan
|
|
|
|
{
|
|
|
|
NNTPServer::NNTPServer(uv_loop_t * loop)
|
|
|
|
{
|
|
|
|
uv_tcp_init(loop, &m_server);
|
|
|
|
m_loop = loop;
|
2016-10-18 17:17:40 +05:00
|
|
|
m_server.data = this;
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
NNTPServer::~NNTPServer()
|
|
|
|
{
|
2016-10-18 17:17:40 +05:00
|
|
|
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;
|
|
|
|
});
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2016-10-15 22:53:35 +05:00
|
|
|
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);
|
2016-10-15 21:37:59 +05:00
|
|
|
conn->Greet();
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-15 22:53:35 +05:00
|
|
|
void NNTPServer::SetLoginDB(const std::string path)
|
|
|
|
{
|
|
|
|
m_logindbpath = path;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-15 18:12:01 +05:00
|
|
|
void NNTPServer::SetStoragePath(const std::string & path)
|
|
|
|
{
|
|
|
|
m_storagePath = path;
|
|
|
|
}
|
2016-10-18 17:17:40 +05:00
|
|
|
|
|
|
|
void NNTPServer::SetFrontend(Frontend * f)
|
|
|
|
{
|
|
|
|
if(m_frontend) delete m_frontend;
|
|
|
|
m_frontend = f;
|
|
|
|
}
|
2016-10-15 18:12:01 +05:00
|
|
|
|
2016-10-15 22:53:35 +05:00
|
|
|
NNTPServerConn::NNTPServerConn(uv_loop_t * l, uv_stream_t * s, const std::string & storage, NNTPCredentialDB * creds) :
|
2016-10-15 18:12:01 +05:00
|
|
|
m_handler(storage)
|
|
|
|
{
|
2016-10-15 22:53:35 +05:00
|
|
|
m_handler.SetAuth(creds);
|
2016-10-15 18:12:01 +05:00
|
|
|
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;
|
2016-10-15 21:37:59 +05:00
|
|
|
if(self == nullptr) return;
|
2016-10-15 18:12:01 +05:00
|
|
|
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;
|
2016-10-15 21:37:59 +05:00
|
|
|
if(self == nullptr) return;
|
2016-10-15 18:12:01 +05:00
|
|
|
if(nread > 0) {
|
2016-10-15 21:37:59 +05:00
|
|
|
self->m_handler.OnData(b->base, nread);
|
2016-10-15 18:12:01 +05:00
|
|
|
self->SendNextReply();
|
2016-10-15 21:37:59 +05:00
|
|
|
if(self->m_handler.Done())
|
|
|
|
self->Close();
|
2016-10-15 18:12:01 +05:00
|
|
|
} else {
|
|
|
|
if (nread != UV_EOF) {
|
|
|
|
std::cerr << "error in nntp server conn alloc: ";
|
|
|
|
std::cerr << uv_strerror(nread);
|
|
|
|
std::cerr << std::endl;
|
|
|
|
}
|
2016-10-15 21:37:59 +05:00
|
|
|
// got eof or error
|
|
|
|
self->Close();
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-10-15 22:53:35 +05:00
|
|
|
|
2016-10-15 18:12:01 +05:00
|
|
|
void NNTPServerConn::SendNextReply()
|
|
|
|
{
|
|
|
|
if(m_handler.HasNextLine()) {
|
|
|
|
auto line = m_handler.GetNextLine();
|
2016-10-15 21:37:59 +05:00
|
|
|
SendString(line+"\n");
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|
|
|
|
}
|
2016-10-15 21:37:59 +05:00
|
|
|
|
|
|
|
|
|
|
|
void NNTPServerConn::Greet()
|
2016-10-15 18:12:01 +05:00
|
|
|
{
|
2016-10-15 22:53:35 +05:00
|
|
|
m_handler.Greet();
|
|
|
|
SendNextReply();
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|
2016-10-15 21:37:59 +05:00
|
|
|
|
|
|
|
void NNTPServerConn::SendString(const std::string & str)
|
2016-10-15 18:12:01 +05:00
|
|
|
{
|
2016-10-15 21:37:59 +05:00
|
|
|
WriteBuffer * b = new WriteBuffer(str);
|
2016-10-15 18:12:01 +05:00
|
|
|
uv_write(&b->w, *this, &b->b, 1, [](uv_write_t * w, int status) {
|
2016-10-15 21:37:59 +05:00
|
|
|
(void) status;
|
2016-10-15 18:12:01 +05:00
|
|
|
WriteBuffer * wb = (WriteBuffer *) w->data;
|
2016-10-15 21:37:59 +05:00
|
|
|
if(wb)
|
|
|
|
delete wb;
|
2016-10-15 18:12:01 +05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-10-15 21:37:59 +05:00
|
|
|
void NNTPServerConn::Close()
|
2016-10-15 18:12:01 +05:00
|
|
|
{
|
2016-10-15 21:37:59 +05:00
|
|
|
uv_close((uv_handle_t*)&m_conn, [] (uv_handle_t * s) {
|
|
|
|
NNTPServerConn * self = (NNTPServerConn*) s->data;
|
|
|
|
if(self)
|
|
|
|
delete self;
|
|
|
|
s->data = nullptr;
|
|
|
|
});
|
|
|
|
}
|
2016-10-15 18:12:01 +05:00
|
|
|
}
|