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
control.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 #include <iostream>
18 #include <fstream>
19 #include <algorithm>
20 #include <vector>
21 #include <string>
22 #include <sstream>
23 #include <map>
24 #include <utility>
25 using namespace std;
26 
27 #ifdef WINDOWS
28 #include <winsock2.h>
29 #include <process.h>
30 #include <ws2tcpip.h>
31 #include <ctype.h>
32 #include <windows.h>
33 #else
34 #include <sys/socket.h>
35 #include <arpa/inet.h>
36 #include <unistd.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <pthread.h>
40 #include <dlfcn.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <sys/prctl.h>
44 #include <syslog.h>
45 #endif
46 
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <time.h>
51 #include <signal.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <errno.h>
55 #include "sslserver.h"
56 #include "generic_plugin.h"
57 #include "generic_server.h"
58 #include "control.h"
59 #ifdef WINDOWS
60 BOOL CtrlHandler( DWORD fdwCtrlType);
61 #endif
62 /*********************************************************************************************/
63 
64 #ifdef LINUX
65 void *thread_fn(void *inp_arg)
66 #else
67 unsigned _stdcall thread_fn(void *inp_arg)
68 #endif
69 {
70 int thread_no,plugin_init_state,iResult;
71 GENERIC_PLUGIN *plugin_p,*plugin_inp;
72 SOCKET clnt_sock,nfds;
73 fd_set socks;
75 ostringstream oss;
76  fwork->rel_thread_sync_mutex();
77  try
78  {
79  plugin_inp = dynamic_cast<GENERIC_PLUGIN *>((GENERIC_PLUGIN *)inp_arg);
80  plugin_p = (fwork->factory[plugin_inp->get_plugin()])();
81  *plugin_p = *plugin_inp;
82  delete plugin_inp;
83  thread_no = plugin_p->get_thread_id();
84  fwork->plugin_read_conf_file(plugin_p,thread_no);
85  plugin_init_state = 1;
86  clnt_sock = (SOCKET) plugin_p->get_client_socket();
87  iResult = plugin_p->plugin_init(thread_no);
88  if(iResult == 0)
89  plugin_init_state = 0;
90  struct timeval timeout;
91  // This function gets called after client makes a 'connect' request to framework
92  // Loop to read data from one client. One thread -> 1 client
93  while(1)
94  {
95  FD_ZERO(&socks);
96  FD_SET (clnt_sock, &socks);
97  nfds = clnt_sock;
98  timeout.tv_sec = fwork->timeout_seconds;
99  timeout.tv_usec = 0;
100  iResult = select((int)nfds+1, &socks, NULL, NULL, &timeout);
101  if (iResult <= 0) // client did not send any requests within TIMEOUT interval.
102  throw (char *)"97 Thread timeout.";
103  else if (iResult > 0 && FD_ISSET (clnt_sock, &socks))
104  {
105  if(!process_client_req(clnt_sock,plugin_init_state,plugin_p,thread_no,fwork))
106  throw 0;
107  }
108  else
109  throw (char *)"98 client disconnect.";
110  }
111  }
112  catch(int i)
113  {
114  terminate_client_session(clnt_sock,fwork,plugin_p,thread_no,(unsigned char *)"00 Terminating.");
115  }
116  catch(char *cp)
117  {
118  if(cp != 0)
119  terminate_client_session(clnt_sock,fwork,plugin_p,thread_no,(unsigned char *)cp);
120  }
121 #ifdef LINUX
122  return(NULL);
123 #else
124  return(0);
125 #endif
126 }
127 /*********************************************************************************************/
128 
129 #ifdef LINUX
130 void *ssl_thread_fn(void *inp_arg)
131 #else
132 unsigned _stdcall ssl_thread_fn(void *inp_arg)
133 #endif
134 {
135  int thread_no,plugin_init_state;
136  signed int status;
137  GENERIC_PLUGIN *plugin_p,*plugin_inp;
138  SOCKET clnt_sock,nfds;
139  fd_set socks;
140  SSL *ssl;
141  ostringstream oss;
143  fwork->rel_thread_sync_mutex();
144  try
145  {
146  plugin_inp = dynamic_cast<GENERIC_PLUGIN *>((GENERIC_PLUGIN *)inp_arg);
147  plugin_p = (fwork->factory[plugin_inp->get_plugin()])();
148  *plugin_p = *plugin_inp;
149  delete plugin_inp;
150  ssl = SSL_new(fwork->sslserver.get_ctx());
151  thread_no = plugin_p->get_thread_id();
152  fwork->plugin_read_conf_file(plugin_p,thread_no);
153  plugin_init_state = 1;
154  clnt_sock = (SOCKET) plugin_p->get_client_socket();
155  status = SSL_set_fd(ssl, clnt_sock);
156  if(status == 0)
157  throw (char *) "86 SSL_set_fd failed.";
158  if(fwork->get_verify_client())
159  SSL_set_verify(ssl,SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,NULL);
160  status = fwork->ssl_async_accept((SSL *)ssl);
161  if(status == 0)
162  throw (char *) "87 SSL_accept failed.";
163  status = plugin_p->plugin_init(thread_no);
164  if(status == 0)
165  plugin_init_state = 0;
166  struct timeval timeout;
167  // This function gets called after client makes a 'connect' request to framework
168  // Loop to read data from one client. One thread -> 1 client
169  while(1)
170  {
171  FD_ZERO(&socks);
172  FD_SET(clnt_sock, &socks);
173  nfds = clnt_sock;
174  timeout.tv_sec = fwork->timeout_seconds;
175  timeout.tv_usec = 0;
176  status = select((int)nfds+1, &socks, NULL, NULL, &timeout);
177  if (status <= 0) // client did not send any requests within TIMEOUT interval.
178  throw 1;
179  else if (status > 0 && FD_ISSET (clnt_sock, &socks))
180  {
181  if(!process_ssl_client_req(clnt_sock,ssl,plugin_init_state,plugin_p,thread_no,fwork))
182  throw 0;
183  }
184  else
185  throw (char *)"89 client disconnect.";
186  }
187  }
188  catch(int err)
189  {
190  if(err == 1)
191  terminate_ssl_client_session(ssl,fwork,plugin_p,thread_no,(unsigned char *)"88 Thread timeout.");
192  if(err == 0)
193  terminate_ssl_client_session(ssl,fwork,plugin_p,thread_no,(unsigned char *)"00 Terminating.");
194  }
195  catch(char *cp)
196  {
197  if(cp != 0)
198  terminate_ssl_client_session(ssl,fwork,plugin_p,thread_no,(unsigned char *)cp);
199  }
200 #ifdef LINUX
201  return(NULL);
202 #else
203  return(0);
204 #endif
205 }
206 /*********************************************************************************************/
207 
208 static int process_ssl_client_req(SOCKET clnt_sock,SSL *ssl,int plugin_init_state,
209  GENERIC_PLUGIN *plugin_p,int thread_no,generic_server *fwork)
210 {
211 unsigned int size,result;
212 char recvbuf[MAX_SZ];
213 int len,offset,ssl_response;
214 string plugin_name;
215 unsigned char sendbuf[MAX_SZ];
216 ostringstream os;
217 
218  memset(sendbuf,0,MAX_SZ);
219  memset(recvbuf,0,MAX_SZ);
220  size = 0;
221  offset = 0;
222  try
223  {
224  if(plugin_init_state == 0)
225  throw (char *)" 88 Can't inititalize plug-in.";
226  len = recv(SSL_get_fd(ssl), (char*) recvbuf, MAX_SZ, MSG_PEEK);
227  if(len <= 0)
228  throw (char *)" 89 client disconnected.";
229  // MESSAGE HEADER:
230  // SIGNATURE - 4 bytes SIGNATURE for all messages
231  // PAYLOAD_SIZE - 4 bytes network byte order
232  // DATA - PAYLOAD_SIZE data
233  // Data payload:
234  // PLUGIN_NAME_LEN - 4 bytes network byte order (optional)
235  // PLUGIN_NAME - Size as defined by <PLUGIN_NAME_LEN> (optional)
236  // APPLICATION_DATA - PAYLOAD_SIZE-([4+PLUGIN_NAME_LEN])
237  len = fwork->ssl_async_read((SSL *)ssl, recvbuf, 8); // Remove SIGNATURE+PAYLOAD_SIZE
238  if(len < 0)
239  throw (char *)" 90 Invalid data received from client.";
240  if(len == 0)
241  return(0);
242  // check SIGNATURE and get PAYLOAD_SIZE
243  // size is the size_of_data sent by client, this should
244  // exclude SIGNATURE
245  size = get_data_size((unsigned char *)recvbuf);
246  if(size > (unsigned int) MAX_SZ-offset || size == 0)
247  throw 2;
248  len = fwork->ssl_async_read((SSL *)ssl, recvbuf, size);
249  if(len < 0)
250  throw (char *)" 90 Invalid data received from client.";
251  if(len == 0)
252  return(0);
253  if(plugin_p->get_validate_plugin())
254  {
255  offset = 4; // Remove plugin_name_len
256  plugin_name = get_input_plugin_name(recvbuf);
257  offset += plugin_name.length(); // Remove plugin_name
258  if(plugin_name != plugin_p->get_plugin_name())
259  {
260  if(!plugin_p->find_plugin_alias(plugin_name))
261  throw 1;
262  // Moving primary plugin name to alias list for this session..
263  plugin_p->add_plugin_alias(plugin_p->get_plugin_name());
264  // setting alias name as primary Plugin for this thread..
265  plugin_p->set_plugin_name(plugin_name);
266  }
267  }
268  size -= offset;
269  result = plugin_p->process_request(recvbuf+offset,sendbuf,size);
270  if(result == TERMINATE_SESSION)
271  throw 3;
272  add_size(sendbuf,size);
273  ssl_response = fwork->ssl_async_write((SSL *)ssl, (char *)sendbuf, size+8);
274  if(ssl_response < 0)
275  throw (char *)" 93 SSL_write error.";
276  if(ssl_response == 0)
277  throw 3;
278  if(!print_source_hostname(clnt_sock,TLS_REQ,fwork,thread_no,plugin_p))
279  return(0);
280  }
281  catch(char *cp)
282  {
283  os << " Thr.ID:" << thread_no << " Plugin:" << plugin_p->get_plugin_name() << cp;
284  fwork->log(LOG_LOW,LOG_LOW,os.str());
285  return 0;
286  }
287  catch(int err)
288  {
289  switch(err)
290  {
291  case 1:
292  strcpy((char *)sendbuf,"92 Invalid plugin_name sent by client.");
293  case 2:
294  strcpy((char *)sendbuf,"91 Invalid message.");
295  case 3:
296  strcpy((char *)sendbuf,"00 Terminating..");
297  }
298  size = strlen((char *)sendbuf);
299  add_size(sendbuf,size);
300  fwork->ssl_async_write((SSL *)ssl, (char *)sendbuf, size+8);
301  return(0);
302  }
303  return(1);
304 }
305 /*******************************************************************************************/
306 
307 int print_source_hostname(int clnt_sock,int req_type,generic_server *fwork,int thread_no,GENERIC_PLUGIN *plugin_p)
308 {
309  struct sockaddr_storage peer;
310  struct sockaddr_in *s;
311  int peer_len;
312  ostringstream os;
313 
314  peer_len = sizeof(sockaddr_storage);
315  if( (getpeername(clnt_sock, (sockaddr *)&peer,(socklen_t*) &peer_len)) != SOCKET_ERROR)
316  {
317  s = (sockaddr_in *) &peer;
318  os <<" Thr.ID:" << thread_no << " Plugin:" << plugin_p->get_plugin_name() << " Request from: ";
319  os << inet_ntoa(s->sin_addr);
320  }
321  fwork->log(LOG_LOW,LOG_LOW,os.str());
322  return(1);
323 }
324 /*******************************************************************************************/
325 
326 static int process_client_req(SOCKET clnt_sock,int plugin_init_state,GENERIC_PLUGIN *plugin_p,int thread_no,generic_server *fwork)
327 {
328 unsigned int size,result;
329 char recvbuf[MAX_SZ];
330 int len,offset;
331 bool first;
332 string plugin_name;
333 unsigned char sendbuf[MAX_SZ];
334 ostringstream os;
335  memset(sendbuf,0,MAX_SZ);
336  memset(recvbuf,0,MAX_SZ);
337  offset = 0;
338  try
339  {
340  if(plugin_init_state == 0)
341  throw (char *)" 88 Can't inititalize plug-in.";
342  len = recv(clnt_sock, (char*) recvbuf, MAX_SZ, MSG_PEEK);
343  if(len <= 0)
344  throw (char *)" 89 client disconnected.";
345  len = read_socket((unsigned char*) recvbuf,clnt_sock, 8);
346  if(len <= 0)
347  throw (char *)" 90 1 Invalid data received from client.";
348  // MESSAGE HEADER:
349  // SIGNATURE - 4 bytes SIGNATURE for all messages
350  // PAYLOAD_SIZE - 4 bytes network byte order
351  // DATA - PAYLOAD_SIZE data
352  // Data payload:
353  // PLUGIN_NAME_LEN - 4 bytes network byte order (optional)
354  // PLUGIN_NAME - Size as defined by <PLUGIN_NAME_LEN> (optional)
355  // APPLICATION_DATA - PAYLOAD_SIZE-([4+PLUGIN_NAME_LEN])
356 
357  // check SIGNATURE and get PAYLOAD_SIZE
358  // size is the size_of_data sent by client, this should
359  // exclude SIGNATURE
360  size = get_data_size((unsigned char *)recvbuf);
361  if(size > (unsigned int) MAX_SZ-offset || size == 0)
362  throw 2;
363  len = read_socket((unsigned char*) recvbuf,clnt_sock, size);
364  if(len <= 0)
365  throw (char *)" 90 2 Invalid data received from client.";
366  if(plugin_p->get_validate_plugin())
367  {
368  offset = 4; // Remove plugin_name_len
369  plugin_name = get_input_plugin_name(recvbuf);
370  offset += plugin_name.length(); // Remove plugin_name
371  if(plugin_name != plugin_p->get_plugin_name())
372  {
373  if(!plugin_p->find_plugin_alias(plugin_name))
374  throw 1;
375  // Moving primary plugin name to alias list for this session..
376  plugin_p->add_plugin_alias(plugin_p->get_plugin_name());
377  // setting alias name as primary Plugin for this thread..
378  plugin_p->set_plugin_name(plugin_name);
379  }
380  }
381  size -= offset;
382  result = plugin_p->process_request(recvbuf+offset,sendbuf,size);
383  if(result == TERMINATE_SESSION)
384  throw 3;
385  add_size(sendbuf,size);
386  result = send(clnt_sock, (char *)sendbuf,size+8,0);
387  if(result <= 0)
388  throw (char *) " 00 Terminating..";
389  if(!print_source_hostname(clnt_sock,SOCKET_REQ,fwork,thread_no,plugin_p))
390  return(0);
391  }
392  catch(char *cp)
393  {
394  os << " Thr.ID:" << thread_no << " Plugin:" << plugin_p->get_plugin_name() << cp;
395  fwork->log(LOG_LOW,LOG_LOW,os.str());
396  return(0);
397  }
398  catch(int err)
399  {
400  switch(err)
401  {
402  case 1:
403  strcpy((char *)sendbuf,"92 Invalid plugin_name sent by client.");
404  case 2:
405  strcpy((char *)sendbuf,"91 Invalid message.");
406  }
407  size = strlen((char *)sendbuf);
408  add_size(sendbuf,size);
409  send(clnt_sock, (char *)sendbuf,size+8,0);
410  return(0);
411  }
412  return(1);
413 }
414 /*******************************************************************************************/
415 
416 int terminate_client_session(SOCKET clnt_sock,generic_server *fwork, GENERIC_PLUGIN *plugin_p,int thread_no,unsigned char *sendbuf)
417 {
418  int len;
419  ostringstream os;
420 
421  len = strlen((char *)sendbuf);
422  send(clnt_sock, (char *)sendbuf, (int)len, 0 );
423  plugin_p->shutdown_plugin(); // Aborting SESSION..
424  os.str("");
425  os.clear();
426  os << " Thr.ID:" << thread_no << " Plugin:" << plugin_p->get_plugin_name() << " Quitting thread." << sendbuf;
427  fwork->log(LOG_LOW,LOG_LOW,os.str());
428  fwork->socket_close(clnt_sock);
429  delete plugin_p;
430  fwork->rel_thread_id(thread_no);
431  return(1);
432 }
433 /*********************************************************************************************/
434 
435 int terminate_ssl_client_session(SSL *ssl,generic_server *fwork, GENERIC_PLUGIN *plugin_p,int thread_no,unsigned char *sendbuf)
436 {
437  int len,ssl_response,status;
438  ostringstream os;
439  char buf[100];
440 
441  len = strlen((char *)sendbuf);
442  status = recv(SSL_get_fd(ssl), (char*) buf, 10, MSG_PEEK);
443  if(status > 0)
444  {
445  ssl_response = fwork->ssl_async_write((SSL *)ssl, (char *)sendbuf, (int)len);
446  if(ssl_response > 0)
447  {
448  while((SSL_shutdown(ssl)) == 0)
449  ;
450  }
451  }
452  plugin_p->shutdown_plugin();
453  os << " Thr.ID:" << thread_no << " Plugin:" << plugin_p->get_plugin_name() << " Quitting thread." << sendbuf;
454  fwork->log(LOG_LOW,LOG_LOW,os.str());
455  fwork->socket_close(SSL_get_fd(ssl));
456  SSL_free((SSL *)ssl);
457  ERR_free_strings();
458  ERR_remove_state(0);
459  delete plugin_p;
460  fwork->rel_thread_id(thread_no);
461  return(1);
462 }
463 /*******************************************************************************************/
464 
465 #ifdef LINUX
466 int main(int argc, char* argv[])
467 #else
468 VOID start_service(LPSTR* argv)
469 #endif
470 {
471  char pname[100],daemon_flag,cfile[MAX_SZ];
473  ostringstream os;
474  daemon_flag = 0;
475  memset(cfile,0,MAX_SZ);
476 #ifdef LINUX
477  if(argc < 3)
478  {
479  cout << "Usage: generic_server.exe <generic_server_name> <conf file>" << endl;
480  exit(-1);
481  }
482  strncpy(cfile,argv[2],strlen(argv[2]));
483  if(argc == 4)
484  daemon_flag = atoi(argv[3]);
485  strcpy(pname,argv[1]);
486  for(int i = 0;i < argc; i++)
487  memset(argv[i],' ',strlen(argv[i]));
488  strcpy(argv[0],pname);
489  prctl(PR_SET_NAME,(unsigned long)pname,0,0,0);
490 #else
491  string tmp;
492  istringstream iss(GetCommandLine());
493  iss >> tmp;
494  iss >> tmp;
495  if(!tmp.empty())
496  strcpy(cfile,(char *)tmp.c_str());
497  else
498  strcpy(cfile,(char *)"C:\\generic_server\\generic_server.conf");
499  strcpy(pname,argv[0]);
500 #endif
501  framework->set_conf_file(cfile);
502  framework->set_process_name(pname);
503  if(!framework->init())
504  {
505  framework->log(LOG_LOW,LOG_LOW,(char *)" FATAL error. Please check for configuration errors!.");
506  exit(-1);
507  }
508 #ifdef LINUX
509  if(!daemon_flag)
510  daemonize();
511 #else
512  SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE);
513 #endif
514  framework->print_key_message();
515  // Enter infinite loop and dispatch callbacks
516  process_data();
517 }
518 /*******************************************************************************************/
519 #ifndef WINDOWS
520 void daemonize()
521 {
522  int i,lfp;
523  char str[10];
524 
525  if(getppid()==1)
526  return; /* already a daemon */
527  i=fork();
528  if (i < 0)
529  {
530  cerr << "Unable to fork()..." << endl;
531  exit(1); /* can not open */
532  }
533  if (i > 0)
534  exit(0); /* parent exits */
535  /* child (daemon) continues */
536  setsid(); /* obtain a new process group */
537  umask(022); /* set newly created file permissions */
538  signal(SIGCHLD,SIG_IGN); /* ignore child */
539  signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
540  signal(SIGTTOU,SIG_IGN);
541  signal(SIGTTIN,SIG_IGN);
542  signal(SIGPIPE,SIG_IGN);
543  signal(SIGHUP,do_nothing); /* catch hangup signal */
544  signal(SIGTERM,sig_int); /* catch kill signal */
545 }
546 /*****************************************************************************************/
547 #else
548 BOOL WINAPI DllMain(
549  HINSTANCE hinstDLL, // handle to DLL module
550  DWORD fdwReason, // reason for calling function
551  LPVOID lpReserved) // reserved
552 {
553  // Perform actions based on the reason for calling.
554  switch(fdwReason)
555  {
556  case DLL_PROCESS_ATTACH:
557  // Initialize once for each new process.
558  // Return FALSE to fail DLL load.
559  break;
560 
561  case DLL_THREAD_ATTACH:
562  // Do thread-specific initialization.
563  break;
564 
565  case DLL_THREAD_DETACH:
566  //sig_int(0);
567  // Do thread-specific cleanup.
568  break;
569 
570  case DLL_PROCESS_DETACH:
571  //sig_int(0); // Perform any necessary cleanup.
572  break;
573  }
574  return TRUE; // Successful DLL_PROCESS_ATTACH.
575 }
576 /*****************************************************************************************/
577 #endif
578 
579 void sig_int(int sig_num)
580 {
582  vector <GENERIC_PLUGIN *>::iterator it;
583  ostringstream os;
584 
585  os << " Thr.ID:MAIN thread. Signal received to terminate.. " << endl;
586  for(it = framework->get_start_iterator(); it != framework->get_end_iterator();it++)
587  {
588  map<string,bool>::iterator bootstrap_itr = framework->bootstrap_jobs.find((*it)->bootstrap_name());
589  // Cleanup bootstrapped stuff..
590  if(bootstrap_itr != framework->bootstrap_jobs.end() && (*it)->bootstrap_name() != "")
591  {
592  os << "\tThr.ID:MAIN. Invoking bootstrap terminate: " << (*it)->bootstrap_name() << " on plug-in: " << (*it)->get_plugin_name() << endl;
593  if(!(*it)->bootstrap_terminate((*it)->bootstrap_name()))
594  {
595  os << "\tThr.ID:MAIN failed to terminate bootstrap: " << (*it)->bootstrap_name() << " on plug-in: " << (*it)->get_plugin_name() << endl;
596  }
597  framework->bootstrap_jobs.erase(bootstrap_itr);
598  }
599  if( (framework->check_enabled_plugin((*it)->get_plugin())) > 1)
600  it = framework->v.erase(it);
601  else
602  {
603  os << "\tShutting down: " << *(*it) << endl;
604  (*it)->server_shutdown();
605  it = framework->v.erase(it);
606  }
607  }
608  framework->log(LOG_LOW,LOG_LOW,(char *)os.str().c_str());
609  framework->close_log();
610  exit(0);
611 }
612 /*****************************************************************************************/
613 
614 int process_data(void)
615 {
616  SOCKET command_sock;
617  fd_set socks;
618  size_t readsock;
619  unsigned int nfds;
621  struct timeval timeout;
622 
623  timeout.tv_sec = 0;
624  timeout.tv_usec = 20;
625  command_sock = fwork->create_socket(fwork->get_command_port());
626  if(command_sock == 0)
627  return(0);
628  while(1)
629  {
630  nfds = 0;
631  FD_ZERO(&socks);
632  nfds = init_sock_fds(&socks,command_sock);
633  readsock = select(nfds+1,&socks,NULL,NULL,0);
634  if(errno == EINTR)
635  {
636  fwork->reload_conf_file();
637  continue;
638  }
639  if(readsock <= 0)
640  continue;
641  if(chk_command_sock(&socks,command_sock))
642  continue;
643  chk_all_clients(&socks);
644  if(!fwork->syslog_flag)
645  fwork->rollover_logs();
646  }
647 }
648 /*****************************************************************************************/
649 
650 unsigned int init_sock_fds(fd_set *socks,SOCKET command_sock)
651 {
652  unsigned int nfds;
654  nfds = 0;
655  for(fwork->itr = fwork->v.begin(); fwork->itr != fwork->v.end(); ++fwork->itr)
656  {
657  if(nfds < (*fwork->itr)->get_socket())
658  nfds = (unsigned int)(*fwork->itr)->get_socket();
659  FD_SET((*fwork->itr)->get_socket(),socks);
660  }
661  FD_SET(command_sock,socks);
662  return(nfds);
663 }
664 /*****************************************************************************************/
665 
666 int chk_command_sock(fd_set *socks,SOCKET command_sock)
667 {
669  SOCKET clnt_sock;
670 
671  if(FD_ISSET(command_sock,socks))
672  {
673  clnt_sock = accept(command_sock,NULL,NULL);
674  if(clnt_sock < 0)
675  return(0);
676  shutdown(clnt_sock,2);
677 #ifdef WINDOWS
678  closesocket(clnt_sock);
679 #else
680  close(clnt_sock);
681 #endif
682  fwork->reload_conf_file();
683  return(1);
684  }
685  return(0);
686 }
687 /*****************************************************************************************/
688 
689 int launch_thread(GENERIC_PLUGIN *generic_plugin,unsigned int new_slot)
690 {
692 #ifdef LINUX
693  pthread_attr_t attr; // thread attribute
694  // set thread detachstate attribute to DETACHED
695  fwork->get_thread_sync_mutex();
696  pthread_attr_init(&attr);
697  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
698 #endif
699  if(generic_plugin->get_tls_flag())
700  {
701 #ifdef WINDOWS
702  fwork->get_thread_sync_mutex();
703  fwork->thread_ids[new_slot].th = (HANDLE)_beginthreadex(NULL, 0, &ssl_thread_fn, (void *)generic_plugin, 0, NULL );
704 #else
705  pthread_create(&fwork->thread_ids[new_slot].th,&attr,ssl_thread_fn, (void *)generic_plugin);
706 #endif
707  }
708  else
709  {
710 #ifdef WINDOWS
711  fwork->get_thread_sync_mutex();
712  fwork->thread_ids[new_slot].th = (HANDLE)_beginthreadex(NULL, 0, &thread_fn, (void *)generic_plugin, 0, NULL );
713 #else
714  pthread_create(&fwork->thread_ids[new_slot].th,&attr,thread_fn, (void *)generic_plugin);
715 #endif
716  }
717 #ifdef LINUX
718  pthread_attr_destroy(&attr);
719 #endif
720  fwork->close_thread_ids();
721  return(1);
722 }
723 /*****************************************************************************************/
724 
725 int chk_all_clients(fd_set *socks)
726 {
728  SOCKET clnt_sock;
729  unsigned int len,new_slot;
731  char sendbuf[MAX_SZ];
732 
733  memset(sendbuf,0,MAX_SZ);
734  for(fwork->itr = fwork->v.begin(); fwork->itr != fwork->v.end(); ++fwork->itr)
735  {
736  if(FD_ISSET((*fwork->itr)->get_socket(),socks))
737  {
738  clnt_sock = accept((*fwork->itr)->get_socket(),NULL,NULL);
739  if(clnt_sock < 0)
740  continue;
741  fwork->setnonblocking(clnt_sock);
742  len = recv(clnt_sock, (char*) sendbuf, 10, MSG_PEEK);
743  if(len <= 0)
744  {
745  shutdown(clnt_sock,2);
746  fwork->log(LOG_LOW,LOG_LOW,(char *)"85 client disconnected.");
747  continue;
748  }
749  if(fwork->thread_ids.size() >= (unsigned int) fwork->max_threads)
750  {
751  fwork->log(LOG_LOW,LOG_LOW,(char *)"11 Too many threads running. Try later..");
752  shutdown(clnt_sock,2);
753 #ifdef WINDOWS
754  closesocket(clnt_sock);
755 #else
756  close(clnt_sock);
757 #endif
758  }
759  else
760  {
761  fwork->close_thread_ids();
762  generic_plugin = new GENERIC_PLUGIN;
763  *generic_plugin = (GENERIC_PLUGIN) *(*fwork->itr);
764  generic_plugin->set_client_socket(clnt_sock);
765  new_slot = fwork->get_thread_id();
766  generic_plugin->set_thread_id(new_slot);
767  launch_thread(generic_plugin,new_slot);
768  }
769  }
770  }
771  return(1);
772 }
773 /*****************************************************************************************/
774 #ifdef WINDOWS
775 BOOL CtrlHandler( DWORD fdwCtrlType )
776 {
777  switch( fdwCtrlType )
778  {
779  // Handle the CTRL-C signal.
780  case CTRL_C_EVENT:
781  sig_int(fdwCtrlType);
782  return(TRUE);
783  case CTRL_BREAK_EVENT:
784  return(TRUE);
785  default:
786  return FALSE;
787  }
788 }
789 /*****************************************************************************************/
790 #endif
791 
792 void do_nothing(int sig_num)
793 {
794 }
795 /*********************************************************************************************/
796 
797 unsigned int get_data_size(unsigned char *recvbuf)
798 {
799  unsigned int size,plugin_signature;
800 
801  plugin_signature = htonl(PLUGIN_SIGNATURE);
802  // check for PLUGIN_SIGNATURE
803  if(memcmp(recvbuf,(char *)&plugin_signature,4))
804  return(0);
805  memcpy(&size,recvbuf+4,4);
806  size = ntohl(size);
807  return(size);
808 }
809 /*******************************************************************************************/
810 
811 int add_size(unsigned char *recvbuf,unsigned int size)
812 {
813  int sav_size;
814  unsigned int plugin_signature;
815  char buffer[MAX_SZ+8];
816 
817  plugin_signature = htonl(PLUGIN_SIGNATURE);
818  sav_size = size;
819  size = htonl(size);
820  memcpy(buffer,(char *)&plugin_signature,4);
821  memcpy(buffer+4,&size,4);
822  memcpy(buffer+8,recvbuf,sav_size);
823  memcpy(recvbuf,buffer,sav_size+8);
824  return(1);
825 }
826 /*******************************************************************************************/
827 
828 string get_input_plugin_name(char *buffer)
829 {
830  string plugin_name;
831  unsigned int size;
832 
833  memcpy((char *)&size,buffer,4);
834  size = ntohl(size);
835  plugin_name = string(buffer+4,size);
836  return(plugin_name);
837 }
838 /*******************************************************************************************/
839 
840 static int read_socket(unsigned char *buffer,SOCKET sock,int size)
841 {
842  fd_set socks;
843  struct timeval timeout;
844  char str[MAX_SZ];
845  size_t readsock;
846  int t,bytes_recvd;
847  bytes_recvd = 0;
848 
849  memset(buffer,0,sizeof(buffer));
850  memset(str,0,MAX_SZ);
851  while(bytes_recvd < size)
852  {
853  FD_ZERO(&socks);
854  FD_SET(sock,&socks);
855  timeout.tv_sec = 2;
856  timeout.tv_usec = 0;
857  readsock = select((int)sock+1,&socks,NULL,NULL,&timeout);
858  if(readsock <= 0)
859  return(0);
860  if(FD_ISSET(sock,&socks))
861  {
862  t = recv(sock,str,size, 0);
863  if(t > 0)
864  {
865  memcpy(buffer+bytes_recvd,str,t);
866  bytes_recvd += t;
867  if(bytes_recvd >= size)
868  break;
869  }
870  }
871  }
872  return(bytes_recvd);
873 }
874 /**************************************************************************************/
map< int, THREAD_INFO > thread_ids
Map to store all currently running threads.
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...
static int terminate_ssl_client_session(SSL *ssl, generic_server *framework, GENERIC_PLUGIN *plugin_p, int thread_no, unsigned char *senduf)
Definition: control.cpp:435
int rollover_logs(void)
Rolls over log files, configured in Master configuation file.
static int terminate_client_session(SOCKET clnt_sock, generic_server *framework, GENERIC_PLUGIN *plugin_p, int thread_no, unsigned char *senduf)
Definition: control.cpp:416
This is a singleton class and provides framework functionality.
virtual int shutdown_plugin(void)
This component provides functionality that are common across plug-ins. Framework would instantiate an...
static int process_client_req(SOCKET clnt_sock, int plugin_init_state, GENERIC_PLUGIN *plugin_p, int thread_no, generic_server *framework)
static int process_data(void)
Main loop to 'select()' sockets from multiple clients.
Definition: control.cpp:614
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.
virtual int plugin_init(int thread_no)
static int launch_thread(GENERIC_PLUGIN *generic_plugin, unsigned int new_slot)
Definition: control.cpp:689
static int process_ssl_client_req(SOCKET clnt_sock, SSL *ssl, int plugin_init_state, GENERIC_PLUGIN *plugin_p, int thread_no, generic_server *framework)
SOCKET create_socket(int)
virtual int process_request(void *buffer, void *out_buff, unsigned int &size)
Master program that initiates GENERIC_SERVER, spawns a thread for each plug-in and runs message loop ...
vector< GENERIC_PLUGIN * > v
Vector to hold all plug-ins.
map< string, create_fp > factory
Map that has function pointers to 'create_instance()' factory method for all plug-in libraries...
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...