E-MailRelay

gsmtpserverbufferin.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gsmtpserverbufferin.cpp
19///
20
21#include "gdef.h"
22#include "gsmtpserverbufferin.h"
23#include "glog.h"
24#include "gassert.h"
25
26 GSmtp::ServerBufferIn::ServerBufferIn( GNet::EventState es , ServerProtocol & protocol ,
27 const Config & config ) :
28 m_protocol(protocol) ,
29 m_config(config) ,
30 m_line_buffer(GNet::LineBuffer::Config::smtp()) ,
31 m_timer(*this,&ServerBufferIn::onTimeout,es)
32{
33 m_protocol.changeSignal().connect( G::Slot::slot(*this,&ServerBufferIn::onProtocolChange) ) ;
34}
35
36 GSmtp::ServerBufferIn::~ServerBufferIn()
37{
38 m_protocol.changeSignal().disconnect() ;
39}
40
41 void GSmtp::ServerBufferIn::apply( const char * data , std::size_t size )
42{
43 applySome( data , size ) ;
44 if( m_timer.active() && overLimit() )
45 flowOff() ;
46}
47
48 void GSmtp::ServerBufferIn::onTimeout()
49{
50 applySome( nullptr , 0U ) ;
51 if( !m_timer.active() )
52 flowOn() ;
53}
54
55 void GSmtp::ServerBufferIn::applySome( const char * data , std::size_t size )
56{
57 if( m_protocol.inBusyState() )
58 {
59 G_ASSERT( m_timer.active() ) ;
60 m_line_buffer.add( data , size ) ;
61 }
62 else if( !m_line_buffer.apply( std::bind(&ServerProtocol::apply,&m_protocol,std::placeholders::_1) ,
63 {data,size} , std::bind(&ServerProtocol::inDataState,&m_protocol) ) )
64 {
65 // ServerProtocol::apply() returned false
66 G_ASSERT( m_protocol.inBusyState() ) ;
67 m_timer.startTimer( G::TimeInterval::limit() ) ;
68 }
69 else
70 {
71 m_timer.cancelTimer() ;
72 }
73 G_ASSERT( m_timer.active() == m_protocol.inBusyState() ) ;
74 if( overHardLimit() )
75 throw Overflow() ; // (if flow-control is not working)
76}
77
78 bool GSmtp::ServerBufferIn::overLimit() const
79{
80 return m_line_buffer.buffersize() >= std::max(std::size_t(1U),m_config.input_buffer_soft_limit) ;
81}
82
83 bool GSmtp::ServerBufferIn::overHardLimit() const
84{
85 return m_config.input_buffer_hard_limit && m_line_buffer.buffersize() >= m_config.input_buffer_hard_limit ;
86}
87
88 void GSmtp::ServerBufferIn::flowOn()
89{
90 if( !m_flow_on )
91 {
92 m_flow_on = true ;
93 m_flow_signal.emit( true ) ;
94 }
95}
96
97 void GSmtp::ServerBufferIn::flowOff()
98{
99 if( m_flow_on )
100 {
101 m_flow_on = false ;
102 m_flow_signal.emit( false ) ;
103 }
104}
105
106 void GSmtp::ServerBufferIn::onProtocolChange()
107{
108 if( m_timer.active() )
109 m_timer.startTimer( 0U ) ;
110}
111
112 void GSmtp::ServerBufferIn::expect( std::size_t n )
113{
114 m_line_buffer.expect( n ) ;
115}
116
117std::string GSmtp::ServerBufferIn::head() const
118{
119 return m_line_buffer.state().head() ;
120}
121
122 G::Slot::Signal<bool> & GSmtp::ServerBufferIn::flowSignal() noexcept
123{
124 return m_flow_signal ;
125}
126
GNet::EventState
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
GSmtp::ServerBufferIn
A helper class for GSmtp::ServerProtocol that does buffering of data received from the remote peer an...
Definition: gsmtpserverbufferin.h:74
GSmtp::ServerBufferIn::flowSignal
G::Slot::Signal< bool > & flowSignal() noexcept
Returns a signal that should be connected to a function that controls network flow control,...
Definition: gsmtpserverbufferin.cpp:122
GSmtp::ServerBufferIn::head
std::string head() const
Returns GNet::LineBufferState::head().
Definition: gsmtpserverbufferin.cpp:117
GSmtp::ServerBufferIn::~ServerBufferIn
~ServerBufferIn()
Destructor.
Definition: gsmtpserverbufferin.cpp:36
GSmtp::ServerBufferIn::expect
void expect(std::size_t)
Forwards to GNet::LineBuffer::expect().
Definition: gsmtpserverbufferin.cpp:112
GSmtp::ServerBufferIn::apply
void apply(const char *, std::size_t)
Called when raw data is received from the peer.
Definition: gsmtpserverbufferin.cpp:41
GSmtp::ServerBufferIn::ServerBufferIn
ServerBufferIn(GNet::EventState, ServerProtocol &, const Config &)
Constructor.
Definition: gsmtpserverbufferin.cpp:26
GSmtp::ServerProtocol
Implements the SMTP server-side protocol.
Definition: gsmtpserverprotocol.h:80
GSmtp::ServerProtocol::changeSignal
G::Slot::Signal & changeSignal() noexcept
A signal that is emitted at the end of apply() or whenever the protocol state might have changed by s...
Definition: gsmtpserverprotocol.cpp:130
GSmtp::ServerProtocol::apply
bool apply(const ApplyArgsTuple &)
Called on receipt of a complete line of text from the client, or possibly a line fragment iff this ob...
Definition: gsmtpserverprotocol.cpp:253
GSmtp::ServerProtocol::inDataState
bool inDataState() const
Returns true if currently in a data-transfer state meaning that the next apply() does not need to con...
Definition: gsmtpserverprotocol.cpp:186
G::TimeInterval::limit
static TimeInterval limit()
Factory function for the maximum valid interval.
Definition: gdatetime.cpp:638
gassert.h
glog.h
gsmtpserverbufferin.h
GNet
Network classes.
Definition: gdef.h:1243
G::Slot::slot
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
Definition: gslot.h:240
GSmtp::ServerBufferIn::Config
A configuration structure for GSmtp::ServerBufferIn.
Definition: gsmtpserverbufferin.h:79
G::Slot::Signal< bool >