GENERIC_SERVER  0.0.0.9
A light-weight, cross-platform, pluggable, extensible and secure framework for deploying C++ plug-ins.
 All Classes Files Functions Variables Typedefs Pages
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | Private Attributes | List of all members
generic_server Class Reference

This is a singleton class and provides framework functionality. More...

#include <generic_server.h>

Public Member Functions

int init ()
 
int log (unsigned int, unsigned int, char *)
 enables logging to framework managed log file.
 
int log (unsigned int, unsigned int, string)
 enables logging to framework managed log file.
 
int get_log_size (void)
 
int rollover_logs (void)
 Rolls over log files, configured in Master configuation file.
 
int close_log (void)
 
int sock_init (void)
 Really useful only for Windows, just invokes WSAStartup API.
 
int swap_bytes (unsigned char *key)
 A simple utility to swap upper / lower 8 bytes of a 16 bytes buffer.
 
int bb_getline (char *sav_buffer, size_t length, size_t conn_s)
 
int bb_getline (char *sav_buffer, size_t length, size_t conn_s, int)
 
int get_status (unsigned char *buff)
 
string get_cur_time (void)
 
string trim (const std::string &)
 
int socket_close (SOCKET)
 
int close_thread_ids (void)
 
SOCKET create_socket (int)
 
bool get_verify_client (void)
 
int set_verify_client (bool)
 
int check_enabled_plugin (string)
 
int check_allocated_port (string in_plugin_id, string in_plugin_port)
 
int set_conf_file (char *cfile)
 
int set_process_name (char *cfile)
 
int reload_conf_file (void)
 
int get_command_port (void)
 
int plugin_read_conf_file (GENERIC_PLUGIN *, int thread_no)
 
int syslog_msg (unsigned int debug_level, unsigned int verbose_level, string data)
 
string get_framework_version (void)
 
int print_key_message ()
 
int get_thread_id ()
 
int rel_thread_id (int)
 
bool check_plugin_aliases (vector< string > &alias)
 
int set_plugins_path (vector< string > &plugin_parms)
 
string get_plugins_path ()
 
int setnonblocking (SOCKET)
 
int setblocking (SOCKET)
 
int get_thread_sync_mutex (void)
 
int rel_thread_sync_mutex (void)
 
int ssl_async_write (SSL *ssl, char *buf, int size)
 
int ssl_async_read (SSL *ssl, char *buf, int size)
 
int ssl_async_accept (SSL *ssl)
 
vector< string > split (const string &s, const string &delim, const bool keep_empty)
 
GENERIC_PLUGINload_shared_lib (string library_image, string)
 
int unload_shared_lib (string plugin_type)
 
vector< GENERIC_PLUGIN * >
::iterator 
get_start_iterator (void)
 
vector< GENERIC_PLUGIN * >
::iterator 
get_end_iterator (void)
 

Static Public Member Functions

static generic_serverinstance (void)
 Instantiate tis singleton class only once and return pointer to instantiated object later on..
 

Public Attributes

vector< GENERIC_PLUGIN * >
::iterator 
itr
 
vector< GENERIC_PLUGIN * > v
 Vector to hold all plug-ins.
 
unsigned int timeout_seconds
 
int max_threads
 
int command_port
 
ofstream log_file
 
string logname
 
map< string, void * > dll_handles
 
map< int, THREAD_INFOthread_ids
 Map to store all currently running threads.
 
map< string, create_fpfactory
 Map that has function pointers to 'create_instance()' factory method for all plug-in libraries.
 
SSLServer sslserver
 
bool syslog_flag
 
map< string, bool > bootstrap_jobs
 
string server_cert
 TLS certificate stuff.
 
string rsa_private_key
 
string ca_certificate
 

Static Public Attributes

static generic_serverpinstance = 0
 Pointer to singleton framework instance.
 

Private Member Functions

int get_log_file_mutex (void)
 
int rel_log_file_mutex (void)
 
int get_server_params (string, int)
 
int tls_setup (void)
 Initializes TLS.
 
int remove_plugins (map< string, int > &new_ports)
 This is invoked when any plug-in entry gets removed from Master configuration file and framework gets signaled.
 
int remove_all_aliases ()
 
GENERIC_PLUGINinitialize_plugin_object (vector< string > plugin_parms, GENERIC_PLUGIN *plugin)
 
int tls_initialize ()
 Validates generic_server framework and CA certificates, calls tls_setup().
 
int set_access_control (char daemon_flag)
 

Private Attributes

unsigned int iResult
 
unsigned int tls_setup_reqd
 
string conf_file
 
string process_name
 
string plugins_path
 
pthread_mutex_t log_file_mutex
 
pthread_mutex_t thread_cnt_mutex
 
pthread_mutex_t thread_sync_mutex
 
unsigned long max_log_size
 
int max_logs_saved
 
bool verify_client
 

Detailed Description

This is a singleton class and provides framework functionality.

Definition at line 83 of file generic_server.h.

Member Function Documentation

int generic_server::bb_getline ( char *  sav_buffer,
size_t  length,
size_t  conn_s 
)

Asynchronous socket read utility.

Parameters
[out]sav_bufferBuffer to store read data.
[in]lengthMaximum number of bytes to read from socket.
Returns
Number of bytes actually read, or zero on error. failure to read any data.

Definition at line 904 of file generic_server.cpp.

905 {
906  fd_set socks;
907  struct timeval timeout;
908  char str[MAX_SZ];
909  size_t readsock,t;
910  size_t bytes_recvd;
911 
912  memset(sav_buffer,0,sizeof(sav_buffer));
913  memset(str,0,MAX_SZ);
914  bytes_recvd = 0;
915 
916  while(1)
917  {
918  FD_ZERO(&socks);
919  FD_SET(conn_s,&socks);
920  timeout.tv_sec = 0;
921  timeout.tv_usec = 50000;
922  readsock = select((int)conn_s+1,&socks,NULL,NULL,&timeout);
923  if(bytes_recvd && readsock <= 0)
924  return(bytes_recvd);
925  if(FD_ISSET(conn_s,&socks))
926  {
927  if ((t = recv(conn_s,str,sizeof(str), 0)) > 0)
928  {
929  memcpy(sav_buffer+bytes_recvd,str,t);
930  bytes_recvd += t;
931  if(bytes_recvd >= length)
932  return(bytes_recvd);
933  }
934  else
935  {
936  return(bytes_recvd);
937  }
938  }
939  }
940 }
bool generic_server::check_plugin_aliases ( vector< string > &  alias)

Checks for 'alias' plug-ins. An 'alias' is any plug-in that uses the same TCP port of primary plug-in. Framework would use one TCP port/socket to service all 'aliased' plug-ins.

Parameters
[in]&aliasReference to alias Vector within every

Definition at line 290 of file generic_server.cpp.

291 {
292  ostringstream oss;
293  vector <GENERIC_PLUGIN *>::iterator it;
294 
295  for(it = get_start_iterator(); it != get_end_iterator();it++)
296  {
297  if( (*it)->get_plugin_name() != plugin_parms.at(PLUGIN_NAME) &&
298  (*it)->get_plugin() == plugin_parms.at(PLUGIN_TYPE) &&
299  (*it)->get_plugin_path() == plugin_parms.at(SHARED_LIB_PATH) &&
300  (*it)->get_port() == atoi(plugin_parms.at(PORT).c_str()) &&
301  (*it)->get_conf_file() == plugin_parms.at(PLUGIN_CONF) &&
302  (*it)->get_tls_flag() == atoi(plugin_parms.at(TLS_FLAG).c_str())
303  )
304  {
305  if(!(*it)->find_plugin_alias(plugin_parms.at(PLUGIN_NAME)))
306  (*it)->add_plugin_alias(plugin_parms.at(PLUGIN_NAME));
307  return(true);
308  }
309  else
310  if( (*it)->get_plugin_name() != plugin_parms.at(PLUGIN_NAME) &&
311  (*it)->get_plugin() == plugin_parms.at(PLUGIN_TYPE) &&
312  (*it)->get_port() == atoi(plugin_parms.at(PORT).c_str()) &&
313  (*it)->get_tls_flag() == atoi(plugin_parms.at(TLS_FLAG).c_str())
314  )
315  {
316  if( (*it)->get_conf_file() != plugin_parms.at(PLUGIN_CONF) ||
317  (*it)->get_plugin_path() != plugin_parms.at(SHARED_LIB_PATH) )
318  {
319  oss << " Ignoring attempted plugin alias for: " << (*it)->get_plugin_name() << ". check alias configuration.";
320  log(LOG_LOW,LOG_LOW,oss.str());
321  return(true);
322  }
323  }
324  }
325  return(false);
326 }
int log(unsigned int, unsigned int, char *)
enables logging to framework managed log file.
SOCKET generic_server::create_socket ( int  port)

Creates a 'listen'ing socket for every plugin, sets socket to 'nonblocking' mode.

Parameters
[in]portTCP port for socket to bind.
Returns
socket descriptor on success or zero on error.

Definition at line 1244 of file generic_server.cpp.

Referenced by process_data().

1245 {
1246  SOCKET ListenSocket;
1247  struct addrinfo *result = NULL;
1248  struct sockaddr_in local_address;
1249  struct addrinfo hints;
1250  ostringstream os;
1251  int iResult;
1252 
1253  os << port;
1254  memset(&local_address,0,sizeof(local_address));
1255  memset(&hints, 0,sizeof(hints));
1256  hints.ai_family = AF_INET;
1257  hints.ai_socktype = SOCK_STREAM;
1258  hints.ai_protocol = IPPROTO_TCP;
1259  hints.ai_flags = AI_PASSIVE;
1260  iResult = getaddrinfo(NULL, os.str().c_str(), &hints, &result);
1261  if (iResult != 0)
1262  {
1263  os.str("");
1264  os.clear();
1265  os << " Thr.ID:MAIN getaddrinfo failed.";
1266  log(LOG_LOW,LOG_LOW,os.str());
1267  }
1268  ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
1269  if (ListenSocket == INVALID_SOCKET)
1270  {
1271  os.str("");
1272  os.clear();
1273  os << " Thr.ID:MAIN socket creation failed.";
1274  log(LOG_LOW,LOG_LOW,os.str());
1275  freeaddrinfo(result);
1276  return 0;
1277  }
1278  local_address.sin_family = AF_INET;
1279  local_address.sin_addr.s_addr = inet_addr("127.0.0.1");
1280  local_address.sin_port = htons(port);
1281  iResult = bind(ListenSocket, (sockaddr *) &local_address, (int)result->ai_addrlen);
1282  if (iResult != 0)
1283  {
1284  os.str("");
1285  os.clear();
1286  os << " Thr.ID:MAIN socket bind failed for port: " << port;
1287  log(LOG_LOW,LOG_LOW,os.str());
1288  freeaddrinfo(result);
1289  shutdown(ListenSocket,2);
1290 #ifdef WINDOWS
1291  closesocket(ListenSocket);
1292 #else
1293  close(ListenSocket);
1294 #endif
1295  return 0;
1296  }
1297  iResult = listen(ListenSocket, SOMAXCONN);
1298  if (iResult == SOCKET_ERROR)
1299  {
1300  os.str("");
1301  os.clear();
1302  os << " Thr.ID:MAIN socket listen failed for port: " << port;
1303  log(LOG_LOW,LOG_LOW,os.str());
1304  shutdown(ListenSocket,2);
1305 #ifdef WINDOWS
1306  closesocket(ListenSocket);
1307 #else
1308  close(ListenSocket);
1309 #endif
1310  return 0;
1311  }
1312  setnonblocking(ListenSocket);
1313  return(ListenSocket);
1314 }
int log(unsigned int, unsigned int, char *)
enables logging to framework managed log file.
int generic_server::init ( )

Reads master configuration file, loads plug-in shared libraries and initializes master Vector to store plug-ins.

Definition at line 472 of file generic_server.cpp.

473 {
474  int ret;
475  GENERIC_PLUGIN *plugin;
476  vector<string> plugin_parms;
477  string line,delim,library_image;
478  ostringstream os;
479 
480  ret = 0;
481 #ifdef WINDOWS
482  if (!sock_init())
483  {
484  cout << "Can't init socket library! " << endl;
485  return(0);
486  }
487  TCHAR filebuf[MAX_SZ];
488  get_exe_directory(filebuf,MAX_SZ);
489  SetCurrentDirectory(filebuf);
490 #endif
491  tls_setup_reqd = 0;
492  delim = "|";
493  ifstream inf(conf_file.c_str());
494 
495  if(!inf)
496  {
497  cout << " Can't Open file: " << conf_file << endl;
498  return(0);
499  }
500  while(getline(inf, line))
501  {
502  line = trim(line);
503  if(line.length() == 0 || line.at(0) == '#')
504  continue;
505  if(!get_server_params(line,INIT))
506  continue;
507  plugin_parms = split(line,delim,true);
508  if(plugin_parms.size() != 7)
509  continue;
510  set_plugins_path(plugin_parms);
511  // returns true if PLUGIN_NAME is a new alias or an existing alias
512  // generic_plugin will be updated in case of new alias
513  if(check_plugin_aliases(plugin_parms))
514  continue;
515  plugin = load_shared_lib(plugin_parms.at(SHARED_LIB_PATH),plugin_parms.at(PLUGIN_TYPE));
516  if(plugin == NULL)
517  {
518  os << " Thr.ID:MAIN load_library failed: " << plugin_parms.at(SHARED_LIB_PATH) << " PLUGIN_TYPE: " << plugin_parms.at(PLUGIN_TYPE) << endl;
519  log(LOG_LOW,LOG_LOW,os.str());
520  return 0;
521  }
522  plugin = initialize_plugin_object(plugin_parms,plugin);
523  if(plugin == NULL)
524  return(0);
525  v.push_back(plugin);
526  }
527  inf.close();
528  if(!tls_initialize())
529  return(0);
530 return(1);
531 }
GENERIC_PLUGIN * load_shared_lib(string library_image, string)
int log(unsigned int, unsigned int, char *)
enables logging to framework managed log file.
bool check_plugin_aliases(vector< string > &alias)
This component provides functionality that are common across plug-ins. Framework would instantiate an...
int sock_init(void)
Really useful only for Windows, just invokes WSAStartup API.
int tls_initialize()
Validates generic_server framework and CA certificates, calls tls_setup().
GENERIC_PLUGIN * initialize_plugin_object(vector< string > plugin_parms, GENERIC_PLUGIN *plugin)
vector< GENERIC_PLUGIN * > v
Vector to hold all plug-ins.
GENERIC_PLUGIN * generic_server::initialize_plugin_object ( vector< string >  plugin_parms,
GENERIC_PLUGIN plugin 
)
private

Update plug-in object with plug-in specific configuration parameters from plug-in conf file.

Parameters
[in]plugin_parmsVector that holds plug-in configuration details.
[in]pluginPlug-in object to be updated.
Returns
Updated plugin object or NULL on error.

Definition at line 1138 of file generic_server.cpp.

References generic_plugin::bootstrap_init(), generic_plugin::bootstrap_name(), generic_plugin::initialize_socket(), generic_plugin::pinstance, and generic_plugin::server_init().

