E-MailRelay
gnetworkfilter.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 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 gnetworkfilter.cpp
19///
20
21#include "gdef.h"
22#include "gnetworkfilter.h"
23#include "gstr.h"
24#include "gassert.h"
25#include "glog.h"
26
28 GStore::FileStore & file_store , Filter::Type , const Filter::Config & config ,
29 const std::string & server ) :
30 m_es(es) ,
31 m_file_store(file_store) ,
32 m_timer(*this,&NetworkFilter::onTimeout,m_es) ,
33 m_done_signal(true) ,
34 m_location(server) ,
35 m_connection_timeout(config.timeout) ,
36 m_response_timeout(config.timeout) ,
37 m_result(Result::fail)
38{
39 m_client_ptr.eventSignal().connect( G::Slot::slot(*this,&GFilters::NetworkFilter::clientEvent) ) ;
40}
41
43{
44 m_client_ptr.eventSignal().disconnect() ;
45}
46
47std::string GFilters::NetworkFilter::id() const
48{
49 return m_location.displayString() ;
50}
51
52bool GFilters::NetworkFilter::quiet() const
53{
54 return false ;
55}
56
57void GFilters::NetworkFilter::start( const GStore::MessageId & message_id )
58{
59 m_text.clear() ;
60 m_timer.cancelTimer() ;
61 m_done_signal.reset() ;
62 if( m_client_ptr.get() == nullptr || m_client_ptr->busy() )
63 {
64 unsigned int idle_timeout = 0U ;
65 m_client_ptr.reset( std::make_unique<GSmtp::RequestClient>(
66 GNet::ExceptionSink(*this,&m_client_ptr),
67 "scanner" , "ok" ,
68 m_location , m_connection_timeout , m_response_timeout ,
69 idle_timeout ) ) ;
70 }
71 m_client_ptr->request( m_file_store.contentPath(message_id).str() ) ; // (no need to wait for connection)
72}
73
74void GFilters::NetworkFilter::onException( GNet::ExceptionSource * , std::exception & e , bool done )
75{
76 if( m_client_ptr.get() )
77 m_client_ptr->doOnDelete( e.what() , done ) ;
78 m_client_ptr.reset() ;
79
80 sendResult( std::string("failed\t").append(e.what()) ) ;
81}
82
83void GFilters::NetworkFilter::clientEvent( const std::string & s1 , const std::string & s2 , const std::string & )
84{
85 if( s1 == "scanner" ) // ie. this is the response received by the RequestClient
86 {
87 sendResult( s2 ) ;
88 }
89}
90
91void GFilters::NetworkFilter::sendResult( const std::string & reason )
92{
93 if( !m_text.has_value() )
94 {
95 m_text = reason ;
96 m_timer.startTimer( 0 ) ;
97 m_result = m_text.value().empty() ? Result::ok : Result::fail ;
98 }
99}
100
101void GFilters::NetworkFilter::onTimeout()
102{
103 if( m_text.has_value() )
104 m_done_signal.emit( static_cast<int>(m_result) ) ;
105}
106
107GSmtp::Filter::Result GFilters::NetworkFilter::result() const
108{
109 return m_result ;
110}
111
112bool GFilters::NetworkFilter::special() const
113{
114 return false ;
115}
116
117std::pair<std::string,int> GFilters::NetworkFilter::responsePair() const
118{
119 // "[<response-code> ]<response>[<tab><reason>]"
120 std::string s = G::Str::printable( G::Str::head( m_text.value_or({}) , "\t" , false ) ) ;
121 int n = 0 ;
122 if( s.size() >= 3U &&
123 ( s[0] == '4' || s[0] == '5' ) &&
124 ( s[1] >= '0' && s[1] <= '9' ) &&
125 ( s[2] >= '0' && s[2] <= '9' ) &&
126 ( s.size() == 3U || s[3] == ' ' ) )
127 {
128 n = G::Str::toInt( s.substr(0U,3U) ) ;
129 s.erase( 0U , s.size() == 3U ? 3U : 4U ) ;
130 }
131 return {s,n} ;
132}
133
134std::string GFilters::NetworkFilter::response() const
135{
136 return responsePair().first ;
137}
138
139int GFilters::NetworkFilter::responseCode() const
140{
141 return responsePair().second ;
142}
143
144std::string GFilters::NetworkFilter::reason() const
145{
146 return G::Str::printable( G::Str::tail( m_text.value_or({}) , "\t" , false ) ) ;
147}
148
149G::Slot::Signal<int> & GFilters::NetworkFilter::doneSignal() noexcept
150{
151 return m_done_signal ;
152}
153
154void GFilters::NetworkFilter::cancel()
155{
156 m_text.clear() ;
157 m_timer.cancelTimer() ;
158 m_done_signal.emitted( true ) ;
159 m_client_ptr.reset() ;
160}
161
A Filter class that passes the name of a message file to a remote network server.
~NetworkFilter() override
Destructor.
NetworkFilter(GNet::ExceptionSink, GStore::FileStore &, Filter::Type, const Filter::Config &, const std::string &server_location)
Constructor.
G::Slot::Signal< const std::string &, const std::string &, const std::string & > & eventSignal() noexcept
A signal that is linked to the contained client's eventSignal().
Definition: gclientptr.cpp:32
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
A mixin base class that identifies the source of an exception when delivered to GNet::ExceptionHandle...
A concrete implementation of the MessageStore interface dealing in paired flat files.
Definition: gfilestore.h:56
A somewhat opaque identifer for a GStore::MessageStore message id.
Definition: gmessagestore.h:43
static int toInt(string_view s)
Converts string 's' to an int.
Definition: gstr.cpp:541
static std::string printable(const std::string &in, char escape='\\')
Returns a printable representation of the given input string, using chacter code ranges 0x20 to 0x7e ...
Definition: gstr.cpp:916
static std::string tail(string_view in, std::size_t pos, string_view default_={})
Returns the last part of the string after the given position.
Definition: gstr.cpp:1325
static std::string head(string_view in, std::size_t pos, string_view default_={})
Returns the first part of the string up to just before the given position.
Definition: gstr.cpp:1297
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
Definition: gslot.h:240