parent
4ca867ceab
commit
a4abb2ac91
22 changed files with 351 additions and 345 deletions
@ -1,41 +0,0 @@ |
||||
#ifndef _SMTPD_REQUEST_ |
||||
#define _SMTPD_REQUEST_ |
||||
|
||||
#include <smtpd/session.hpp> |
||||
#include <smtpd/message.hpp> |
||||
#include <smtpd/mail.hpp> |
||||
#include <smtpd/types.hpp> |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
#include <any> |
||||
|
||||
namespace smtpd { |
||||
class FilterRequest { |
||||
public: |
||||
FilterRequest(Session & session, RequestToken requestToken); |
||||
|
||||
// Responses
|
||||
|
||||
void sendFilterResult(TokenVector tokenVector); |
||||
|
||||
void submitMail(const Mail & mail); |
||||
|
||||
void proceed(); |
||||
void junk(); |
||||
void fail(String response = "451 Aborted"); |
||||
void commit(); |
||||
|
||||
Session & session; |
||||
const RequestToken requestToken; |
||||
std::any data; |
||||
|
||||
private: |
||||
TokenVector withAddress(TokenVector tokenVector); |
||||
|
||||
void submitMailSection(const StringVector & lines, bool isBody); |
||||
void submitDataLine(const String & line, bool inBody); |
||||
}; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,27 @@ |
||||
#include <smtpd/mail.hpp> |
||||
#include <smtpd/types.hpp> |
||||
#include <smtpd/token.hpp> |
||||
|
||||
#include <any> |
||||
#include <functional> |
||||
|
||||
namespace smtpd { |
||||
class Request { |
||||
public: |
||||
void proceed(); |
||||
void junk(); |
||||
void fail(std::string response = "451 Aborted"); |
||||
void commit(); |
||||
|
||||
void sendFilterResult(TokenPattern pattern); |
||||
void submitMail(const Mail & mail); |
||||
|
||||
std::any payload; |
||||
|
||||
std::function<void(Token command, TokenPattern arguments)> send; |
||||
|
||||
private: |
||||
void submitMailSection(const std::vector<std::string> & lines, bool isBody); |
||||
void submitDataLine(std::string line, bool inBody); |
||||
}; |
||||
} |
@ -1,28 +1,15 @@ |
||||
#ifndef _SMTPD_SESSION_ |
||||
#define _SMTPD_SESSION_ |
||||
|
||||
#include <smtpd/protocol.hpp> |
||||
#include <smtpd/request.hpp> |
||||
#include <smtpd/types.hpp> |
||||
|
||||
#include <unordered_map> |
||||
#include <functional> |
||||
|
||||
namespace smtpd { |
||||
class Session; |
||||
|
||||
using SessionMap = std::unordered_map<SessionID, Session>; |
||||
using ProtocolMap = std::unordered_map<size_t, SessionMap>; |
||||
using RequestMap = std::unordered_map<RequestToken, Request>; |
||||
|
||||
class Session { |
||||
public: |
||||
Protocol & protocol; |
||||
const SessionID id; |
||||
RequestMap requests; |
||||
|
||||
Session(Protocol & protocol, const SessionID & sessionID); |
||||
static void sessionListener(Protocol & protocol, const Message & message); |
||||
|
||||
private: |
||||
static ProtocolMap protocolMap; |
||||
std::function<void(Token command, Token requestID, TokenPattern arguments)> send; |
||||
}; |
||||
} |
||||
|
||||
#endif |
||||
} |
@ -0,0 +1,132 @@ |
||||
#include <vector> |
||||
#include <map> |
||||
#include <iterator> |
||||
|
||||
template <class T> |
||||
class sparse_vector { |
||||
std::map<size_t, T> map; |
||||
size_t _size = 0; |
||||
|
||||
public: |
||||
const T empty; |
||||
|
||||
template <class U> |
||||
class iterator : public std::iterator<std::input_iterator_tag, U> { |
||||
sparse_vector<U> & vector; |
||||
size_t index; |
||||
|
||||
public: |
||||
iterator(sparse_vector<U> & vector, size_t index) : vector(vector), index(index) {} |
||||
iterator(const iterator<U> & from) : vector(from.vector), index(from.index) {} |
||||
|
||||
// Prefix increment operator
|
||||
iterator<U> & operator++() { |
||||
++index; |
||||
return *this; |
||||
} |
||||
|
||||
// Postfix increment operator
|
||||
iterator<U> operator++(int) { |
||||
iterator<U> tmp(*this); |
||||
operator++(); |
||||
return tmp; |
||||
} |
||||
|
||||
bool operator==(const iterator<U> & rhs) const { |
||||
return index == rhs.index; |
||||
} |
||||
|
||||
bool operator!=(const iterator<U> & rhs) const { |
||||
return index != rhs.index; |
||||
} |
||||
|
||||
U & operator*() const { |
||||
return vector.at(index); |
||||
} |
||||
}; |
||||
|
||||
sparse_vector() {} |
||||
|
||||
// Construct from element list given as arguments
|
||||
sparse_vector(std::initializer_list<T> list) { |
||||
size_t index = 0; |
||||
for(auto element : list) { |
||||
map[index] = element; |
||||
} |
||||
} |
||||
|
||||
// Copy constructor
|
||||
sparse_vector(const sparse_vector<T> & svector) { |
||||
map = svector.map; |
||||
_size = svector._size; |
||||
} |
||||
|
||||
// Move constructor
|
||||
sparse_vector(sparse_vector<T> && svector) { |
||||
map = std::move(svector.map); |
||||
_size = svector._size; |
||||
svector._size = 0; |
||||
} |
||||
|
||||
// Construct from regular vector
|
||||
sparse_vector(const std::vector<T> vector) { |
||||
for(size_t index = 0; index < vector.size(); ++index) { |
||||
map[index] = vector.at(index); |
||||
} |
||||
_size = vector.size(); |
||||
} |
||||
|
||||
// Move assignment operator
|
||||
sparse_vector<T> & operator=(sparse_vector<T> && svector) { |
||||
map = std::move(svector.map); |
||||
size = svector._size; |
||||
svector._size = 0; |
||||
return *this; |
||||
} |
||||
|
||||
size_t size() const { |
||||
return _size; |
||||
} |
||||
|
||||
const T & at(size_t index) const { |
||||
return map.at(index); |
||||
} |
||||
|
||||
bool has(size_t index) const { |
||||
return map.count(index) == 1; |
||||
} |
||||
|
||||
void push_back(const T & element) { |
||||
map[_size++] = element; |
||||
} |
||||
|
||||
template <class Range> |
||||
void push_back(Range range) { |
||||
for(T & element : range) { |
||||
push_back(element); |
||||
} |
||||
} |
||||
|
||||
T pop_back() { |
||||
--_size; |
||||
if(has(_size)) { |
||||
T element = map->at(_size); |
||||
map.erase(_size); |
||||
return element; |
||||
} |
||||
|
||||
return empty; |
||||
} |
||||
|
||||
iterator<T> begin() const { |
||||
return iterator<T>(*this, 0); |
||||
} |
||||
|
||||
iterator<T> end() const { |
||||
return iterator<T>(*this, size()); |
||||
} |
||||
|
||||
T & operator[](size_t index) { |
||||
return map[index]; |
||||
} |
||||
}; |
@ -1,53 +0,0 @@ |
||||
#include <smtpd/filter_request.hpp> |
||||
|
||||
using namespace std; |
||||
|
||||
namespace smtpd { |
||||
FilterRequest::FilterRequest(Session & session, RequestToken requestToken) : |
||||
session(session), requestToken(requestToken) { } |
||||
|
||||
void FilterRequest::sendFilterResult(TokenVector tokenVector) { |
||||
tokenVector.insert(tokenVector.begin(), {"filter-result", "", ""}); |
||||
session.protocol.send(withAddress(tokenVector)); |
||||
} |
||||
|
||||
void FilterRequest::proceed() { |
||||
sendFilterResult({"proceed"}); |
||||
} |
||||
|
||||
void FilterRequest::junk() { |
||||
sendFilterResult({"junk"}); |
||||
} |
||||
|
||||
void FilterRequest::fail(String response) { |
||||
sendFilterResult({"disconnect", response}); |
||||
} |
||||
|
||||
void FilterRequest::submitMail(const Mail & mail) { |
||||
submitMailSection(mail.header, false); |
||||
submitMailSection(mail.body, true); |
||||
} |
||||
|
||||
void FilterRequest::submitMailSection(const StringVector & lines, bool isBody) { |
||||
for(auto line : lines) { |
||||
submitDataLine(line, isBody); |
||||
} |
||||
submitDataLine(isBody ? "." : "", false); |
||||
} |
||||
|
||||
void FilterRequest::submitDataLine(const String & line, bool inBody) { |
||||
session.protocol.send(withAddress({"filter-dataline", "?", "?", |
||||
inBody && line == "." ? ".." : line})); |
||||
} |
||||
|
||||
TokenVector FilterRequest::withAddress(TokenVector tokenVector) { |
||||
if(session.protocol.version < "0.5") { |
||||
tokenVector.at(1) = requestToken; |
||||
tokenVector.at(2) = session.id; |
||||
} else { |
||||
tokenVector.at(1) = session.id; |
||||
tokenVector.at(2) = requestToken; |
||||
} |
||||
return tokenVector; |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
#include <smtpd/request.hpp> |
||||
|
||||
#include <vector> |
||||
#include <string> |
||||
|
||||
using namespace std; |
||||
|
||||
namespace smtpd { |
||||
void Request::proceed() { |
||||
send("filter-result", {"proceed"}); |
||||
} |
||||
|
||||
void Request::junk() { |
||||
send("filter-result", {"junk"}); |
||||
} |
||||
|
||||
void Request::fail(string response) { |
||||
send("filter-result", {"disconnect", response}); |
||||
} |
||||
|
||||
void Request::submitMail(const Mail & mail) { |
||||
submitMailSection(mail.header, false); |
||||
submitMailSection(mail.body, true); |
||||
} |
||||
|
||||
void Request::submitMailSection(const vector<string> & lines, bool isBody) { |
||||
for(auto line : lines) { |
||||
submitDataLine(line, isBody); |
||||
} |
||||
submitDataLine(isBody ? "." : "", false); |
||||
} |
||||
|
||||
void Request::submitDataLine(string line, bool inBody) { |
||||
send("filter-dataline", {inBody && line == "." ? ".." : line}); |
||||
} |
||||
} |
@ -1,31 +1,5 @@ |
||||
#include <smtpd/protocol.hpp> |
||||
#include <smtpd/session.hpp> |
||||
|
||||
using namespace std; |
||||
|
||||
namespace smtpd { |
||||
ProtocolMap Session::protocolMap{}; |
||||
|
||||
Session::Session(Protocol & protocol, const SessionID & sessionID) : |
||||
protocol(protocol), id(sessionID) { } |
||||
|
||||
void Session::sessionListener(Protocol & protocol, const Message & message) { |
||||
size_t protocolID = hash<Protocol *>{}(&protocol); |
||||
SessionMap * pSessionMap; |
||||
try { |
||||
pSessionMap = &protocolMap.at(protocolID); |
||||
} catch(out_of_range & e) { |
||||
auto element = protocolMap.emplace(protocolID, SessionMap{}); |
||||
pSessionMap = &element.first->second; |
||||
} |
||||
|
||||
Session * pSession; |
||||
auto sessionID = message.sessionID(); |
||||
try { |
||||
pSession = &pSessionMap->at(sessionID); |
||||
} catch(out_of_range & e) { |
||||
auto element = pSessionMap->emplace(sessionID, Session{protocol, sessionID}); |
||||
pSession = &element.first->second; |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue