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
generic_server.cpp
1 /*
2  Copyright 2013 Broadcom Corporation
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License version 2.1 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public
14  License along with this library; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <iostream>
19 #include <fstream>
20 #include <algorithm>
21 #include <vector>
22 #include <string>
23 #include <sstream>
24 #include <map>
25 #include <utility>
26 using namespace std;
27 
28 #ifdef WINDOWS
29 #include <winsock2.h>
30 #include <process.h>
31 #include <ws2tcpip.h>
32 #include <ctype.h>
33 #include <windows.h>
34 #else
35 #include <sys/socket.h>
36 #include <arpa/inet.h>
37 #include <unistd.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #include <pthread.h>
41 #include <dlfcn.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <sys/prctl.h>
45 #include <syslog.h>
46 #endif
47 
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <time.h>
52 #include <signal.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <errno.h>
56 #include "sslserver.h"
57 #include "generic_plugin.h"
58 #include "generic_server.h"
59 
61 generic_server::generic_server(void)
62 {
63  pinstance = 0;
64  command_port = 10000;
65  plugins_path = "";
66  max_threads = 100;
67  timeout_seconds = 0;
68  logname = "";
69  server_cert = "";
70  ca_certificate = "";
71  verify_client = false;
72  rsa_private_key = "";
73  max_log_size = 10*1000*1000;
74  max_logs_saved = 5;
75  syslog_flag = false;
76 #ifdef WINDOWS
77  log_file_mutex = CreateMutex( NULL, FALSE, NULL);
78  thread_cnt_mutex = CreateMutex( NULL, FALSE, NULL);
79  thread_sync_mutex = CreateMutex( NULL, FALSE, NULL);
80 #else
81  pthread_mutex_init(&log_file_mutex,NULL);
82  pthread_mutex_init(&thread_cnt_mutex,NULL);
83  pthread_mutex_init(&thread_sync_mutex,NULL);
84 #endif
85 }
86 /*********************************************************************************************/
87 
89 {
90  return pinstance ? pinstance : (pinstance = new generic_server);
91 }
92 /*********************************************************************************************/
93 
94 int generic_server::log(unsigned int debug_level,unsigned int verbose_level,char *data)
95 {
96 
97  if(syslog_flag)
98  return(syslog_msg(debug_level,verbose_level,data));
99  unsigned int msk = 0xFFFFFFFF;
100  msk = msk << 4;
101  get_log_file_mutex();
102  debug_level = debug_level & ~msk;
103  if(verbose_level >= debug_level)
104  {
105  if(log_file.is_open())
106  log_file << get_cur_time() << data << endl;
107  else
108  cout << get_cur_time() << data << endl;
109  }
110  rel_log_file_mutex();
111  return(1);
112 }
113 /*********************************************************************************************/
114 
115 int generic_server::log(unsigned int debug_level,unsigned int verbose_level,string data)
116 {
117  if(syslog_flag)
118  return(syslog_msg(debug_level,verbose_level,data));
119  unsigned int msk = 0xFFFFFFFF;
120 
121  msk = msk << 4;
122  get_log_file_mutex();
123  debug_level = debug_level & ~msk;
124  if(verbose_level >= debug_level)
125  {
126  if(log_file.is_open())
127  log_file << get_cur_time() << data << endl;
128  else
129  cout << get_cur_time() << data << endl;
130  }
131  rel_log_file_mutex();
132  return(1);
133 }
134 /*********************************************************************************************/
135 
136 int generic_server::get_log_file_mutex(void)
137 {// not using pthread_cond variable, since Windows does not support cond. variables
138 #ifdef WINDOWS
139 DWORD dwWaitResult;
140  dwWaitResult = WaitForSingleObject(log_file_mutex,INFINITE);
141 #else
142  pthread_mutex_lock(&log_file_mutex);
143 #endif
144  return(1);
145 }
146 /*********************************************************************************************/
147 
149 {
150  int i;
151  unsigned long size;
152  string file_name,fname2;
153  struct _stat stFileInfo;
154  size = get_log_size();
155  map<int,string> log_files;
156  map<int,string>::iterator itr;
157  ostringstream oss;
158  if(size > max_log_size)
159  {
160  log(LOG_LOW,LOG_LOW,oss.str());
161  get_log_file_mutex();
162  if(log_file.is_open())
163  log_file.close();
164  for(i = 0;i <= max_logs_saved; i++)
165  {
166  stringstream oss;
167  if(i > 0)
168  oss << logname << "." << i;
169  else
170  oss << logname;
171  file_name = oss.str();
172  if(!_stat(file_name.c_str(),&stFileInfo))
173  log_files[i] = file_name;
174  }
175  if(log_files.size() == max_logs_saved+1)
176  {
177  itr = log_files.end();
178  itr--;
179  log_files.erase(itr);
180  }
181  if(log_files.size() == 1)
182  {
183  fname2 = logname + ".1";
184  rename(log_files[0].c_str(),fname2.c_str());
185  }
186  else
187  {
188  for(i = log_files.size()-1; i >= 0;i--)
189  {
190  stringstream oss;
191  oss << logname << "." << (i+1);
192  fname2 = oss.str();
193  rename(log_files[i].c_str(),fname2.c_str());
194  }
195  }
196  log_file.open(logname.c_str());
197  rel_log_file_mutex();
198  }
199  return(1);
200 }
201 /*********************************************************************************************/
202 
203 int generic_server::rel_log_file_mutex(void)
204 {
205 #ifdef WINDOWS
206  ReleaseMutex(log_file_mutex);
207 #else
208  pthread_mutex_unlock(&log_file_mutex);
209 #endif
210  return(1);
211 }
212 /*********************************************************************************************/
213 
214 int generic_server::set_conf_file(char *cfile)
215 {
216  conf_file = cfile;
217  return(1);
218 }
219 /*********************************************************************************************/
220 
221 int generic_server::set_process_name(char *pname)
222 {
223  process_name = pname;
224  return(1);
225 }
226 /*********************************************************************************************/
227 
228 int generic_server::get_thread_sync_mutex(void)
229 {
230 #ifdef WINDOWS
231 DWORD dwWaitResult;
232  dwWaitResult = WaitForSingleObject(thread_sync_mutex,INFINITE);
233 #else
234  pthread_mutex_lock(&thread_sync_mutex);
235 #endif
236  return(1);
237 }
238 /*********************************************************************************************/
239 
240 int generic_server::rel_thread_sync_mutex(void)
241 {
242 #ifdef WINDOWS
243  ReleaseMutex(thread_sync_mutex);
244 #else
245  pthread_mutex_unlock(&thread_sync_mutex);
246 #endif
247  return(1);
248 }
249 /*********************************************************************************************/
250 
251 int generic_server::get_command_port(void)
252 {
253  return(command_port);
254 }
255 /*********************************************************************************************/
256 
257 bool generic_server::get_verify_client(void)
258 {
259  return(verify_client);
260 }
261 /*********************************************************************************************/
262 
263 int generic_server::check_allocated_port(string in_plugin_id,string in_plugin_port)
264 {
265  vector <GENERIC_PLUGIN *>::iterator it;
266 
267  for(it = get_start_iterator(); it != get_end_iterator();it++)
268  {
269  if((*it)->get_plugin_name() == in_plugin_id && (*it)->get_port() == atoi(in_plugin_port.c_str()))
270  return(1);
271  }
272  return(0);
273 }
274 /*********************************************************************************************/
275 
276 int generic_server::check_enabled_plugin(string in_plugin_type)
277 {
278  int cnt;
279  vector <GENERIC_PLUGIN *>::iterator it;
280 
281  for(cnt=0,it = get_start_iterator(); it != get_end_iterator();it++)
282  {
283  if((*it)->get_plugin() == in_plugin_type)
284  cnt++;
285  }
286  return(cnt);
287 }
288 /*********************************************************************************************/
289 
290 bool generic_server::check_plugin_aliases(vector<string> &plugin_parms)
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 }
327 /*********************************************************************************************/
328 
329 int generic_server::remove_plugins(map <string,int> &new_ports)
330 {
331  vector <GENERIC_PLUGIN *>::iterator it;
332  map <string,int>::iterator ports_itr;
333  int pos;
334  string new_pluginid;
335 
336  for(pos=0,it = get_start_iterator(); it != get_end_iterator();it++,pos++)
337  {
338  ports_itr = new_ports.find((*it)->get_plugin_name());
339  if(new_ports.empty() || ports_itr == new_ports.end()) // a plugin / port got removed from conf_file
340  {
341  if((*it)->aliases_count()) // Removed plugin in CONF has some alias plugins
342  { // We'll now make first alias plugin as the 'new'
343  new_pluginid = (*it)->pop_alias(); // primary plugin
344  (*it)->set_plugin_name(new_pluginid);
345  }
346  else // Removed plugin in CONF does not have any alias plugins
347  { // remove it from global vector
348  shutdown((*it)->get_socket(),2);
349 #ifdef WINDOWS
350  closesocket((*it)->get_socket());
351 #else
352  close((*it)->get_socket());
353 #endif
354  if( (check_enabled_plugin((*it)->get_plugin())) == 1)
355  (*it)->server_shutdown();
356  unload_shared_lib((*it)->get_plugin());
357  v.erase(get_start_iterator()+pos);
358  pos = 0;
359  it = get_start_iterator();
360  continue;
361  }
362  }
363  }
364  return(1);
365 }
366 /*********************************************************************************************/
367 
368 int generic_server::remove_all_aliases()
369 {
370  vector <GENERIC_PLUGIN *>::iterator it;
371 
372  for(it = get_start_iterator(); it != get_end_iterator();it++)
373  (*it)->clear_aliases();
374  return(1);
375 }
376 /*********************************************************************************************/
377 
378 int generic_server::get_server_params(string line,int start_type)
379 {
380  ostringstream os;
381 
382  if(line.size() > 9 && line.compare(0,9,"LOG_FILE=") == 0)
383  {
384  logname = line.substr(9);
385  if(logname.compare(0,6,"SYSLOG") != 0)
386 #ifdef LINUX
387  {
388  syslog_flag = false;
389  log_file.open(logname.c_str(),ios_base::app);
390  }
391  else
392  {
393  syslog_flag = true;
394  openlog(process_name.c_str(),LOG_NDELAY,LOG_LOCAL0);
395  }
396 #else
397  {
398  syslog_flag = false;
399  log_file.open(logname.c_str(),ios_base::app);
400  }
401  else
402  {
403  syslog_flag = true;
404  el.Init(trim(process_name).c_str());
405  }
406 #endif
407  if(start_type == INIT)
408  {
409  os << " Starting GENERIC_SERVER as: " << trim(process_name) << " with conf file: " << trim(conf_file);
410  log(LOG_LOW,LOG_LOW,os.str());
411  }
412  return(0);
413  }
414  if(line.size() > 13 && line.compare(0,13,"COMMAND_PORT=") == 0)
415  {
416  command_port = atoi(line.substr(13).c_str());
417  return(0);
418  }
419  if(line.size() > 19 && line.compare(0,19,"MAX_LOG_SIZE_IN_MB=") == 0)
420  {
421  max_log_size = atoi(line.substr(19).c_str());
422  max_log_size = max_log_size*1000*1000;
423  return(0);
424  }
425  if(line.size() > 15 && line.compare(0,15,"MAX_LOGS_SAVED=") == 0)
426  {
427  max_logs_saved = atoi(line.substr(15).c_str());
428  return(0);
429  }
430  if (line.size() > 16 && line.compare(0,16,"TIMEOUT_SECONDS=") == 0)
431  {
432  timeout_seconds = atoi(line.substr(16).c_str());
433  return(0);
434  }
435  if (line.size() > 12 && line.compare(0,12,"MAX_THREADS=") == 0)
436  {
437  max_threads = atoi(line.substr(12).c_str());
438  return(0);
439  }
440  if (line.size() > 19 && line.compare(0,19,"SERVER_CERTIFICATE=") == 0)
441  {
442  server_cert = line.substr(19);
443  return(0);
444  }
445  if (line.size() > 16 && line.compare(0,16,"RSA_PRIVATE_KEY=") == 0)
446  {
447  rsa_private_key = line.substr(16);
448  return(0);
449  }
450  if (line.size() > 15 && line.compare(0,15,"CA_CERTIFICATE=") == 0)
451  {
452  ca_certificate = line.substr(15);
453  return(0);
454  }
455  if (line.size() > 14 && line.compare(0,14,"VERIFY_CLIENT=") == 0)
456  {
457  if(atoi(line.substr(14).c_str()))
458  verify_client = true;
459  else
460  verify_client = false;
461  return(0);
462  }
463  if (line.size() > 13 && line.compare(0,13,"PLUGINS_PATH=") == 0)
464  {
465  plugins_path = line.substr(13);
466  return(0);
467  }
468  return(1);
469 }
470 /*********************************************************************************************/
471 
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 }
532 /*****************************************************************************************/
533 
535 {
536  ostringstream os;
537  if(rsa_private_key != "" && server_cert != "" && ca_certificate !="")
538  {
539  if(!tls_setup())
540  {
541  os << " Thr.ID:MAIN TLS_init failed.";
542  log(LOG_LOW,LOG_LOW,os.str());
543  return(0);
544  }
545  }
546  else if(tls_setup_reqd)
547  {
548  os << " Thr.ID:MAIN TLS not correctly setup in CONF file. Please check.";
549  log(LOG_LOW,LOG_LOW,os.str());
550  return(0);
551  }
552 return(1);
553 }
554 /*****************************************************************************************/
555 
557 {
558  ostringstream os;
559 
560  sslserver.set_cert_file(server_cert);
561  sslserver.set_priv_key(rsa_private_key);
562  sslserver.set_ca_cert(ca_certificate);
563  sslserver.set_verify_client(verify_client);
564  if(!sslserver.tls_init())
565  {
566  os << " Thr.ID:MAIN Unable to initiliaze TLS.";
567  log(LOG_LOW,LOG_LOW,(char *)os.str().c_str());
568  return(0);
569  }
570  if(!sslserver.CreateCTX())
571  {
572  os << " Thr.ID:MAIN Unable to set TLS context.";
573  log(LOG_LOW,LOG_LOW,(char *)os.str().c_str());
574  return(0);
575  }
576  if(!sslserver.LoadCerts())
577  {
578  os << " Thr.ID:MAIN Unable to load TLS certificates.";
579  log(LOG_LOW,LOG_LOW,(char *)os.str().c_str());
580  return(0);
581  }
582  os << " Thr.ID:MAIN successfully initialized TLS.";
583  log(LOG_LOW,LOG_LOW,(char *)os.str().c_str());
584  return(1);
585 }
586 /*****************************************************************************************/
587 
588 int generic_server::unload_shared_lib(string plugin_type)
589 {
590 #ifdef WINDOWS
591  FreeLibrary((HMODULE)dll_handles[plugin_type]);
592 #else
593  dlclose(dll_handles[plugin_type]);
594 #endif
595  return(1);
596 }
597 /*****************************************************************************************/
598 
599 GENERIC_PLUGIN *generic_server::load_shared_lib(string library_image,string plugin_type)
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 }
639 /*****************************************************************************************/
640 
641 #ifdef WINDOWS
643 {
644  WSADATA wsaData;
645  int iResult;
646  // Initialize Winsock
647  iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
648  if (iResult != 0)
649  return(0);
650  return(1);
651 }
652 #endif
653 /*****************************************************************************************/
654 
655 int generic_server::socket_close(SOCKET sock)
656 {
657 int iResult;
658  // shutdown the connection since we're done
659  iResult = shutdown(sock, 2);
660 #ifdef WINDOWS
661  closesocket(sock);
662 #else
663  close(sock);
664 #endif
665  if (iResult == SOCKET_ERROR)
666  {
667 #ifdef WINDOWS
668  //WSACleanup();
669 #endif
670  return 0;
671  }
672  return 1;
673 }
674 /*****************************************************************************************/
675 
676 int generic_server::plugin_read_conf_file(GENERIC_PLUGIN *plugin,int thread_no)
677 {
678  ostringstream os;
679  string line,delim,conf_file;
680  conf_file = plugin->plugin_conf_file;
681 
682  delim = "|";
683  ifstream inf(conf_file.c_str());
684  if(!inf.rdbuf()->is_open())
685  {
686  os << " Thr.ID:" << thread_no << " Plugin:" << plugin->get_plugin_name() << " 11 cannot read: " << conf_file;
687  log(LOG_LOW,LOG_LOW,os.str());
688  return(0);
689  }
690  while(getline(inf, line))
691  {
692  line = trim(line);
693  if(line.length() == 0 || line.at(0) == '#')
694  continue;
695  if(!plugin->get_plugin_params(line))
696  continue;
697  }
698  inf.close();
699 return(1);
700 }
701 /*****************************************************************************************/
702 
703 string generic_server::trim(const std::string& s)
704 {
705  if(s.length() == 0)
706  return s;
707  size_t b = s.find_first_not_of(" \t\r\n");
708  size_t e = s.find_last_not_of(" \t\r\n");
709  if(b == -1) // No non-spaces
710  return "";
711  return string(s, b, e - b + 1);
712 }
713 /*****************************************************************************************/
714 
715 string generic_server::get_cur_time(void)
716 {
717 time_t tim;
718 struct tm now;
719 ostringstream os;
720 
721  tim=time(NULL);
722 #ifdef LINUX
723  localtime_r(&tim,&now);
724 #else
725  localtime_s(&now,&tim);
726 #endif
727  os << setw(2) << setfill('0') << now.tm_mon+1 << "/" ;
728  os << setw(2) << setfill('0') << now.tm_mday << "/";
729  os << setw(2) << setfill('0') << now.tm_year+1900 << " ";
730  os << setw(2) << setfill('0') << now.tm_hour << ":";
731  os << setw(2) << setfill('0') << now.tm_min << ":";
732  os << setw(2) << setfill('0') << now.tm_sec;
733  return(os.str());
734 }
735 /*****************************************************************************************/
736 
737 int generic_server::get_thread_id()
738 {
739  THREAD_INFO th_info;
740  int new_thread_id,thread_cnt;
741 #ifdef WINDOWS
742  DWORD dwWaitResult;
743  dwWaitResult = WaitForSingleObject(thread_cnt_mutex,INFINITE);
744 #else
745  pthread_mutex_lock(&thread_cnt_mutex);
746 #endif
747  map<int,THREAD_INFO>::iterator it;
748 
749  for(thread_cnt = 0,it = thread_ids.begin(); it != thread_ids.end();it++,thread_cnt++)
750  {
751  th_info = (THREAD_INFO) (*it).second;
752  if(th_info.state == THREAD_FREE)
753  {
754  th_info = (THREAD_INFO) (*it).second;
755  th_info.state = THREAD_ALLOCATED;
756  thread_ids[thread_cnt] = th_info;
757  new_thread_id = (*it).first;
758  break;
759  }
760  }
761  if(it == thread_ids.end())
762  {
763  th_info.state = THREAD_ALLOCATED;
764  thread_ids[thread_cnt] = th_info;
765  new_thread_id = thread_cnt;
766  }
767 #ifdef WINDOWS
768  ReleaseMutex(thread_cnt_mutex);
769 #else
770  pthread_mutex_unlock(&thread_cnt_mutex);
771 #endif
772  return(new_thread_id);
773 }
774 /*********************************************************************************************/
775 
776 int generic_server::rel_thread_id(int thread_id)
777 {
778  int status;
779 #ifdef WINDOWS
780  DWORD dwWaitResult;
781  dwWaitResult = WaitForSingleObject(thread_cnt_mutex,INFINITE);
782 #else
783  pthread_mutex_lock(&thread_cnt_mutex);
784 #endif
785 
786  if(thread_ids.find(thread_id) != thread_ids.end())
787  {
788  thread_ids[thread_id].state = THREAD_COMPLETED;
789  status = 1;
790  }
791  else
792  status = 0;
793 #ifdef WINDOWS
794  ReleaseMutex(thread_cnt_mutex);
795 #else
796  pthread_mutex_unlock(&thread_cnt_mutex);
797 #endif
798  return(status);
799 }
800 /*********************************************************************************************/
801 
802 int generic_server::close_thread_ids(void)
803 {
804  THREAD_INFO th_info;
805  int thread_cnt;
806 #ifdef WINDOWS
807  DWORD dwWaitResult;
808  dwWaitResult = WaitForSingleObject(thread_cnt_mutex,INFINITE);
809 #else
810  pthread_mutex_lock(&thread_cnt_mutex);
811 #endif
812  map<int,THREAD_INFO>::iterator it;
813 
814  for(thread_cnt = 0,it = thread_ids.begin(); it != thread_ids.end();it++,thread_cnt++)
815  {
816  th_info = (THREAD_INFO) (*it).second;
817  if(thread_ids[thread_cnt].state == THREAD_COMPLETED)
818  {
819 #ifdef WINDOWS
820  CloseHandle(th_info.th);
821 #endif
822  thread_ids[thread_cnt].state = THREAD_FREE;
823  }
824  }
825 #ifdef WINDOWS
826  ReleaseMutex(thread_cnt_mutex);
827 #else
828  pthread_mutex_unlock(&thread_cnt_mutex);
829 #endif
830  return(1);
831 }
832 /*****************************************************************************************/
833 
834 vector <GENERIC_PLUGIN *>::iterator generic_server::get_start_iterator(void)
835 {
836  vector <GENERIC_PLUGIN *>::iterator it = v.begin();
837  return(it);
838 }
839 /*********************************************************************************************/
840 
841 vector <GENERIC_PLUGIN *>::iterator generic_server::get_end_iterator(void)
842 {
843  vector <GENERIC_PLUGIN *>::iterator it = v.end();
844  return(it);
845 }
846 /*********************************************************************************************/
847 
848 int generic_server::print_key_message()
849 {
850  vector <GENERIC_PLUGIN *>::iterator it;
851  GENERIC_PLUGIN tmp_plugin;
852  ostringstream os;
853 
854  log(LOG_LOW,LOG_LOW,(char *)" Thr.ID:MAIN thread. Doing PLUGIN_WALK: ");
855  for(it = get_start_iterator(); it != get_end_iterator();it++)
856  {
857  os.str("");
858  os.clear();
859  os << *(*it);
860  log(LOG_LOW,LOG_LOW,os.str());
861  }
862  os.str("");
863  os.clear();
864  os << " RSA: " << rsa_private_key;
865  os << " CERT: " << server_cert;
866  os << " CA-CERT: " << ca_certificate;
867  log(LOG_LOW,LOG_LOW,os.str());
868  os.str("");
869  os.clear();
870  os << " GENERIC_SERVER framework version: " << get_framework_version() << " using GEN_PLUGIN version: ";
871  os << tmp_plugin.generic_plugin_version() << " ready.";
872  log(LOG_LOW,LOG_LOW,os.str());
873 
874  return(1);
875 }
876 /*********************************************************************************************/
877 
878 int generic_server::set_access_control(char daemon_flag)
879 {
880  ostringstream os;
881 #ifdef LINUX
882  if(getuid() != 0 && !daemon_flag)
883  {
884  os << " Thr.ID:MAIN thread. Only 'root'' user can start generic_server..";
885  log(LOG_LOW,LOG_LOW,os.str());
886  cout << " Thr.ID:MAIN thread. Only 'root' user can start generic_server.." << endl;
887  return(0);
888  }
889 #endif
890  return(1);
891 }
892 /*********************************************************************************************/
893 
894 int generic_server::swap_bytes(unsigned char *key)
895 {
896  unsigned char buff[25];
897  memcpy(buff,key,16);
898  memcpy(key,buff+8,8);
899  memcpy(key+8,buff,8);
900 return(1);
901 }
902 /*********************************************************************************************/
903 
904 int generic_server::bb_getline(char *sav_buffer,size_t length,size_t conn_s)
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 }
941 /*******************************************************************************************/
942 
943 int generic_server::bb_getline(char *sav_buffer,size_t length,size_t conn_s,int secs)
944 {
945  fd_set socks;
946  struct timeval timeout;
947  char str[MAX_SZ];
948  size_t readsock,t;
949  size_t bytes_recvd;
950  bytes_recvd = 0;
951 
952  memset(sav_buffer,0,sizeof(sav_buffer));
953  memset(str,0,MAX_SZ);
954 
955  while(1)
956  {
957  FD_ZERO(&socks);
958  FD_SET(conn_s,&socks);
959  timeout.tv_sec = secs;
960  timeout.tv_usec = 0;
961  readsock = select((int)conn_s+1,&socks,NULL,NULL,&timeout);
962  if(readsock <= 0)
963  return(bytes_recvd);
964  if(FD_ISSET(conn_s,&socks))
965  {
966  if ((t = recv(conn_s,str,sizeof(str), 0)) > 0)
967  {
968  memcpy(sav_buffer,str,t);
969  bytes_recvd += t;
970  if(bytes_recvd >= length)
971  return(bytes_recvd);
972  }
973  else
974  return(bytes_recvd);
975  }
976  }
977 }
978 /******************************************************************************************/
979 
980 int generic_server::get_status(unsigned char *buff)
981 {
982  return(((buff[0]-48)*10)+(buff[1]-48));
983 }
984 /******************************************************************************************/
985 
986 int generic_server::close_log(void)
987 {
988  if(log_file.is_open())
989  log_file.close();
990  return(1);
991 }
992 /******************************************************************************************/
993 
994 int generic_server::get_log_size()
995 {
996 #ifdef WINDOWS
997  struct _stat fileStat;
998 #else
999  struct stat fileStat;
1000 #endif
1001  int err;
1002 
1003 #ifdef WINDOWS
1004  err = _stat(logname.c_str(),&fileStat);
1005 #else
1006  err = stat(logname.c_str(),&fileStat);
1007 #endif
1008  if (err != 0)
1009  return 0;
1010  return fileStat.st_size;
1011 }
1012 /*****************************************************************************************************/
1013 
1014 vector<string> generic_server::split(const string& s, const string& delim, const bool keep_empty = true)
1015 {
1016  vector<string> result;
1017  if (delim.empty())
1018  {
1019  result.push_back(s);
1020  return result;
1021  }
1022  string::const_iterator substart = s.begin(), subend;
1023  while (true)
1024  {
1025  subend = search(substart, s.end(), delim.begin(), delim.end());
1026  string temp(substart, subend);
1027  if (keep_empty || !temp.empty())
1028  result.push_back(temp);
1029  if (subend == s.end())
1030  break;
1031  substart = subend + delim.size();
1032  }
1033  return result;
1034 }
1035 /*****************************************************************************************************/
1036 #ifdef WINDOWS
1037 BOOL generic_server::get_exe_directory(TCHAR *obuf, size_t osize)
1038  {
1039  if(!GetModuleFileName(0, obuf, osize))
1040  {
1041  *obuf = '\0';// insure it's NUL terminated
1042  return FALSE;
1043  }
1044  // run through looking for the *last* slash in this path.
1045  // if we find it, NUL it out to truncate the following
1046  // filename part.
1047  TCHAR*lastslash = 0;
1048  for(; *obuf; obuf++)
1049  {
1050  if (*obuf == '\\' || *obuf == '/')
1051  lastslash = obuf;
1052  }
1053  if(lastslash)
1054  *lastslash = '\0';
1055  return TRUE;
1056 }
1057 /*****************************************************************************************************/
1058 #endif
1059 
1060 int generic_server::reload_conf_file(void)
1061 {
1062  GENERIC_PLUGIN *plugin;
1063  vector <string> plugin_parms;
1064  map <string,int> new_conf_ports;
1065  string line,delim,library_image;
1066  ostringstream os;
1067  vector <GENERIC_PLUGIN *>::iterator it;
1068 
1069  log(LOG_LOW,LOG_LOW,(char *)" Thr.ID:MAIN thread. SIGNAL received to re-read conf file..");
1070  delim = "|";
1071  ifstream inf(conf_file.c_str(),ifstream::in);
1072  if(!inf)
1073  return(0);
1074  close_log();
1075  remove_all_aliases();
1076  while(getline(inf, line))
1077  {
1078  line = trim(line);
1079  if(line.length() == 0 || line.at(0) == '#')
1080  continue;
1081  if(!get_server_params(line,RELOAD))
1082  continue;
1083  if(command_port == 0)
1084  {
1085  os << " Thr.ID:MAIN thread. COMMAND_PORT not defined in CONF file." << endl;
1086  log(LOG_LOW,LOG_LOW,os.str());
1087  command_port = 10000;
1088  return(0);
1089  }
1090  plugin_parms = split(line,delim,true);
1091  set_plugins_path(plugin_parms);
1092  new_conf_ports[plugin_parms.at(PLUGIN_NAME)] = atoi(plugin_parms.at(PORT).c_str());
1093  if(check_allocated_port(plugin_parms.at(PLUGIN_NAME),plugin_parms.at(PORT)))
1094  continue;
1095  // returns true if PLUGIN_NAME is a new alias or an existing alias
1096  // generic_plugin will be updated in case of new alias
1097  if(check_plugin_aliases(plugin_parms))
1098  continue;
1099  plugin = load_shared_lib(plugin_parms.at(SHARED_LIB_PATH),plugin_parms.at(PLUGIN_TYPE));
1100  if(plugin == NULL)
1101  {
1102  os.str("");
1103  os.clear();
1104  os << " Thr.ID:MAIN thread. load_library failed for: " << plugin_parms.at(SHARED_LIB_PATH) << endl;
1105  log(LOG_LOW,LOG_LOW,os.str());
1106  return 0;
1107  }
1108  plugin = initialize_plugin_object(plugin_parms,plugin);
1109  if(plugin == NULL)
1110  return(0);
1111  v.push_back(plugin);
1112  }
1113  inf.close();
1114  remove_plugins(new_conf_ports);
1115  print_key_message();
1116 return(1);
1117 }
1118 /*****************************************************************************************/
1119 
1120 int generic_server::set_plugins_path(vector<string> &plugin_parms)
1121 {
1122  if(plugins_path != "")
1123  {
1124  plugin_parms.at(SHARED_LIB_PATH) = plugins_path + "//" + plugin_parms.at(SHARED_LIB_PATH);
1125  if(plugin_parms.size() > PLUGIN_CONF)
1126  plugin_parms.at(PLUGIN_CONF) = plugins_path + "//" + plugin_parms.at(PLUGIN_CONF);
1127  }
1128  return(1);
1129 }
1130 /*****************************************************************************************/
1131 
1132 string generic_server::get_plugins_path()
1133 {
1134  return(plugins_path);
1135 }
1136 /*****************************************************************************************/
1137 
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 }
1200 /*****************************************************************************************/
1201 
1202 int generic_server::setnonblocking(SOCKET sock)
1203 {
1204  int iResult;
1205 #ifdef WINDOWS
1206  u_long iMode = 1;
1207  iResult = ioctlsocket(sock, FIONBIO, &iMode);
1208  if (iResult != NO_ERROR)
1209  return(0);
1210  return(1);
1211 #else
1212  int opts = fcntl(sock,F_GETFL);
1213  if (opts < 0)
1214  return(0);
1215  opts = (opts | O_NONBLOCK);
1216  if (fcntl(sock,F_SETFL,opts) < 0)
1217  return(0);
1218  return(1);
1219 #endif
1220 }
1221 /*****************************************************************************************/
1222 
1223 int generic_server::setblocking(SOCKET sock)
1224 {
1225  int iResult;
1226 #ifdef WINDOWS
1227  u_long iMode = 0;
1228  iResult = ioctlsocket(sock, FIONBIO, &iMode);
1229  if (iResult != NO_ERROR)
1230  return(0);
1231  return(1);
1232 #else
1233  int opts = fcntl(sock,F_GETFL);
1234  if (opts < 0)
1235  return(0);
1236  opts = (opts | ~O_NONBLOCK);
1237  if (fcntl(sock,F_SETFL,opts) < 0)
1238  return(0);
1239  return(1);
1240 #endif
1241 }
1242 /*****************************************************************************************/
1243 
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 }
1315 /*********************************************************************************************/
1316 
1317 int generic_server::syslog_msg(unsigned int debug_level,unsigned int verbose_level,string data)
1318 {
1319  unsigned int msk = 0xFFFFFFFF;
1320  msk = msk << 4;
1321  debug_level = debug_level & ~msk;
1322  if (verbose_level >= debug_level)
1323  {
1324  switch(debug_level)
1325  {
1326 #ifdef LINUX
1327  case LOG_LOW:
1328  syslog(LOG_INFO,"%s",trim(data).c_str());
1329  break;
1330  case LOG_MEDIUM:
1331  syslog(LOG_NOTICE,"%s",trim(data).c_str());
1332  break;
1333  case LOG_HI:
1334  syslog(LOG_WARNING,"%s",trim(data).c_str());
1335  break;
1336 #else
1337  case LOG_LOW:
1338  el.Write(EVENTLOG_INFORMATION_TYPE, trim(data).c_str());
1339  break;
1340  case LOG_MEDIUM:
1341  el.Write(EVENTLOG_INFORMATION_TYPE, trim(data).c_str());
1342  break;
1343  case LOG_HI:
1344  el.Write(EVENTLOG_WARNING_TYPE, trim(data).c_str());
1345  break;
1346 #endif
1347  }
1348  }
1349 
1350  return(1);
1351 }
1352 /*********************************************************************************************/
1353 
1354 int generic_server::ssl_async_write(SSL *ssl,char *buf,int size)
1355 {
1356  signed int status,status1,ssl_response;
1357  ostringstream oss;
1358  ssl_response = 1;
1359  while(ssl_response == 1)
1360  {
1361  oss.str("");
1362  oss.clear();
1363  status = SSL_write((SSL *)ssl,buf,size);
1364  if(status > 0)
1365  break;
1366  status1 = SSL_get_error((SSL *)ssl,status);
1367  switch(status1)
1368  {
1369  case SSL_ERROR_WANT_READ:
1370  oss << " AWRITE: ERROR: SSL_ERROR_WANT_READ ";
1371  break;
1372 
1373  case SSL_ERROR_WANT_WRITE:
1374  oss << " AWRITE: ERROR: SSL_ERROR_WANT_WRITE ";
1375  break;
1376 
1377  case SSL_ERROR_WANT_CONNECT:
1378  oss << " AWRITE: ERROR: SSL_ERROR_WANT_CONNECT ";
1379  break;
1380 
1381  case SSL_ERROR_WANT_ACCEPT:
1382  oss << " AWRITE: ERROR: SSL_ERROR_WANT_ACCEPT ";
1383  break;
1384 
1385  case SSL_ERROR_SYSCALL:
1386  oss << " AWRITE: ERROR: SSL_ERROR_SYSCALL ";
1387  ssl_response = -1;
1388  break;
1389 
1390  case SSL_ERROR_NONE:
1391  oss << " AWRITE: ERROR: SSL_ERROR_NONE ";
1392  ssl_response = 0;
1393  break;
1394 
1395  case SSL_ERROR_SSL:
1396  oss << " AWRITE: ERROR: SSL_ERROR_SSL ";
1397  ssl_response = -1;
1398  break;
1399 
1400  case SSL_ERROR_ZERO_RETURN:
1401  oss << " AWRITE ERROR: SSL_ERROR_ZERO_RETURN ";
1402  ssl_response = 0;
1403  break;
1404  }
1405  }
1406  if(ssl_response < 0)
1407  {
1408  //log(LOG_LOW,LOG_LOW,oss.str());
1409  return(ssl_response);
1410  }
1411  if(ssl_response == 0)
1412  {
1413  //log(LOG_LOW,LOG_LOW,oss.str());
1414  return(0);
1415  }
1416  return(1);
1417 }
1418 /*********************************************************************************************/
1419 
1420 int generic_server::ssl_async_read(SSL *ssl,char *buf,int size)
1421 {
1422  signed int status,status1,ssl_response;
1423  ostringstream oss;
1424  ssl_response = 1;
1425  while(ssl_response == 1)
1426  {
1427  oss.str("");
1428  oss.clear();
1429  status = SSL_read((SSL *)ssl,buf,size);
1430  if(status > 0)
1431  break;
1432  status1 = SSL_get_error((SSL *)ssl,status);
1433  switch(status1)
1434  {
1435  case SSL_ERROR_WANT_READ:
1436  oss << " AREAD: ERROR: SSL_ERROR_WANT_READ ";
1437  break;
1438 
1439  case SSL_ERROR_WANT_WRITE:
1440  oss << " AREAD: ERROR: SSL_ERROR_WANT_WRITE ";
1441  break;
1442 
1443  case SSL_ERROR_WANT_CONNECT:
1444  oss << " AREAD: ERROR: SSL_ERROR_WANT_CONNECT ";
1445  break;
1446 
1447  case SSL_ERROR_WANT_ACCEPT:
1448  oss << " AREAD: ERROR: SSL_ERROR_WANT_ACCEPT ";
1449  break;
1450 
1451  case SSL_ERROR_SYSCALL:
1452  oss << " AREAD: ERROR: SSL_ERROR_SYSCALL ";
1453  ssl_response = -1;
1454  break;
1455 
1456  case SSL_ERROR_NONE:
1457  oss << " AREAD: ERROR: SSL_ERROR_NONE ";
1458  ssl_response = 0;
1459  break;
1460 
1461  case SSL_ERROR_SSL:
1462  oss << " AREAD: ERROR: SSL_ERROR_SSL ";
1463  ssl_response = -1;
1464  break;
1465 
1466  case SSL_ERROR_ZERO_RETURN:
1467  oss << " AREAD: ERROR: SSL_ERROR_ZERO_RETURN ";
1468  ssl_response = 0;
1469  break;
1470  }
1471  }
1472  if(ssl_response < 0)
1473  {
1474  //log(LOG_LOW,LOG_LOW,oss.str());
1475  return(ssl_response);
1476  }
1477  if(ssl_response == 0)
1478  {
1479  //log(LOG_LOW,LOG_LOW,oss.str());
1480  return(0);
1481  }
1482  return(status);
1483 }
1484 /*********************************************************************************************/
1485 
1486 int generic_server::ssl_async_accept(SSL *ssl)
1487 {
1488  signed int status,status1,ssl_response;
1489  ostringstream oss;
1490  ssl_response = 1;
1491  while(ssl_response == 1)
1492  {
1493  oss.str("");
1494  oss.clear();
1495  status = SSL_accept((SSL *)ssl);
1496  if(status > 0)
1497  break;
1498  status1 = SSL_get_error((SSL *)ssl,status);
1499  switch(status1)
1500  {
1501  case SSL_ERROR_WANT_READ:
1502  oss << " ACCEPT: ERROR: SSL_ERROR_WANT_READ ";
1503  break;
1504 
1505  case SSL_ERROR_WANT_WRITE:
1506  oss << " ACCEPT: ERROR: SSL_ERROR_WANT_WRITE ";
1507  break;
1508 
1509  case SSL_ERROR_WANT_X509_LOOKUP:
1510  oss << " ACCEPT: ERROR: SSL_ERROR_WANT_CONNECT ";
1511  break;
1512 
1513  case SSL_ERROR_SYSCALL:
1514  oss << " ACCEPT: ERROR: SSL_ERROR_SYSCALL ";
1515  ssl_response = -1;
1516  break;
1517 
1518  case SSL_ERROR_NONE:
1519  oss << " ACCEPT: ERROR: SSL_ERROR_NONE ";
1520  ssl_response = 0;
1521  break;
1522 
1523  case SSL_ERROR_SSL:
1524  oss << " ACCEPT: ERROR: SSL_ERROR_SSL ";
1525  ssl_response = -1;
1526  break;
1527 
1528  case SSL_ERROR_ZERO_RETURN:
1529  oss << " ACCEPT: ERROR: SSL_ERROR_ZERO_RETURN ";
1530  ssl_response = 0;
1531  break;
1532  }
1533  }
1534  if(ssl_response <= 0)
1535  {
1536  log(LOG_LOW,LOG_LOW,oss.str());
1537  return(0);
1538  }
1539  return(status);
1540 }
1541 /*********************************************************************************************/
GENERIC_PLUGIN * load_shared_lib(string library_image, string)
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.
Singleton class to manage framework state and provide utility functions. This class stores master Vec...
int rollover_logs(void)
Rolls over log files, configured in Master configuation file.
bool check_plugin_aliases(vector< string > &alias)
This is a singleton class and provides framework functionality.
virtual bool bootstrap_init(string)
This component provides functionality that are common across plug-ins. Framework would instantiate an...
OS agnostic thread handle.
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.
struct thread_info THREAD_INFO
OS agnostic thread handle.
GENERIC_PLUGIN *(* create_fp)()
Every plug-in should have a function with following prototype. This is the factory method: 'create_in...
int tls_initialize()
Validates generic_server framework and CA certificates, calls tls_setup().
This is the base class for all plugins. All plug-ins should derive from this class. This class has a bunch of virtual functions that all plug-in could/should implement. In addition to virtual functions, this class also provides a lot of utility functions for all plug-ins.
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...
GENERIC_PLUGIN * initialize_plugin_object(vector< string > plugin_parms, GENERIC_PLUGIN *plugin)
SOCKET create_socket(int)
int bb_getline(char *sav_buffer, size_t length, size_t conn_s)
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.
int tls_setup(void)
Initializes TLS.
virtual int server_init(void)
Utility class for TLS. Please refer excellent documentation at: http://www.openssl.org/docs/ssl/ssl.html.
static generic_server * instance(void)
Instantiate tis singleton class only once and return pointer to instantiated object later on...
virtual int get_plugin_params(string line)