1139 {
1140  int ret;
1141  ostringstream os;
1142  SOCKET ListenSocket;
1143  string bootstrap_name;;
1144 
1145  plugin->set_port(atoi(plugin_parms.at(PORT).c_str()));
1146  plugin->set_plugin(plugin_parms.at(PLUGIN_TYPE));
1147  plugin->set_plugin_name(plugin_parms.at(PLUGIN_NAME));
1148  plugin->set_plugin_number(plugin_parms.at(PLUGIN_NUMBER));
1149  plugin->set_plugin_path(plugin_parms.at(SHARED_LIB_PATH));
1150  plugin->set_tls_flag(atoi(plugin_parms.at(TLS_FLAG).c_str()));
1151  memcpy(&plugin->pinstance,&pinstance,4);
1152  if( (ListenSocket = plugin->initialize_socket(plugin_parms.at(PORT))) == 0)
1153  return(NULL);
1154  plugin->set_socket(ListenSocket);
1155  if(plugin->get_tls_flag())
1156  tls_setup_reqd = 1;
1157  if(plugin_parms.size() > PLUGIN_CONF)
1158  {
1159  plugin->set_conf_file(plugin_parms.at(PLUGIN_CONF));
1160  ret = plugin_read_conf_file(plugin,0);
1161  if(!ret) // read in plugin_specific config parameters
1162  {
1163  os << " Thr.ID:MAIN plugin_init failed for: " << plugin->get_plugin_name() << endl;
1164  log(LOG_LOW,LOG_LOW,os.str());
1165  return(NULL);
1166  }
1167  }
1168  bootstrap_name = plugin->bootstrap_name();
1169  map<string,bool>::iterator it = bootstrap_jobs.find(bootstrap_name);
1170  if(it == bootstrap_jobs.end() && bootstrap_name != "")
1171  {
1172  os << " Thr.ID:MAIN Invoking bootstrap: " << bootstrap_name << " on plug-in: " << plugin->get_plugin_name();
1173  log(LOG_LOW,LOG_LOW,os.str());
1174  os.str("");
1175  os.clear();
1176  if(!plugin->bootstrap_init(bootstrap_name))
1177  {
1178  os << " Thr.ID:MAIN failed to bootstrap: " << bootstrap_name << " on plug-in: " << plugin->get_plugin_name();
1179  log(LOG_LOW,LOG_LOW,os.str());
1180  return(NULL);
1181  }
1182  bootstrap_jobs[bootstrap_name] = true;
1183  os << " Thr.ID:MAIN Successfully bootstrapped: " << bootstrap_name << " on plug-in: " << plugin->get_plugin_name();
1184  log(LOG_LOW,LOG_LOW,os.str());
1185  os.str("");
1186  os.clear();
1187  }
1188  if(!check_enabled_plugin(plugin_parms.at(PLUGIN_TYPE)))
1189  {
1190  if(!plugin->server_init()) // Will do only once per plugin type
1191  {
1192  os << " Thr.ID:MAIN thread. server_init failed for: " << plugin_parms.at(PLUGIN_TYPE) << endl;
1193  log(LOG_LOW,LOG_LOW,os.str());
1194  return(NULL);
1195  }
1196  }
1197  setnonblocking(ListenSocket);
1198  return(plugin);
1199 }
virtual string bootstrap_name(void)
int log(unsigned int, unsigned int, char *)
enables logging to framework managed log file.
static generic_server * pinstance
Pointer to singleton framework instance.
virtual bool bootstrap_init(string)
SOCKET initialize_socket(string port)
Binds socket to TCP port, set options on new socket and do socket listen.
unsigned long pinstance
Pointer to 'framework' object.
virtual int server_init(void)
GENERIC_PLUGIN * generic_server::load_shared_lib ( string  library_image,
string  plugin_type 
)

Dynamically loads plug-in shared library.

Parameters
[in]library_imagePath to shared library image.
[in]plugin_typePLUGIN_TYPE to load.
Returns
function pointer to 'create_instance()' factory method of loaded plug-in. NULL on error.

Definition at line 599 of file generic_server.cpp.

600 {
601  GENERIC_PLUGIN *plugin_p;
602  ostringstream os;
603 
604 #ifndef WINDOWS
605  void* handle = dlopen(library_image.c_str(),RTLD_LAZY);
606  if(handle == NULL)
607  {
608  os << " Thr.ID:MAIN Can't load DLL: " << " " << dlerror();
609  log(LOG_LOW,LOG_LOW,os.str());
610  return(NULL);
611  }
612  factory[plugin_type] = (create_fp) dlsym(handle, "create_instance");
613  dll_handles[plugin_type] = (void *) handle;
614 #else
615  HMODULE handle;
616  handle = LoadLibrary(library_image.c_str());
617  if(handle == NULL)
618  {
619  os.str("");
620  os.clear();
621  os << " Thr.ID:MAIN Error loading: " << library_image << " " << GetLastError();
622  log(LOG_LOW,LOG_LOW,os.str());
623  return(NULL);
624  }
625  factory[plugin_type] = (create_fp) GetProcAddress(handle, "create_instance");
626  dll_handles[plugin_type] = (void *) handle;
627 #endif
628  if(factory[plugin_type] == NULL)
629  {
630  os << " Thr.ID:MAIN Can't instantiate PLUGIN_TYPE: " << plugin_type;
631  log(LOG_LOW,LOG_LOW,os.str());
632  return(NULL);
633  }
634  plugin_p = (factory[plugin_type])();
635  os << " Thr.ID:MAIN loaded plugin version: " << plugin_p->get_plugin_version() << " for PLUGIN_TYPE: " << plugin_type;
636  log(LOG_LOW,LOG_LOW,os.str());
637  return(plugin_p);
638 }
int log(unsigned int, unsigned int, char *)
enables logging to framework managed log file.
This component provides functionality that are common across plug-ins. Framework would instantiate an...
GENERIC_PLUGIN *(* create_fp)()
Every plug-in should have a function with following prototype. This is the factory method: 'create_in...
map< string, create_fp > factory
Map that has function pointers to 'create_instance()' factory method for all plug-in libraries...

The documentation for this class was generated from the following files: