Archived
1
0
This repository has been archived on 2023-08-12. You can view files and clone it, but cannot push or open issues or pull requests.
nntpchan/contrib/backends/nntpchan-daemon/libnntpchan/server.cpp

156 lines
2.9 KiB
C++
Raw Normal View History

2017-05-03 17:09:23 +05:00
#include <cassert>
2017-05-03 18:15:06 +05:00
#include <iostream>
2017-10-17 19:29:56 +05:00
#include <nntpchan/net.hpp>
#include <nntpchan/server.hpp>
2017-05-03 17:09:23 +05:00
namespace nntpchan
{
2018-05-03 20:47:20 +05:00
2018-05-06 17:10:20 +05:00
Server::Server(ev::Loop *loop) : ev::io(-1), m_Loop(loop) {}
2017-05-03 17:09:23 +05:00
2018-05-03 20:47:20 +05:00
void Server::close()
2017-10-17 19:29:56 +05:00
{
2018-05-03 20:47:20 +05:00
auto itr = m_conns.begin();
2018-05-06 17:10:20 +05:00
while (itr != m_conns.end())
2018-05-03 20:47:20 +05:00
{
itr = m_conns.erase(itr);
}
m_Loop->UntrackConn(this);
2018-05-03 20:47:20 +05:00
ev::io::close();
2017-10-17 19:29:56 +05:00
}
2018-05-03 20:47:20 +05:00
bool Server::Bind(const std::string &addr)
2017-10-17 19:29:56 +05:00
{
auto saddr = ParseAddr(addr);
return m_Loop->BindTCP(saddr, this);
2017-10-17 19:29:56 +05:00
}
2017-05-03 17:09:23 +05:00
2018-05-04 18:52:54 +05:00
void Server::OnAccept(int f)
2017-10-17 19:29:56 +05:00
{
2018-05-04 18:52:54 +05:00
IServerConn *conn = CreateConn(f);
2018-05-06 17:10:20 +05:00
if (!m_Loop->SetNonBlocking(conn))
2017-05-03 17:09:23 +05:00
{
2018-05-04 18:52:54 +05:00
conn->close();
delete conn;
2017-05-03 17:09:23 +05:00
}
2018-05-06 17:10:20 +05:00
else if (m_Loop->TrackConn(conn))
{
m_conns.push_back(conn);
2018-05-03 20:47:20 +05:00
conn->Greet();
2018-05-04 19:08:09 +05:00
conn->write(1024);
2018-05-03 20:47:20 +05:00
}
2018-05-06 17:10:20 +05:00
else
2018-05-03 20:47:20 +05:00
{
conn->close();
delete conn;
}
}
int Server::accept()
{
2018-05-04 18:52:54 +05:00
int res = ::accept(fd, nullptr, nullptr);
2018-05-06 17:10:20 +05:00
if (res == -1)
return res;
2018-05-04 18:52:54 +05:00
OnAccept(res);
2018-05-03 20:47:20 +05:00
return res;
2017-10-17 19:29:56 +05:00
}
2017-05-03 17:09:23 +05:00
2017-10-17 19:29:56 +05:00
void Server::RemoveConn(IServerConn *conn)
{
auto itr = m_conns.begin();
while (itr != m_conns.end())
2017-05-03 18:15:06 +05:00
{
2017-10-17 19:29:56 +05:00
if (*itr == conn)
itr = m_conns.erase(itr);
else
++itr;
2017-05-03 18:15:06 +05:00
}
m_Loop->UntrackConn(conn);
2017-10-17 19:29:56 +05:00
}
2017-05-03 18:15:06 +05:00
2018-05-06 17:10:20 +05:00
void IConnHandler::QueueLine(const std::string &line) { m_sendlines.push_back(line + "\r\n"); }
2017-05-03 17:09:23 +05:00
2017-10-17 19:29:56 +05:00
bool IConnHandler::HasNextLine() { return m_sendlines.size() > 0; }
2017-05-03 17:09:23 +05:00
2017-10-17 19:29:56 +05:00
std::string IConnHandler::GetNextLine()
{
std::string line = m_sendlines[0];
m_sendlines.pop_front();
return line;
}
2017-05-03 18:15:06 +05:00
2018-05-06 17:10:20 +05:00
IServerConn::IServerConn(int fd, Server *parent, IConnHandler *h) : ev::io(fd), m_parent(parent), m_handler(h) {}
2017-05-03 18:15:06 +05:00
2017-10-17 19:29:56 +05:00
IServerConn::~IServerConn() { delete m_handler; }
2017-05-03 18:15:06 +05:00
2018-05-06 17:10:20 +05:00
int IServerConn::read(char *buf, size_t sz)
2018-05-03 20:47:20 +05:00
{
ssize_t readsz = ::read(fd, buf, sz);
2018-05-06 17:10:20 +05:00
if (readsz > 0)
2018-05-03 20:47:20 +05:00
{
m_handler->OnData(buf, readsz);
}
return readsz;
}
2018-05-06 17:10:20 +05:00
bool IServerConn::keepalive() { return !m_handler->ShouldClose(); }
2018-05-03 20:47:20 +05:00
2018-05-04 19:08:09 +05:00
int IServerConn::write(size_t avail)
2017-10-17 19:29:56 +05:00
{
2018-05-03 20:47:20 +05:00
auto leftovers = m_writeLeftover.size();
ssize_t written;
2018-05-06 17:10:20 +05:00
if (leftovers)
2018-05-03 20:47:20 +05:00
{
2018-05-06 17:10:20 +05:00
if (leftovers > avail)
2018-05-03 20:47:20 +05:00
{
2018-05-04 19:08:09 +05:00
leftovers = avail;
2018-05-03 20:47:20 +05:00
}
written = ::write(fd, m_writeLeftover.c_str(), leftovers);
2018-05-06 17:10:20 +05:00
if (written > 0)
2018-05-03 20:47:20 +05:00
{
2018-05-04 19:08:09 +05:00
avail -= written;
2018-05-03 20:47:20 +05:00
m_writeLeftover = m_writeLeftover.substr(written);
}
2018-05-06 17:10:20 +05:00
else
2018-05-03 20:47:20 +05:00
{
// too much leftovers
return -1;
}
}
do
{
2018-05-06 17:10:20 +05:00
if (!m_handler->HasNextLine())
2018-05-03 20:47:20 +05:00
{
2018-05-04 19:08:09 +05:00
return written;
2018-05-03 20:47:20 +05:00
}
2018-05-04 19:08:09 +05:00
auto line = m_handler->GetNextLine();
int wrote;
2018-05-06 17:10:20 +05:00
if (line.size() <= avail)
2018-05-04 19:08:09 +05:00
{
wrote = ::write(fd, line.c_str(), line.size());
}
else
{
auto subline = line.substr(0, avail);
wrote = ::write(fd, subline.c_str(), subline.size());
}
2018-05-06 17:10:20 +05:00
if (wrote > 0)
2018-05-03 20:47:20 +05:00
{
2018-05-04 19:08:09 +05:00
written += wrote;
m_writeLeftover = line.substr(wrote);
2018-05-03 20:47:20 +05:00
}
else
{
m_writeLeftover = line;
return -1;
}
2018-05-06 17:10:20 +05:00
} while (avail > 0);
2018-05-04 19:08:09 +05:00
return written;
2017-10-17 19:29:56 +05:00
}
2017-05-03 18:15:06 +05:00
2018-05-03 20:47:20 +05:00
void IServerConn::close()
2017-10-17 19:29:56 +05:00
{
m_parent->RemoveConn(this);
2018-05-03 20:47:20 +05:00
ev::io::close();
2017-10-17 19:29:56 +05:00
}
2017-05-03 17:09:23 +05:00
}