E-MailRelay

ginterfaces_common.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 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 ginterfaces_common.cpp
19///
20
21#include "gdef.h"
22#include "ginterfaces.h"
23#include "gstr.h"
24#include "gtest.h"
25#include <algorithm>
26
27 GNet::Interfaces::Interfaces()
28= default;
29
30 GNet::Interfaces::Interfaces( ExceptionSink es , InterfacesHandler & handler ) :
31 m_es(es) ,
32 m_handler(&handler)
33{
34}
35
36 GNet::Interfaces::~Interfaces()
37= default;
38
39 void GNet::Interfaces::load()
40{
41 std::vector<Item> new_list ;
42 loadImp( m_es , new_list ) ;
43 m_loaded = true ;
44 using std::swap ;
45 swap( m_list , new_list ) ;
46}
47
48 bool GNet::Interfaces::supported()
49{
50 return true ;
51}
52
53 bool GNet::Interfaces::loaded() const
54{
55 return m_loaded ;
56}
57
58std::vector<GNet::Address> GNet::Interfaces::find( const std::string & name_in , unsigned int port ,
59 bool decoration ) const
60{
61 std::string name = name_in ;
62 int type = 0 ;
63 if( decoration )
64 {
65 if( G::Str::tailMatch(name_in,"-ipv6") )
66 {
67 name = name_in.substr( 0U , name_in.length()-5U ) ;
68 type = 6 ;
69 }
70 else if( G::Str::tailMatch(name_in,"-ipv4") )
71 {
72 name = name_in.substr( 0U , name_in.length()-5U ) ;
73 type = 4 ;
74 }
75 }
76
77 if( name.empty() )
78 return AddressList() ;
79
80 if( !loaded() )
81 const_cast<Interfaces*>(this)->load() ;
82
83 AddressList result ;
84 for( const auto & item : m_list )
85 {
86 if( ( item.name == name || item.altname == name ) && item.up && item.valid_address )
87 {
88 if( type == 0 ||
89 ( type == 6 && item.address.is6() ) ||
90 ( type == 4 && item.address.is4() ) )
91 {
92 result.push_back( item.address ) ;
93 result.back().setPort( port ) ;
94 }
95 }
96 }
97 return result ;
98}
99
100std::vector<GNet::Address> GNet::Interfaces::addresses( const G::StringArray & names , unsigned int port ,
101 G::StringArray & used_names , G::StringArray & empty_names , G::StringArray & bad_names ) const
102{
103 AddressList result ;
104 for( const auto & name : names )
105 {
106 if( Address::validStrings( name , G::Str::fromUInt(port) ) )
107 {
108 result.push_back( Address::parse(name,port) ) ;
109 }
110 else
111 {
112 // 'name' is not an address so treat it as an interface name having
113 // bound addresses -- reject file system paths as 'bad' unless
114 // they are under "/dev" (bsd)
115 AddressList list = find( name , port , true ) ;
116 if( list.empty() && ( name.empty() || ( name.find('/') != std::string::npos && name.find("/dev/") != 0U ) ) )
117 {
118 bad_names.push_back( name ) ;
119 }
120 else if( list.empty() )
121 {
122 empty_names.push_back( name ) ;
123 }
124 else
125 {
126 used_names.push_back( name ) ;
127 }
128 result.insert( result.end() , list.begin() , list.end() ) ;
129 }
130 }
131 return result ;
132}
133
134 G::StringArray GNet::Interfaces::names( bool all ) const
135{
136 G::StringArray list ;
137 for( const auto & iface : *this )
138 {
139 if( all || iface.up )
140 list.push_back( iface.name ) ;
141 }
142 std::sort( list.begin() , list.end() ) ;
143 list.erase( std::unique(list.begin(),list.end()) , list.end() ) ;
144 return list ;
145}
146
147GNet::Interfaces::const_iterator GNet::Interfaces::begin() const
148{
149 return m_list.begin() ;
150}
151
152GNet::Interfaces::const_iterator GNet::Interfaces::end() const
153{
154 return m_list.end() ;
155}
156
157 void GNet::Interfaces::readEvent()
158{
159 if( m_notifier )
160 {
161 std::string s = m_notifier->readEvent() ;
162 if( m_handler && !s.empty() )
163 m_handler->onInterfaceEvent( s ) ;
164 }
165}
166
167 void GNet::Interfaces::onFutureEvent()
168{
169 if( m_notifier )
170 {
171 std::string s = m_notifier->onFutureEvent() ;
172 if( m_handler && !s.empty() )
173 m_handler->onInterfaceEvent( s ) ;
174 }
175}
176
177// ==
178
179GNet::Interfaces::Item::Item() :
180 address(Address::defaultAddress())
181{
182}
183
GNet::Address::validStrings
static bool validStrings(const std::string &ip, const std::string &port_string, std::string *reason=nullptr)
Returns true if the combined network-address string and port string is valid.
Definition: gaddress.cpp:417
GNet::Address::parse
static Address parse(const std::string &display_string)
Factory function for any address family.
Definition: gaddress.cpp:217
GNet::ExceptionSink
A tuple containing an ExceptionHandler interface pointer and a bound 'exception source' pointer.
Definition: gexceptionsink.h:100
GNet::InterfacesHandler
An interface for receiving notification of network changes.
Definition: ginterfaces.h:143
GNet::Interfaces
A class for getting a list of network interfaces and their addresses.
Definition: ginterfaces.h:45
GNet::Interfaces::load
void load()
Loads or reloads the list.
Definition: ginterfaces_common.cpp:39
GNet::Interfaces::Interfaces
Interfaces()
Default constructor resulting in an empty list.
GNet::Interfaces::loaded
bool loaded() const
Returns true if load()ed.
Definition: ginterfaces_common.cpp:53
GNet::Interfaces::~Interfaces
~Interfaces() override
Destructor.
GNet::Interfaces::supported
static bool supported()
Returns false if a stubbed-out implementation.
Definition: ginterfaces_common.cpp:48
GNet::Interfaces::begin
const_iterator begin() const
Returns a begin iterator.
Definition: ginterfaces_common.cpp:147
GNet::Interfaces::addresses
std::vector< Address > addresses(const G::StringArray &names, unsigned int port, G::StringArray &used_names, G::StringArray &empty_names, G::StringArray &bad_names) const
Treats each name given as an address or interface name and returns the total set of addresses.
Definition: ginterfaces_common.cpp:100
GNet::Interfaces::end
const_iterator end() const
Returns a one-off-the-end iterator.
Definition: ginterfaces_common.cpp:152
GNet::Interfaces::find
std::vector< Address > find(const std::string &name, unsigned int port, bool allow_decoration=true) const
Finds the named interface and returns its addresses if it is up.
Definition: ginterfaces_common.cpp:58
GNet::Interfaces::names
G::StringArray names(bool all=false) const
Returns the interface names, optionally including interfaces that are not up.
Definition: ginterfaces_common.cpp:134
G::Str::tailMatch
static bool tailMatch(const std::string &in, const std::string &ending)
Returns true if the string has the given ending (or the given ending is empty).
Definition: gstr.cpp:1302
G::Str::fromUInt
static std::string fromUInt(unsigned int ui)
Converts unsigned int 'ui' to a string.
Definition: gstr.h:579
ginterfaces.h
gstr.h
gtest.h
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:31