• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 16481710579

23 Jul 2025 09:00PM UTC coverage: 59.58% (+0.04%) from 59.537%
16481710579

push

github

web-flow
Add ecompile flag -Z to print AST (#796)

* Add -Z option to print string tree

* Simple test to print an AST

* Make CompiledScript owner of the tree

* some refactoring
- rename ecompile.cfg option
- rename AST generator class

* core-changes, docs

* fix warnings

34 of 38 new or added lines in 7 files covered. (89.47%)

2 existing lines in 2 files now uncovered.

43382 of 72813 relevant lines covered (59.58%)

457932.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.09
/pol-core/pol/network/auxclient.cpp
1
/** @file
2
 *
3
 * @par History
4
 * - 2005/11/26 Shinigami: changed "strcmp" into "stricmp" to suppress Script Errors
5
 */
6

7

8
#include "pol_global_config.h"
9

10
#include "auxclient.h"
11

12
#include <chrono>
13
#include <iosfwd>
14

15
#include "../../bscript/berror.h"
16
#include "../../bscript/bobject.h"
17
#include "../../bscript/bstruct.h"
18
#include "../../bscript/executor.h"
19
#include "../../bscript/impstr.h"
20
#include "../../clib/cfgelem.h"
21
#include "../../clib/clib.h"
22
#include "../../clib/esignal.h"
23
#include "../../clib/logfacility.h"
24
#include "../../clib/network/sckutil.h"
25
#include "../../clib/network/socketsvc.h"
26
#include "../../clib/network/wnsckt.h"
27
#include "../../clib/stlutil.h"
28
#include "../../clib/threadhelp.h"
29
#include "../../plib/pkg.h"
30
#include "../globals/network.h"
31
#include "../module/uomod.h"
32
#include "../polsem.h"
33
#include "../scrdef.h"
34
#include "../scrsched.h"
35
#include "../uoexec.h"
36

37
namespace Pol
38
{
39
namespace Network
40
{
41
Bscript::BObjectImp* AuxConnection::copy() const
6✔
42
{
43
  return const_cast<AuxConnection*>( this );
6✔
44
}
45

46
std::string AuxConnection::getStringRep() const
×
47
{
48
  return "<AuxConnection>";
×
49
}
50

51
size_t AuxConnection::sizeEstimate() const
×
52
{
53
  return sizeof( AuxConnection ) + _ip.capacity();
×
54
}
55

56
bool AuxConnection::isTrue() const
×
57
{
58
  return ( _auxclientthread != nullptr );
×
59
}
60

61
Bscript::BObjectRef AuxConnection::get_member( const char* membername )
×
62
{
63
  if ( stricmp( membername, "ip" ) == 0 )
×
64
  {
65
    return Bscript::BObjectRef( new Bscript::String( _ip ) );
×
66
  }
67
  return Bscript::BObjectRef( Bscript::UninitObject::create() );
×
68
}
69

70
Bscript::BObjectImp* AuxConnection::call_polmethod( const char* methodname, Core::UOExecutor& ex )
167✔
71
{
72
  if ( stricmp( methodname, "transmit" ) == 0 )
167✔
73
  {
74
    if ( ex.numParams() == 1 )
167✔
75
    {
76
      if ( _auxclientthread != nullptr )
167✔
77
      {
78
        Bscript::BObjectImp* value = ex.getParamImp( 0 );
167✔
79
        _auxclientthread->transmit( value );
167✔
80
      }
81
      else
82
      {
83
        return new Bscript::BError( "Client has disconnected" );
×
84
      }
85
    }
86
    else
87
    {
88
      return new Bscript::BError( "1 parameter expected" );
×
89
    }
90
  }
91
  return nullptr;
167✔
92
}
93

94
void AuxConnection::disconnect()
4✔
95
{
96
  _auxclientthread = nullptr;
4✔
97
}
4✔
98

99
AuxClientThread::AuxClientThread( AuxService* auxsvc, Clib::Socket&& sock )
×
100
    : SocketClientThread( std::move( sock ) ),
×
101
      _auxservice( auxsvc ),
×
102
      _auxconnection(),
×
103
      _uoexec( nullptr ),
×
104
      _scriptdef(),
×
105
      _params( nullptr ),
×
106
      _assume_string( false ),
×
107
      _transmit_counter( 0 ),
×
108
      _keep_alive( false ),
×
109
      _ignore_line_breaks( false ),
×
110
      _transmit_mutex()
×
111
{
112
}
×
113
AuxClientThread::AuxClientThread( Core::ScriptDef scriptdef, Clib::Socket&& sock,
4✔
114
                                  Bscript::BObjectImp* params, bool assume_string, bool keep_alive,
115
                                  bool ignore_line_breaks )
4✔
116
    : SocketClientThread( std::move( sock ) ),
4✔
117
      _auxservice( nullptr ),
4✔
118
      _auxconnection(),
4✔
119
      _uoexec( nullptr ),
4✔
120
      _scriptdef( scriptdef ),
4✔
121
      _params( params ),
4✔
122
      _assume_string( assume_string ),
4✔
123
      _transmit_counter( 0 ),
4✔
124
      _keep_alive( keep_alive ),
4✔
125
      _ignore_line_breaks( ignore_line_breaks ),
4✔
126
      _transmit_mutex()
8✔
127
{
128
}
4✔
129

130
bool AuxClientThread::init()
4✔
131
{
132
  Core::PolLock lock;
4✔
133
  struct sockaddr ConnectingIP = _sck.peer_address();
4✔
134
  if ( ipAllowed( ConnectingIP ) )
4✔
135
  {
136
    _auxconnection.set( new AuxConnection( this, _sck.getpeername() ) );
4✔
137
    Module::UOExecutorModule* uoemod;
138
    if ( _auxservice )
4✔
139
      uoemod = Core::start_script( _auxservice->scriptdef(), _auxconnection.get() );
×
140
    else
141
      uoemod = Core::start_script( _scriptdef, _auxconnection.get(), _params );
4✔
142
    if ( uoemod == nullptr )
4✔
143
      return false;
×
144
    auto& uoex = uoemod->uoexec();
4✔
145
    _uoexec = uoex.weakptr;
4✔
146
    if ( _assume_string )
4✔
147
    {
148
      uoex.auxsvc_assume_string = _assume_string;
4✔
149
    }
150
    return true;
4✔
151
  }
152
  else
153
  {
154
    return false;
×
155
  }
156
}
4✔
157

158
bool AuxClientThread::ipAllowed( sockaddr MyPeer )
4✔
159
{
160
  if ( !_auxservice || _auxservice->_aux_ip_match.empty() )
4✔
161
  {
162
    return true;
4✔
163
  }
164
  for ( unsigned j = 0; j < _auxservice->_aux_ip_match.size(); ++j )
×
165
  {
166
    unsigned int addr1part, addr2part;
167
    struct sockaddr_in* sockin = reinterpret_cast<struct sockaddr_in*>( &MyPeer );
×
168

169
    addr1part = _auxservice->_aux_ip_match[j] & _auxservice->_aux_ip_match_mask[j];
×
170
#ifdef _WIN32
171
    addr2part = sockin->sin_addr.S_un.S_addr & _auxservice->_aux_ip_match_mask[j];
172
#else
173
    addr2part = sockin->sin_addr.s_addr & _auxservice->_aux_ip_match_mask[j];
×
174
#endif
175
    if ( addr1part == addr2part )
×
176
      return true;
×
177
  }
178
  return false;
×
179
}
180
void AuxClientThread::run()
4✔
181
{
182
  if ( !init() )
4✔
183
  {
184
    if ( _sck.connected() )
×
185
    {
186
      writeline( _sck, "Connection closed" );
×
187
      _sck.close();
×
188
    }
189
    _auxconnection.clear();
×
190
    return;
×
191
  }
192

193
  std::string tmp;
4✔
194
  bool result, timeout_exit;
195

196
  std::unique_ptr<Clib::SocketReader> reader;
4✔
197

198
  if ( _ignore_line_breaks )
4✔
199
  {
200
    reader = std::make_unique<Clib::SocketByteReader>( _sck, 5, !_keep_alive );
3✔
201
  }
202
  else
203
  {
204
    reader = std::make_unique<Clib::SocketLineReader>( _sck, 5, 0, !_keep_alive );
1✔
205
  }
206

207
  for ( ;; )
208
  {
209
    result = reader->read( tmp, &timeout_exit );
720✔
210
    if ( Clib::exit_signalled || ( !result && !timeout_exit && !_keep_alive ) )
720✔
211
      break;
×
212

213
    Core::PolLock lock;
720✔
214

215
    if ( _uoexec.exists() )
720✔
216
    {
217
      if ( result )
717✔
218
      {
219
        std::istringstream is( tmp );
716✔
220
        std::unique_ptr<Bscript::BObjectImp> value( _uoexec->auxsvc_assume_string
716✔
221
                                                        ? new Bscript::String( tmp )
716✔
222
                                                        : Bscript::BObjectImp::unpack( is ) );
1,432✔
223

224
        std::unique_ptr<Bscript::BStruct> event( new Bscript::BStruct );
716✔
225
        event->addMember( "type", new Bscript::String( "recv" ) );
716✔
226
        event->addMember( "value", value.release() );
716✔
227
        _uoexec->signal_event( event.release() );
716✔
228
      }
716✔
229
      else if ( !reader->connected() )
1✔
230
      {
231
        _uoexec->signal_event( new Bscript::BError( "connection closed" ) );
1✔
232
        break;
1✔
233
      }
234
    }
235
    else
236
    {  // the controlling script dropped its last reference to the connection,
237
      // by exiting or otherwise.
238
      break;
3✔
239
    }
240
  }
1,436✔
241
  // wait for all transmits to finish
242
  while ( !Clib::exit_signalled && _transmit_counter > 0 )
4✔
UNCOV
243
    std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
×
244

245
  Core::PolLock lock;
4✔
246
  // hold also the transmit mutex, the counter syncs but not in a way that the threadsanitizer
247
  // recognizes is.
248
  std::unique_lock<std::mutex> transmitlock( _transmit_mutex );
4✔
249
  _auxconnection->disconnect();
4✔
250
  // the auxconnection is probably referenced by another ref_ptr,
251
  // so its deletion must be protected by the lock.
252
  // Clear our reference:
253
  _auxconnection.clear();
4✔
254
}
4✔
255

256
void AuxClientThread::transmit( const Bscript::BObjectImp* value )
167✔
257
{
258
  // defer transmit to not block server
259
  std::string tmp = _uoexec->auxsvc_assume_string ? value->getStringRep() : value->pack();
167✔
260
  ++_transmit_counter;
167✔
261
  Core::networkManager.auxthreadpool->push( [tmp, this]() { transmit( tmp ); } );
334✔
262
}
167✔
263

264
void AuxClientThread::transmit( const std::string& msg )
167✔
265
{
266
  // wait for all other transmits to finish
267
  // sending in parallel is nothing what we want
268
  std::unique_lock<std::mutex> lock( _transmit_mutex );
167✔
269
  if ( _sck.connected() )
167✔
270
  {
271
    if ( _ignore_line_breaks )
167✔
272
      _sck.write( msg );
50✔
273
    else
274
      writeline( _sck, msg );
117✔
275
  }
276
  --_transmit_counter;
167✔
277
}
167✔
278

279
AuxService::AuxService( const Plib::Package* pkg, Clib::ConfigElem& elem )
×
280
    : _pkg( pkg ),
×
281
      _scriptdef( elem.remove_string( "SCRIPT" ), _pkg ),
×
282
      _port( elem.remove_ushort( "PORT" ) )
×
283
{
284
  std::string iptext;
×
285
  while ( elem.remove_prop( "IPMATCH", &iptext ) )
×
286
  {
287
    auto delim = iptext.find_first_of( '/' );
×
288
    if ( delim != std::string::npos )
×
289
    {
290
      std::string ipaddr_str = iptext.substr( 0, delim );
×
291
      std::string ipmask_str = iptext.substr( delim + 1 );
×
292
      unsigned int ipaddr = inet_addr( ipaddr_str.c_str() );
×
293
      unsigned int ipmask = inet_addr( ipmask_str.c_str() );
×
294
      _aux_ip_match.push_back( ipaddr );
×
295
      _aux_ip_match_mask.push_back( ipmask );
×
296
    }
×
297
    else
298
    {
299
      unsigned int ipaddr = inet_addr( iptext.c_str() );
×
300
      _aux_ip_match.push_back( ipaddr );
×
301
      _aux_ip_match_mask.push_back( 0xFFffFFffLu );
×
302
    }
303
  }
304
}
×
305

306
void AuxService::run()
×
307
{
308
  INFO_PRINTLN( "Starting Aux Listener ({}, port {})", _scriptdef.relativename(), _port );
×
309

310
  Clib::SocketListener listener( _port );
×
311
  while ( !Clib::exit_signalled )
×
312
  {
313
    Clib::Socket sock;
×
314
    if ( listener.GetConnection( &sock, 5000 ) && sock.connected() )
×
315
    {
316
      Core::PolLock lock;
×
317
      AuxClientThread* client( new AuxClientThread( this, std::move( sock ) ) );
×
318
      Core::networkManager.auxthreadpool->push(
×
319
          [client]()
×
320
          {
321
            std::unique_ptr<AuxClientThread> _clientptr( client );
×
322
            _clientptr->run();
×
323
          } );
×
324
    }
×
325
  }
×
326
}
×
327

328
size_t AuxService::estimateSize() const
×
329
{
330
  size_t size = sizeof( Plib::Package* ) + _scriptdef.estimatedSize() +
×
331
                sizeof( unsigned short ) /*_port*/
332
                + Clib::memsize( _aux_ip_match ) + Clib::memsize( _aux_ip_match_mask );
×
333
  return size;
×
334
}
335

336
void aux_service_thread_stub( void* arg )
×
337
{
338
  AuxService* as = static_cast<AuxService*>( arg );
×
339
  as->run();
×
340
}
×
341

342
void start_aux_services()
2✔
343
{
344
  for ( unsigned i = 0; i < Core::networkManager.auxservices.size(); ++i )
2✔
345
  {
346
    threadhelp::start_thread( aux_service_thread_stub, "AuxService",
×
347
                              Core::networkManager.auxservices[i] );
×
348
  }
349
}
2✔
350

351
void load_auxservice_entry( const Plib::Package* pkg, Clib::ConfigElem& elem )
×
352
{
353
  Core::networkManager.auxservices.push_back( new AuxService( pkg, elem ) );
×
354
}
×
355

356
void load_aux_services()
3✔
357
{
358
  load_packaged_cfgs( "auxsvc.cfg", "AuxService", load_auxservice_entry );
3✔
359
}
3✔
360
}  // namespace Network
361
}  // namespace Pol
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc