E-MailRelay
gnetworkfilter.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 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{
38 m_client_ptr.eventSignal().connect( G::Slot::slot(*this,&GFilters::NetworkFilter::clientEvent) ) ;
39}
40
42{
43 m_client_ptr.eventSignal().disconnect() ;
44}
45
46std::string GFilters::NetworkFilter::id() const
47{
48 return m_location.displayString() ;
49}
50
51bool GFilters::NetworkFilter::quiet() const
52{
53 return false ;
54}
55
56void GFilters::NetworkFilter::start( const GStore::MessageId & message_id )
57{
58 m_text.reset() ;
59 m_timer.cancelTimer() ;
60 m_done_signal.reset() ;
61 if( m_client_ptr.get() == nullptr || m_client_ptr->busy() )
62 {
63 unsigned int idle_timeout = 0U ;
64 m_client_ptr.reset( std::make_unique<GSmtp::RequestClient>(
65 m_es.eh(this) ,
66 "scanner" , "ok" ,
67 m_location , m_connection_timeout , m_response_timeout ,
68 idle_timeout ) ) ;
69 }
70 m_client_ptr->request( m_file_store.contentPath(message_id).str() ) ; // (no need to wait for connection)
71}
72
73void GFilters::NetworkFilter::onException( GNet::ExceptionSource * , std::exception & e , bool done )
74{
75 if( m_client_ptr.get() )
76 m_client_ptr->doOnDelete( e.what() , done ) ;
77 m_client_ptr.reset() ;
78
79 sendResult( std::string("failed\t").append(e.what()) ) ;
80}
81
82void GFilters::NetworkFilter::clientEvent( const std::string & s1 , const std::string & s2 , const std::string & )
83{
84 if( s1 == "scanner" ) // ie. this is the response received by the RequestClient
85 {
86 sendResult( s2 ) ;
87 }
88}
89
90void GFilters::NetworkFilter::sendResult( const std::string & reason )
91{
92 if( !m_text.has_value() )
93 {
94 m_text = reason ;
95 m_timer.startTimer( 0 ) ;
96 m_result = m_text.value().empty() ? Result::ok : Result::fail ;
97 }
98}
99
100void GFilters::NetworkFilter::onTimeout()
101{
102 if( m_text.has_value() )
103 m_done_signal.emit( static_cast<int>(m_result) ) ;
104}
105
106GSmtp::Filter::Result GFilters::NetworkFilter::result() const
107{
108 return m_result ;
109}
110
111bool GFilters::NetworkFilter::special() const
112{
113 return false ;
114}
115
116std::pair<std::string,int> GFilters::NetworkFilter::responsePair() const
117{
118 // "[<response-code> ]<response>[<tab><reason>]"
119 std::string s = G::Str::printable( G::Str::head( m_text.value_or(std::string()) , "\t" , false ) ) ;
120 int n = 0 ;
121 if( s.size() >= 3U &&
122 ( s[0] == '4' || s[0] == '5' ) &&
123 ( s[1] >= '0' && s[1] <= '9' ) &&
124 ( s[2] >= '0' && s[2] <= '9' ) &&
125 ( s.size() == 3U || s[3] == ' ' ) )
126 {
127 n = G::Str::toInt( s.substr(0U,3U) ) ;
128 s.erase( 0U , s.size() == 3U ? 3U : 4U ) ;
129 }
130 return {s,n} ;
131}
132
133std::string GFilters::NetworkFilter::response() const
134{
135 return responsePair().first ;
136}
137
138int GFilters::NetworkFilter::responseCode() const
139{
140 return responsePair().second ;
141}
142
143std::string GFilters::NetworkFilter::reason() const
144{
145 return G::Str::printable( G::Str::tail( m_text.value_or(std::string()) , "\t" , false ) ) ;
146}
147
148G::Slot::Signal<int> & GFilters::NetworkFilter::doneSignal() noexcept
149{
150 return m_done_signal ;
151}
152
153void GFilters::NetworkFilter::cancel()
154{
155 m_text.reset() ;
156 m_timer.cancelTimer() ;
157 m_done_signal.emitted( true ) ;
158 m_client_ptr.reset() ;
159}
160
A Filter class that passes the name of a message file to a remote network server.
NetworkFilter(GNet::EventState, GStore::FileStore &, Filter::Type, const Filter::Config &, const std::string &server_location)
Constructor.
~NetworkFilter() override
Destructor.
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 lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
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(std::string_view s)
Converts string 's' to an int.
Definition: gstr.cpp:538
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:913
static std::string tail(std::string_view in, std::size_t pos, std::string_view default_={})
Returns the last part of the string after the given position.
Definition: gstr.cpp:1322
static std::string head(std::string_view in, std::size_t pos, std::string_view default_={})
Returns the first part of the string up to just before the given position.
Definition: gstr.cpp:1294
Slot< Args... > slot(TSink &sink, void(TSink::*method)(Args...))
A factory function for Slot objects.
Definition: gslot.h:240