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_plugin.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 <algorithm>
19 #include <vector>
20 #include <string>
21 #include <sstream>
22 #include <iomanip>
23 using namespace std;
24 
25 #ifdef WINDOWS
26 #include <winsock2.h>
27 #include <ws2tcpip.h>
28 #include <conio.h>
29 #include <process.h>
30 #else
31 #include <sys/socket.h>
32 #include <arpa/inet.h>
33 #include <unistd.h>
34 #include <netinet/in.h>
35 #include <netdb.h>
36 #include <pthread.h>
37 #include <dlfcn.h>
38 #endif
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <openssl/ssl.h>
44 #include <openssl/err.h>
45 #include <stdio.h>
46 #include "generic_plugin.h"
47 #include "generic_server.h"
48 
49 /*********************************************************************************************/
50 
51 ostream& operator<<(ostream& output, generic_plugin& p)
52 {
54  vector<string>::iterator itr;
55  output.clear();
56  output << "(PLUGIN_TYPE: " << setw(12) << setfill(' ') << setiosflags(ios::left) << p.plugin_type << " ";
57  output << " PLUGIN_ID: " << setw(12) << setfill(' ') << setiosflags(ios::left) << p.plugin_name << " ";
58  output << " IP: " << setw(12) << p.local_ip_address;
59  if(p.tls_enabled)
60  output << " TLS_PORT: " << p.port << ")";
61  else
62  output << " RAW_PORT: " << p.port << ")";
63  for(itr = p.v_plugin_aliases.begin(); itr != p.v_plugin_aliases.end(); ++itr)
64  {
65  output << endl;
66  output << fwork->get_cur_time();
67  output << "(PLUGIN_TYPE: " << setw(12) << setfill(' ') << setiosflags(ios::left) << p.plugin_type << " ";
68  output << " ALIAS PLUGIN_ID: " << setw(12) << setfill(' ') << setiosflags(ios::left) << (*itr) << " ";
69  output << " IP: " << setw(12) << p.local_ip_address;
70  if(p.tls_enabled)
71  output << " TLS_PORT: " << p.port << ")";
72  else
73  output << " RAW_PORT: " << p.port << ")";
74  }
75  return output;
76 }
77 /*********************************************************************************************/
78 
79 generic_plugin &generic_plugin::operator=(const generic_plugin &rhs)
80 {
81  if(this != &rhs)
82  {
83  plugin_type = rhs.plugin_type;
84  plugin_number = rhs.plugin_number;
85  plugin_name = rhs.plugin_name;
86  client_socket = rhs.client_socket;
87  server_socket = rhs.server_socket;
88  plugin_conf_file = rhs.plugin_conf_file;
89  networking = rhs.networking;
90  verbose_level = rhs.verbose_level;
91  tls_enabled = rhs.tls_enabled;
92  thread_id = rhs.thread_id;
93  validate_plugin = rhs.validate_plugin;
94  port = rhs.port;
95  pinstance = rhs.pinstance;
96  local_ip_address = rhs.local_ip_address;
97  v_plugin_aliases = rhs.v_plugin_aliases;
98  }
99  return(*this);
100 }
101 /*********************************************************************************************/
102 
103 int generic_plugin::clear_aliases()
104 {
105  this->v_plugin_aliases.clear();
106  return(1);
107 }
108 /*********************************************************************************************/
109 
110 int generic_plugin::set_plugin(string in_plugin)
111 {
112  this->plugin_type = in_plugin;
113  return(1);
114 }
115 /*********************************************************************************************/
116 
117 int generic_plugin::set_conf_file(string conf_file)
118 {
119  plugin_conf_file = conf_file;
120  return(1);
121 }
122 /*********************************************************************************************/
123 
124 int generic_plugin::set_plugin_name(string in_plugin_name)
125 {
126  plugin_name = in_plugin_name;
127  return(1);
128 }
129 /*********************************************************************************************/
130 
131 int generic_plugin::set_plugin_number(string in_plugin_number)
132 {
133  plugin_number = in_plugin_number;
134  return(1);
135 }
136 /*********************************************************************************************/
137 
138 int generic_plugin::set_plugin_path(string plugin_path)
139 {
140  plugin_lib_path = plugin_path;
141  return(1);
142 }
143 /*********************************************************************************************/
144 
145 int generic_plugin::set_tls_flag(int in_tls_flag)
146 {
147  tls_enabled = in_tls_flag;
148  return(1);
149 }
150 /*********************************************************************************************/
151 
152 int generic_plugin::set_socket(SOCKET in_socket)
153 {
154  server_socket = in_socket;
155  return(1);
156 }
157 /*********************************************************************************************/
158 
159 int generic_plugin::set_client_socket(SOCKET in_socket)
160 {
161  client_socket = in_socket;
162  return(1);
163 }
164 /*********************************************************************************************/
165 
166 int generic_plugin::set_port(int in_port)
167 {
168  port = in_port;
169  return(1);
170 }
171 /*********************************************************************************************/
172 
173 int generic_plugin::add_plugin_alias(string plugin_alias)
174 {
175  v_plugin_aliases.push_back(plugin_alias);
176  return(1);
177 }
178 /*********************************************************************************************/
179 
180 bool generic_plugin::find_plugin_alias(string alias_name)
181 {
182  vector<string>::iterator itr;
183  for(itr = v_plugin_aliases.begin(); itr != v_plugin_aliases.end(); ++itr)
184  if((*itr) == alias_name)
185  return(true);
186  return(false);
187 }
188 /*********************************************************************************************/
189 
190 int generic_plugin::aliases_count()
191 {
192  return(v_plugin_aliases.size());
193 }
194 /*********************************************************************************************/
195 
196 string generic_plugin::pop_alias()
197 {
198  string alias_name;
199 
200  alias_name = v_plugin_aliases.front();
201  v_plugin_aliases.erase(v_plugin_aliases.begin());
202  return(alias_name);
203 }
204 /*********************************************************************************************/
205 
206 int generic_plugin::set_thread_id(int in_thread_id)
207 {
208  thread_id = in_thread_id;
209  return(1);
210 }
211 /*********************************************************************************************/
212 
213 string generic_plugin::get_plugin_path()
214 {
215  return(plugin_lib_path);
216 }
217 /*********************************************************************************************/
218 
219 SOCKET generic_plugin::get_socket(void)
220 {
221  return(server_socket);
222 }
223 /*********************************************************************************************/
224 
225 SOCKET generic_plugin::get_client_socket(void)
226 {
227  return(client_socket);
228 }
229 /*********************************************************************************************/
230 
231 string generic_plugin::get_plugin(void)
232 {
233  return(plugin_type);
234 }
235 /*********************************************************************************************/
236 
237 string generic_plugin::get_plugin_name(void)
238 {
239  return(plugin_name);
240 }
241 /*********************************************************************************************/
242 
243 string generic_plugin::get_conf_file(void)
244 {
245  return(plugin_conf_file);
246 }
247 /*********************************************************************************************/
248 
249 string generic_plugin::get_plugin_number(void)
250 {
251  return(plugin_number);
252 }
253 /*********************************************************************************************/
254 
255 int generic_plugin::get_port(void)
256 {
257  return(port);
258 }
259 /*********************************************************************************************/
260 
261 int generic_plugin::get_thread_id(void)
262 {
263  return(thread_id);
264 }
265 /*********************************************************************************************/
266 
267 int generic_plugin::get_tls_flag(void)
268 {
269  return(tls_enabled);
270 }
271 /*********************************************************************************************/
272 
273 bool generic_plugin::get_validate_plugin(void)
274 {
275  return(validate_plugin);
276 }
277 /*********************************************************************************************/
278 
279 generic_plugin::generic_plugin(void)
280 {
281  verbose_level = 2;
282  networking = 1;
283  tls_enabled = 0;
284  local_ip_address = NULL;
285  validate_plugin = true;
286  plugin_name = "";
287  plugin_conf_file = "";
288  plugin_number = "";
289  plugin_type = "";
290  client_socket = 0;
291  server_socket = 0;
292  tls_enabled = 0;
293  pinstance = 0;
294  thread_id = 0;
295 }
296 /*********************************************************************************************/
297 
298 generic_plugin::generic_plugin(char *plugin_name,int plugin_port)
299 {
300  port = plugin_port;
301  plugin_type = plugin_name;
302  networking = 1;
303  tls_enabled = 0;
304  verbose_level = 2;
305  pinstance = 0;
306  local_ip_address = NULL;
307  validate_plugin = true;
308 }
309 /*********************************************************************************************/
310 
311 generic_plugin::generic_plugin(char *plugin_name,char *plugin_id,int plugin_port)
312 {
313  port = plugin_port;
314  plugin_type = plugin_name;
315  plugin_name = plugin_id;
316  networking = 1;
317  tls_enabled = 0;
318  verbose_level = 2;
319  local_ip_address = NULL;
320  validate_plugin = true;
321 }
322 /*********************************************************************************************/
323 
325 {
326  SOCKET ListenSocket, on;
327  struct addrinfo *result = NULL;
328  struct sockaddr_in local_address;
329  struct sockaddr_in *sa;
330  struct addrinfo hints;
331  ostringstream os;
332  int iResult;
333  generic_server *fwork = (generic_server *) pinstance;
334 
335  memset(&local_address,0,sizeof(local_address));
336  memset(&hints, 0,sizeof(hints));
337  hints.ai_family = AF_INET;
338  hints.ai_socktype = SOCK_STREAM;
339  hints.ai_protocol = IPPROTO_TCP;
340  hints.ai_flags = AI_PASSIVE;
341  iResult = getaddrinfo(NULL, port.c_str(), &hints, &result);
342  if (iResult != 0)
343  {
344  os.str("");
345  os.clear();
346  os << fwork->get_cur_time() << " Thr.ID:MAIN getaddrinfo failed.";
347  fwork->log(LOG_LOW,verbose_level,os.str());
348  }
349  // Create a SOCKET for one plugin
350  ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
351  if (ListenSocket == INVALID_SOCKET)
352  {
353  os.str("");
354  os.clear();
355  os << fwork->get_cur_time() << " Thr.ID:MAIN socket creation failed.";
356  fwork->log(LOG_LOW,verbose_level,os.str());
357  freeaddrinfo(result);
358  return 0;
359  }
360  on = 1;
361 #ifdef WINDOWS
362  setsockopt(ListenSocket,SOL_SOCKET, SO_EXCLUSIVEADDRUSE,(char *) &on, sizeof (on));
363 #endif
364  setsockopt(ListenSocket,SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
365  if(!networking)
366  {
367  local_address.sin_family = AF_INET;
368  local_address.sin_addr.s_addr = inet_addr("127.0.0.1");
369  local_address.sin_port = htons(atoi(port.c_str()));
370  iResult = bind(ListenSocket, (sockaddr *) &local_address, (int)result->ai_addrlen);
371  sa = (struct sockaddr_in *) result->ai_addr;
372  local_ip_address = inet_ntoa(local_address.sin_addr);
373  }
374  else
375  {
376  iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
377  sa = (struct sockaddr_in *) result->ai_addr;
378  local_ip_address = inet_ntoa(sa->sin_addr);
379  }
380  if (iResult == SOCKET_ERROR)
381  {
382  os.str("");
383  os.clear();
384  os << fwork->get_cur_time() << " Thr.ID:MAIN socket bind failed for port: " << port;
385  log(LOG_LOW,os.str());
386  freeaddrinfo(result);
387  shutdown(ListenSocket,2);
388 #ifdef WINDOWS
389  closesocket(ListenSocket);
390 #else
391  close(ListenSocket);
392 #endif
393  return 0;
394  }
395  iResult = listen(ListenSocket, SOMAXCONN);
396  if (iResult == SOCKET_ERROR)
397  {
398  os.str("");
399  os.clear();
400  os << fwork->get_cur_time() << " Thr.ID:MAIN socket listen failed for port: " << port;
401  log(LOG_LOW,os.str());
402  shutdown(ListenSocket,2);
403 #ifdef WINDOWS
404  closesocket(ListenSocket);
405 #else
406  close(ListenSocket);
407 #endif
408  return 0;
409  }
410  fwork->setblocking(ListenSocket);
411  freeaddrinfo(result);
412  return(ListenSocket);
413 }
414 /*****************************************************************************************************/
415 
416 string generic_plugin::generic_plugin_version()
417 {
418  return("0_0_0_9");
419 }
420 /*****************************************************************************************************/
421 
423 {
424  generic_server *fwork = (generic_server *) pinstance;
425 
426  if(line.size() > 11 && line.compare(0,11,"NETWORKING=") == 0)
427  {
428  networking = atoi(line.substr(11).c_str());
429  return(0);
430  }
431  if(line.size() > 14 && line.compare(0,14,"VERBOSE_LEVEL=") == 0)
432  {
433  verbose_level = atoi(line.substr(14).c_str());
434  return(0);
435  }
436  if (line.size() > 16 && line.compare(0,16,"VALIDATE_PLUGIN=") == 0)
437  {
438  if(atoi(line.substr(16).c_str()) )
439  validate_plugin = true;
440  else
441  validate_plugin = false;
442  return(0);
443  }
444  return(1);
445 }
446 /*****************************************************************************************************/
447 
448 GEN_PLUGIN_MUTEX generic_plugin::create_mutex(void)
449 {
450  GEN_PLUGIN_MUTEX mutex;
451 #ifdef WINDOWS
452  mutex = CreateMutex( NULL, FALSE, NULL);
453 #else
454  pthread_mutex_init(&mutex,NULL);
455 #endif
456  return(mutex);
457 }
458 /*****************************************************************************************************/
459 
460 int generic_plugin::lock_mutex(GEN_PLUGIN_MUTEX *mutex)
461 {// not using pthread_cond variable, since Windows does not support cond. variables
462 #ifdef WINDOWS
463 DWORD dwWaitResult;
464  dwWaitResult = WaitForSingleObject(*mutex,INFINITE);
465 #else
466  pthread_mutex_lock(mutex);
467 #endif
468  return(1);
469 }
470 /*****************************************************************************************************/
471 
472 int generic_plugin::rel_mutex(GEN_PLUGIN_MUTEX *mutex)
473 {
474 #ifdef WINDOWS
475  ReleaseMutex(mutex);
476 #else
477  pthread_mutex_unlock(mutex);
478 #endif
479  return(1);
480 }
481 /*****************************************************************************************************/
482 
483 int generic_plugin::log(unsigned int debug_level,string data)
484 {
485  generic_server *fwork = (generic_server *) pinstance;
486 
487  return(fwork->log(debug_level,verbose_level,data));
488 }
489 /*****************************************************************************************************/
490 
491 int generic_plugin::log(unsigned int debug_level,char *data)
492 {
493  generic_server *fwork = (generic_server *) pinstance;
494 
495  return(fwork->log(debug_level,verbose_level,(char *) data));
496 }
497 /*****************************************************************************************************/
498 
500 {
501  return("");
502 }
503 /*****************************************************************************************************/
504 
506 {
507  return(true);
508 }
509 /*****************************************************************************************************/
virtual string bootstrap_name(void)
int log(unsigned int, unsigned int, char *)
enables logging to framework managed log file.
GEN_PLUGIN_MUTEX create_mutex(void)
Singleton class to manage framework state and provide utility functions. This class stores master Vec...
vector< string > v_plugin_aliases
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...
int rel_mutex(GEN_PLUGIN_MUTEX *)
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 lock_mutex(GEN_PLUGIN_MUTEX *)
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 get_plugin_params(string line)