Pol  Revision:cb584c9
auxclient.cpp
Go to the documentation of this file.
1 
8 #include "pol_global_config.h"
9 
10 #include "auxclient.h"
11 
12 #include <iosfwd>
13 
14 #include "../../bscript/berror.h"
15 #include "../../bscript/bobject.h"
16 #include "../../bscript/bstruct.h"
17 #include "../../bscript/executor.h"
18 #include "../../bscript/impstr.h"
19 #include "../../clib/cfgelem.h"
20 #include "../../clib/clib.h"
21 #include "../../clib/esignal.h"
22 #include "../../clib/logfacility.h"
23 #include "../../clib/sckutil.h"
24 #include "../../clib/socketsvc.h"
25 #include "../../clib/threadhelp.h"
26 #include "../../clib/wnsckt.h"
27 #include "../../plib/pkg.h"
28 #include "../globals/network.h"
29 #include "../module/osmod.h"
30 #include "../module/uomod.h"
31 #include "../polsem.h"
32 #include "../scrdef.h"
33 #include "../scrsched.h"
34 #include "../uoexec.h"
35 
36 namespace Pol
37 {
38 namespace Network
39 {
41 {
42  return const_cast<AuxConnection*>( this );
43 }
44 
45 std::string AuxConnection::getStringRep() const
46 {
47  return "<AuxConnection>";
48 }
49 
51 {
52  return sizeof( AuxConnection ) + _ip.capacity();
53 }
54 
56 {
57  return ( _auxclientthread != nullptr );
58 }
59 
61 {
62  if ( stricmp( membername, "ip" ) == 0 )
63  {
64  return Bscript::BObjectRef( new Bscript::String( _ip ) );
65  }
67 }
68 
70 {
71  if ( stricmp( methodname, "transmit" ) == 0 )
72  {
73  if ( ex.numParams() == 1 )
74  {
75  if ( _auxclientthread != nullptr )
76  {
77  Bscript::BObjectImp* value = ex.getParamImp( 0 );
78  _auxclientthread->transmit( value );
79  }
80  else
81  {
82  return new Bscript::BError( "Client has disconnected" );
83  }
84  }
85  else
86  {
87  return new Bscript::BError( "1 parameter expected" );
88  }
89  }
90  return nullptr;
91 }
92 
94 {
95  _auxclientthread = nullptr;
96 }
97 
99  : SocketClientThread( listener ),
100  _auxservice( auxsvc ),
101  _auxconnection(),
102  _uoexec( nullptr ),
103  _scriptdef(),
104  _params( nullptr ),
105  _assume_string( false ),
106  _transmit_counter( 0 )
107 {
108 }
110  Bscript::BObjectImp* params, bool assume_string )
111  : SocketClientThread( sock ),
112  _auxservice( nullptr ),
113  _auxconnection(),
114  _uoexec( nullptr ),
115  _scriptdef( scriptdef ),
116  _params( params ),
117  _assume_string( assume_string ),
118  _transmit_counter( 0 )
119 {
120 }
121 
123 {
124  Core::PolLock lock;
125  struct sockaddr ConnectingIP = _sck.peer_address();
126  if ( ipAllowed( ConnectingIP ) )
127  {
128  _auxconnection.set( new AuxConnection( this, _sck.getpeername() ) );
129  Module::UOExecutorModule* uoemod;
130  if ( _auxservice )
132  else
134  if ( uoemod == nullptr )
135  return false;
136  _uoexec = uoemod->uoexec.weakptr;
137  if ( _assume_string )
138  {
139  uoemod->uoexec.auxsvc_assume_string = _assume_string;
140  }
141  return true;
142  }
143  else
144  {
145  return false;
146  }
147 }
148 
149 bool AuxClientThread::ipAllowed( sockaddr MyPeer )
150 {
151  if ( !_auxservice || _auxservice->_aux_ip_match.empty() )
152  {
153  return true;
154  }
155  for ( unsigned j = 0; j < _auxservice->_aux_ip_match.size(); ++j )
156  {
157  unsigned int addr1part, addr2part;
158  struct sockaddr_in* sockin = reinterpret_cast<struct sockaddr_in*>( &MyPeer );
159 
161 #ifdef _WIN32
162  addr2part = sockin->sin_addr.S_un.S_addr & _auxservice->_aux_ip_match_mask[j];
163 #else
164  addr2part = sockin->sin_addr.s_addr & _auxservice->_aux_ip_match_mask[j];
165 #endif
166  if ( addr1part == addr2part )
167  return true;
168  }
169  return false;
170 }
172 {
173  if ( !init() )
174  {
175  if ( _sck.connected() )
176  {
177  writeline( _sck, "Connection closed" );
178  _sck.close();
179  }
180  _auxconnection.clear();
181  return;
182  }
183 
184  std::string tmp;
185  bool result, timeout_exit;
186  for ( ;; )
187  {
188  result = readline( _sck, tmp, &timeout_exit, 5 );
189  if ( !result && !timeout_exit )
190  break;
191 
192  Core::PolLock lock;
193 
194  if ( _uoexec.exists() )
195  {
196  if ( result )
197  {
198  std::istringstream is( tmp );
199  std::unique_ptr<Bscript::BObjectImp> value( _uoexec->auxsvc_assume_string
200  ? new Bscript::String( tmp )
201  : Bscript::BObjectImp::unpack( is ) );
202 
203  std::unique_ptr<Bscript::BStruct> event( new Bscript::BStruct );
204  event->addMember( "type", new Bscript::String( "recv" ) );
205  event->addMember( "value", value.release() );
206  _uoexec->os_module->signal_event( event.release() );
207  }
208  }
209  else
210  { // the controlling script dropped its last reference to the connection,
211  // by exiting or otherwise.
212  break;
213  }
214  }
215  // wait for all transmits to finish
216  while ( !Clib::exit_signalled && _transmit_counter > 0 )
217  std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
218 
219  Core::PolLock lock;
220  _auxconnection->disconnect();
221  // the auxconnection is probably referenced by another ref_ptr,
222  // so its deletion must be protected by the lock.
223  // Clear our reference:
224  _auxconnection.clear();
225 }
226 
228 {
229  // defer transmit to not block server
230  std::string tmp = _uoexec->auxsvc_assume_string ? value->getStringRep() : value->pack();
232  Core::networkManager.auxthreadpool->push( [tmp, this]() { transmit( tmp ); } );
233 }
234 
235 void AuxClientThread::transmit( const std::string& msg )
236 {
237  if ( _sck.connected() )
238  writeline( _sck, msg );
240 }
241 
243  : _pkg( pkg ),
244  _scriptdef( elem.remove_string( "SCRIPT" ), _pkg ),
245  _port( elem.remove_ushort( "PORT" ) )
246 {
247  std::string iptext;
248  while ( elem.remove_prop( "IPMATCH", &iptext ) )
249  {
250  auto delim = iptext.find_first_of( '/' );
251  if ( delim != std::string::npos )
252  {
253  std::string ipaddr_str = iptext.substr( 0, delim );
254  std::string ipmask_str = iptext.substr( delim + 1 );
255  unsigned int ipaddr = inet_addr( ipaddr_str.c_str() );
256  unsigned int ipmask = inet_addr( ipmask_str.c_str() );
257  _aux_ip_match.push_back( ipaddr );
258  _aux_ip_match_mask.push_back( ipmask );
259  }
260  else
261  {
262  unsigned int ipaddr = inet_addr( iptext.c_str() );
263  _aux_ip_match.push_back( ipaddr );
264  _aux_ip_match_mask.push_back( 0xFFffFFffLu );
265  }
266  }
267 }
268 
270 {
271  INFO_PRINT << "Starting Aux Listener (" << _scriptdef.relativename() << ", port " << _port
272  << ")\n";
273 
274  Clib::SocketListener listener( _port );
275  while ( !Clib::exit_signalled )
276  {
277  if ( listener.GetConnection( 5 ) )
278  {
279  Core::PolLock lock;
280  AuxClientThread* client( new AuxClientThread( this, listener ) );
281  Core::networkManager.auxthreadpool->push( [client]() {
282  std::unique_ptr<AuxClientThread> _clientptr( client );
283  _clientptr->run();
284  } );
285  }
286  }
287 }
288 
290 {
291  size_t size =
292  sizeof( Plib::Package* ) + _scriptdef.estimatedSize() + sizeof( unsigned short ) /*_port*/
293  + 3 * sizeof( unsigned int* ) + _aux_ip_match.capacity() * sizeof( unsigned int ) +
294  3 * sizeof( unsigned int* ) + _aux_ip_match_mask.capacity() * sizeof( unsigned int );
295  return size;
296 }
297 
298 void aux_service_thread_stub( void* arg )
299 {
300  AuxService* as = static_cast<AuxService*>( arg );
301  as->run();
302 }
303 
305 {
306  for ( unsigned i = 0; i < Core::networkManager.auxservices.size(); ++i )
307  {
309  Core::networkManager.auxservices[i] );
310  }
311 }
312 
314 {
315  Core::networkManager.auxservices.push_back( new AuxService( pkg, elem ) );
316 }
317 
319 {
320  load_packaged_cfgs( "auxsvc.cfg", "AuxService", load_auxservice_entry );
321 }
322 }
323 }
SocketClientThread(SocketListener &SL)
Definition: socketsvc.cpp:49
void load_aux_services()
Definition: auxclient.cpp:318
Bscript::BObjectImp * _params
Definition: auxclient.h:120
virtual Bscript::BObjectImp * call_method(const char *methodname, Bscript::Executor &ex) POL_OVERRIDE
Definition: auxclient.cpp:69
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: auxclient.cpp:50
virtual std::string getStringRep() const =0
AuxClientThread * _auxclientthread
Definition: auxclient.h:81
void load_packaged_cfgs(const char *cfgname, const char *taglist, void(*loadentry)(const Package *, Clib::ConfigElem &))
Definition: pkg.cpp:454
virtual bool isTrue() const POL_OVERRIDE
Definition: auxclient.cpp:55
AuxConnection(AuxClientThread *auxclientthread, std::string ip)
Definition: auxclient.h:62
bool connected() const
Definition: wnsckt.cpp:308
size_t estimateSize() const
Definition: auxclient.cpp:289
size_t estimatedSize() const
Definition: scrdef.cpp:140
void start_aux_services()
Definition: auxclient.cpp:304
std::vector< unsigned int > _aux_ip_match
Definition: auxclient.h:93
Core::ScriptDef _scriptdef
Definition: auxclient.h:119
std::string relativename(const Plib::Package *pkg=nullptr) const
Definition: scrdef.cpp:102
std::vector< Network::AuxService * > auxservices
Definition: network.h:65
void start_thread(void(*entry)(void *), const char *thread_name, void *arg)
Definition: threadhelp.cpp:233
void transmit(const Bscript::BObjectImp *imp)
Definition: auxclient.cpp:227
std::string getpeername() const
Definition: wnsckt.cpp:92
AuxClientThread(AuxService *auxsvc, Clib::SocketListener &listener)
Definition: auxclient.cpp:98
virtual Bscript::BObjectImp * copy() const POL_OVERRIDE
Definition: auxclient.cpp:40
virtual std::string pack() const
Definition: object.cpp:201
std::vector< unsigned int > _aux_ip_match_mask
Definition: auxclient.h:94
weak_ptr< Core::UOExecutor > _uoexec
Definition: auxclient.h:118
std::unique_ptr< threadhelp::DynTaskThreadPool > auxthreadpool
Definition: network.h:99
ref_ptr< AuxConnection > _auxconnection
Definition: auxclient.h:117
NetworkManager networkManager
Definition: network.cpp:28
void load_auxservice_entry(const Plib::Package *pkg, Clib::ConfigElem &elem)
Definition: auxclient.cpp:313
void writeline(Socket &sck, const std::string &s)
Definition: sckutil.cpp:58
bool exists() const
Definition: weakptr.h:115
static UninitObject * create()
Definition: bobject.h:482
std::atomic< int > _transmit_counter
Definition: auxclient.h:122
void aux_service_thread_stub(void *arg)
Definition: auxclient.cpp:298
const Core::ScriptDef & scriptdef() const
Definition: auxclient.h:92
size_t numParams() const
Definition: executor.h:145
static BObjectImp * unpack(const char *pstr)
Definition: object.cpp:120
Core::ScriptDef _scriptdef
Definition: auxclient.h:98
unsigned short _port
Definition: auxclient.h:99
virtual Bscript::BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: auxclient.cpp:60
virtual void run() POL_OVERRIDE
Definition: auxclient.cpp:171
bool remove_prop(const char *propname, std::string *value)
Definition: cfgfile.cpp:128
bool ipAllowed(sockaddr MyPeer)
Definition: auxclient.cpp:149
struct sockaddr peer_address() const
Definition: wnsckt.cpp:107
virtual std::string getStringRep() const POL_OVERRIDE
Definition: auxclient.cpp:45
#define INFO_PRINT
Definition: logfacility.h:223
void start_script(const char *filename, Bscript::BObjectImp *param0, Bscript::BObjectImp *param1)
Definition: scrsched.cpp:150
bool GetConnection(unsigned int timeout_sec)
Definition: socketsvc.cpp:38
bool readline(Socket &sck, std::string &s, bool *timeout_exit, unsigned int timeout_secs, unsigned maxlen)
Definition: sckutil.cpp:17
Definition: berror.cpp:12
std::atomic< bool > exit_signalled
BObjectImp * getParamImp(unsigned param)
Definition: executor.cpp:266
AuxService(const Plib::Package *pkg, Clib::ConfigElem &elem)
Definition: auxclient.cpp:242