fgms 0.11.8
The
FlightGear MultiPlayer Server
project
server.c
Go to the documentation of this file.
1 /*
2  * server.c - the tracker server itself
3  *
4  * Author: Gabor Toth <tgbp@freemail.hu>
5  * License: GPL
6  *
7  * $Log: server.c,v $
8  * Version 1.2 2006/05/10 21:22:34 koversrac
9  * Comment with author and license has been added.
10  * Version 1.3 2012/07/04 geoff (reports _at_ geoffair _dot_ info)
11  * Add user configuration and help
12  * Version 1.4 2012/08/06 geoff (reports _at_ geoffair _dot_ info)
13  * Fix missing -D y|n options, and chop PostgreSQL help if not compiled
14  * Version 1.5 2012/11/09 hazuki (hstsuki_a-ie _at_ yahoo _dot_ com _dot_ hk)
15  * Better resistance on DoS attack. (Still a lot to be done though)
16  * Version 1.6 2013/10/15 hazuki (hstsuki_a-ie _at_ yahoo _dot_ com _dot_ hk)
17  * Code cleanup, some minor fixes and better resistance on DoS attack.
18  * [FIX] msg count overflow if count > 4294967295 (Now counter stops when count = 4294967295)
19  * [FIX] Stop retry on PQ connect when fail count <120, but keeps receiving msg (msg lost)
20  * Starting from this version, older version of fgms which do not require FGTracker reply "OK" will not be supported.
21  * Please use FGTracker version 1.5 if your fgms client is below 0.10.23 or between 0.11 and 0.11.5
22  *
23  *
24  * Current version (Version 1.6) supports the following fgms:
25  * v0.10 : v0.10.23 and above
26  * v0.11 : v0.11.6 and above
27  */
28 
29 #include "fgt_common.h"
30 #include "wrappers.h"
31 #include "fgt_error.h"
32 #ifndef NO_POSTGRESQL
33 #include <libpq-fe.h>
34 #endif // NO_POSTGRESQL
35 #if defined(_MSC_VER) || defined(USE_PTHREAD)
36 #include <pthread.h>
37 #endif // _MSC_VER or USE_PTHREAD
38 #define FGT_VERSION "1.6"
39 #define PORT_SCAN_SPEED 20 /* 1000000/PORT_SCAN_SPEED must be integer*/
40 
41 // static int run_as_daemon = RUN_AS_DAEMON;
42 static int run_as_daemon = 0;
43 
44 static uint32_t server_port = SERVER_PORT;
45 static char *server_addr = 0;
46 
47 /* postgresql default values */
48 #ifndef DEF_IP_ADDRESS
49 #define DEF_IP_ADDRESS "192.168.1.105"
50 #endif
51 
52 #ifndef DEF_PORT
53 #define DEF_PORT "5432"
54 #endif
55 
56 #ifndef DEF_DATABASE
57 #define DEF_DATABASE "fgtracker"
58 #endif
59 
60 #ifndef DEF_USER_LOGIN
61 #define DEF_USER_LOGIN "fgtracker"
62 #endif
63 
64 #ifndef DEF_USER_PWD
65 #define DEF_USER_PWD "fgtracker"
66 #endif
67 
68 static char *ip_address = (char *)DEF_IP_ADDRESS;
69 static char *port = (char *)DEF_PORT;
70 static char *database = (char *)DEF_DATABASE;
71 static char *user = (char *)DEF_USER_LOGIN;
72 static char *pwd = (char *)DEF_USER_PWD;
73 
74 #ifdef NO_POSTGRESQL
75 typedef struct tagPGconn {
76  FILE * fp;
77 }PGconn;
78 #else // !NO_POSTGRESQL = use PostreSQL
79 static char *pgoptions = (char *)"";
80 static char *pgtty = (char *)"";
81 #endif // NO_POSTGRESQL
82 
83 #ifdef _MSC_VER
84 #define pid_t int
85 int getpid(void) {
86  return (int)GetCurrentThreadId();
87 }
88 #define snprintf _snprintf
89 #define sleep(a) Sleep(a * 1000)
90 #define usleep(a) uSleep(a)
91 void uSleep(int waitTime) {
92  LARGE_INTEGER _time1, _time2, _freq;
93  _time1.QuadPart = 0;
94  _time2.QuadPart = 0;
95  _freq.QuadPart = 0;
96  QueryPerformanceCounter(&_time1);
97  QueryPerformanceFrequency(&_freq);
98 
99  do {
100  QueryPerformanceCounter(&_time2);
101  } while ( (_time2.QuadPart - _time1.QuadPart) < waitTime );
102 }
103 #endif // _MSC_VER
104 
105 
106 int
108 {
109 #ifndef _MSC_VER
110  pid_t pid;
111 
112  if ( (pid = fork()) < 0)
113  return(-1);
114  else if (pid != 0)
115  exit(0); /* parent goes bye-bye */
116 
117  /* child continues */
118  setsid(); /* become session leader */
119 
120  if(chdir("/")) /* change working directory */
121  return(1);
122 
123  umask(0); /* clear our file mode creation mask */
124 #endif // !_MSC_VER
125 
126  return(0);
127 }
128 
129 void sigchld_handler(int s)
130 {
131 #ifndef _MSC_VER
132  pid_t childpid;
133  char debugstr[MAXLINE];
134 
135  while( (childpid=waitpid(-1, NULL, WNOHANG)) > 0)
136  {
137  sprintf(debugstr,"Child stopped: %d",childpid);
138  debug(1,debugstr);
139  }
140 #endif // !_MSC_VER
141 }
142 
143 void signal_handler(int s)
144 {
145  #ifndef _MSC_VER
146  char debugstr[MAXLINE];
147  pid_t mypid = getpid();
148 
149  switch (s)
150  {
151  case 1:
152  sprintf(debugstr,"[%d] SIGHUP received, exiting...",mypid);
153  debug(1,debugstr);
154  exit(0);
155  break;
156  case 2:
157  sprintf(debugstr,"[%d] SIGINT received, exiting...",mypid);
158  debug(1,debugstr);
159  exit(0);
160  break;
161  case 3:
162  sprintf(debugstr,"[%d] SIGQUIT received, exiting...",mypid);
163  break;
164  case 4:
165  sprintf(debugstr,"[%d] SIGILL received",mypid);
166  break;
167  case 5:
168  sprintf(debugstr,"[%d] SIGTRAP received",mypid);
169  break;
170  case 6:
171  sprintf(debugstr,"[%d] SIGABRT received",mypid);
172  break;
173  case 7:
174  sprintf(debugstr,"[%d] SIGBUS received",mypid);
175  break;
176  case 8:
177  sprintf(debugstr,"[%d] SIGFPE received",mypid);
178  break;
179  case 9:
180  sprintf(debugstr,"[%d] SIGKILL received",mypid);
181  debug(1,debugstr);
182  exit(0);
183  break;
184  case 10:
185  sprintf(debugstr,"[%d] SIGUSR1 received",mypid);
186  break;
187  case 11:
188  sprintf(debugstr,"[%d] SIGSEGV received. Exiting...",mypid);
189  exit(1);
190  break;
191  case 12:
192  sprintf(debugstr,"[%d] SIGUSR2 received",mypid);
193  break;
194  case 13:
195  sprintf(debugstr,"[%d] SIGPIPE received. Connection Error. Exiting...",mypid);
196  debug(1,debugstr);
197  exit(0);
198  break;
199  case 14:
200  sprintf(debugstr,"[%d] SIGALRM received",mypid);
201  break;
202  case 15:
203  sprintf(debugstr,"[%d] SIGTERM received",mypid);
204  debug(2,debugstr);
205  exit(0);
206  break;
207  case 16:
208  sprintf(debugstr,"[%d] SIGSTKFLT received",mypid);
209  break;
210  case 17:
211  sprintf(debugstr,"[%d] SIGCHLD received",mypid);
212  break;
213  case 18:
214  sprintf(debugstr,"[%d] SIGCONT received",mypid);
215  break;
216  case 19:
217  sprintf(debugstr,"[%d] SIGSTOP received",mypid);
218  break;
219  case 20:
220  sprintf(debugstr,"[%d] SIGTSTP received",mypid);
221  break;
222  case 21:
223  sprintf(debugstr,"[%d] SIGTTIN received",mypid);
224  break;
225  case 22:
226  sprintf(debugstr,"[%d] SIGTTOU received",mypid);
227  break;
228  case 23:
229  sprintf(debugstr,"[%d] SIGURG received",mypid);
230  break;
231  case 24:
232  sprintf(debugstr,"[%d] SIGXCPU received",mypid);
233  break;
234  case 25:
235  sprintf(debugstr,"[%d] SIGXFSZ received",mypid);
236  break;
237  case 26:
238  sprintf(debugstr,"[%d] SIGVTALRM received",mypid);
239  break;
240  case 27:
241  sprintf(debugstr,"[%d] SIGPROF received",mypid);
242  break;
243  case 28:
244  sprintf(debugstr,"[%d] SIGWINCH received",mypid);
245  break;
246  case 29:
247  sprintf(debugstr,"[%d] SIGIO received",mypid);
248  break;
249  case 30:
250  sprintf(debugstr,"[%d] SIGPWR received",mypid);
251  break;
252  default:
253  sprintf(debugstr,"[%d] signal %d received",mypid,s);
254 
255  }
256  debug(2,debugstr);
257  #endif // !_MSC_VER
258 }
259 
260 #ifdef NO_POSTGRESQL
261 #define CONNECTION_OK 0
262 #define CONNECTION_FAILED -1
263 int PQstatus(PGconn *conn)
264 {
265  if (conn && conn->fp)
266  return CONNECTION_OK;
267  return CONNECTION_FAILED;
268 }
269 int PQfinish( PGconn *conn )
270 {
271  if (conn) {
272  if (conn->fp)
273  fclose(conn->fp);
274  conn->fp = 0;
275  free(conn);
276  }
277  return 0;
278 }
279 
280 #ifndef DEF_MESSAGE_LOG
281 #define DEF_MESSAGE_LOG "fgt_server.log"
282 #endif
283 
284 static char *msg_log = (char *)DEF_MESSAGE_LOG;
285 static FILE *msg_file = NULL;
286 static void write_message_log(const char *msg, int len)
287 {
288  if (msg_file == NULL) {
289  msg_file = fopen(msg_log,"ab");
290  if (!msg_file) {
291  printf("ERROR: Failed to OPEN/append %s log file!\n", msg_log);
292  msg_file = (FILE *)-1;
293  }
294  }
295  if (len && msg_file && (msg_file != (FILE *)-1)) {
296  int wtn = (int)fwrite(msg,1,len,msg_file);
297  if (wtn != len) {
298  fclose(msg_file);
299  msg_file = (FILE *)-1;
300  printf("ERROR: Failed to WRITE %d != %d to %s log file!\n", wtn, len, msg_log);
301  } else {
302  if (msg[len-1] != '\n')
303  fwrite((char *)"\n",1,1,msg_file);
304  fflush(msg_file); // push it to disk now
305  }
306  }
307 }
308 
309 #endif // NO_POSTGRESQL
310 
311 /* --------------------------------------
312 PGconn *PQsetdbLogin(const char *pghost,
313  const char *pgport,
314  const char *pgoptions,
315  const char *pgtty,
316  const char *dbName,
317  const char *login,
318  const char *pwd);
319  ------------------------------------- */
320 
321 
322 int ConnectDB(PGconn **conn)
323 {
324  int iret = 0; /* assume no error */
325  char debugstr[MAXLINE];
326 #ifdef NO_POSTGRESQL
327  FILE *fp;
328  PGconn *cp;
329  *conn = (PGconn *)malloc(sizeof(PGconn));
330  if (!*conn) {
331  printf("ERROR: memory allocation FAILED! Aborting...\n");
332  exit(1);
333  }
334  fp = fopen(database,"a");
335  cp = *conn;
336  if (fp) {
337  cp->fp = fp;
338  } else {
339  sprintf(debugstr, "Connection to database failed: %s. NO OPEN/Append",database);
340  debug(1,debugstr);
341  PQfinish(*conn);
342  iret = 1;
343  }
344 #else // !NO_POSTGRESQL
345 
346  *conn = PQsetdbLogin(ip_address, port, pgoptions, pgtty, database, user, pwd);
347 
348  if (PQstatus(*conn) != CONNECTION_OK)
349  {
350  sprintf(debugstr, "Connection to database failed: %s",PQerrorMessage(*conn));
351  debug(1,debugstr);
352  PQfinish(*conn);
353  iret = 1;
354  }
355 #endif // NO_POSTGRESQL y/n
356  return iret;
357 }
358 
359 #ifdef NO_POSTGRESQL
360 #else // !#ifdef NO_POSTGRESQL
361 void SQL_Error(PGconn *conn)
362 {
363  char debugstr[MAXLINE];
364  char *SQLErrorMsg = (char*) calloc(20,1);
365  strncpy(SQLErrorMsg, PQerrorMessage(conn), 20);
366  sprintf(debugstr, "Command failed: %s.", PQerrorMessage(conn));
367  debug(1,debugstr);
368 
369  /*Sometimes the fgms sends invalid packets. Below is a workaround to prevent unnessary forced exit.
370  Example of Invalid messgae are:
371  POSITION * Bad Client * 0 0 . 2012-12-03 21:03:53
372  DISCONNECT * Bad Client * * unknown * 2012-12-03 20:56:32
373  POSITION franck test . . . 2012-12-08 14:28:42
374  */
375 
376  if (strcmp ( SQLErrorMsg, "ERROR: syntax error")!=0 && strcmp ( SQLErrorMsg, "ERROR: invalid inpu")!=0)
377  {
378  sprintf(debugstr, "Force exit due to unrecoverable error.");
379  debug(1,debugstr);
380  exit (1);
381  }
382  free(SQLErrorMsg);
383 
384 }
385 #endif // #ifdef NO_POSTGRESQL y/n
386 
387 int logFlight(PGconn *conn,char *callsign,char *model, char *date, int connect)
388 {
389  #ifdef NO_POSTGRESQL
390  return 0;
391  #else // !#ifdef NO_POSTGRESQL
392  PGresult *res;
393  char statement[MAXLINE];
394  char date2[MAXLINE];
395  char callsign2[MAXLINE];
396  char model2[MAXLINE];
397  int error;
398 
399  PQescapeStringConn (conn, date2, date, MAXLINE, &error);
400  PQescapeStringConn (conn, callsign2, callsign, MAXLINE, &error);
401  PQescapeStringConn (conn, model2, model, MAXLINE, &error);
402 
403  sprintf(statement,"UPDATE flights SET status='CLOSED',end_time='%s' WHERE callsign='%s' AND status='OPEN';",date2,callsign2);
404  res = PQexec(conn, statement);
405  if (PQresultStatus(res) != PGRES_COMMAND_OK)
406  SQL_Error(conn);
407  PQclear(res);
408 
409  if (connect)
410  {
411  sprintf(statement,"INSERT INTO flights (callsign,status,model,start_time) VALUES ('%s','OPEN','%s','%s');",callsign2,model2,date2);
412  res = PQexec(conn, statement);
413  if (PQresultStatus(res) != PGRES_COMMAND_OK)
414  SQL_Error(conn);
415  PQclear(res);
416  }
417  return(0);
418  #endif // #ifdef NO_POSTGRESQL y/n
419 }
420 
421 int logPosition(PGconn *conn, char *callsign, char *date, char *lon, char *lat, char *alt)
422 {
423 #ifdef NO_POSTGRESQL
424  return 0;
425 #else // !#ifdef NO_POSTGRESQL
426  PGresult *res;
427  char statement[MAXLINE];
428  char date2[MAXLINE];
429  char callsign2[MAXLINE];
430  char lon2[MAXLINE];
431  char lat2[MAXLINE];
432  char alt2[MAXLINE];
433  int error;
434 
435  PQescapeStringConn (conn, date2, date, MAXLINE, &error);
436  PQescapeStringConn (conn, callsign2, callsign, MAXLINE, &error);
437  PQescapeStringConn (conn, lon2, lon, MAXLINE, &error);
438  PQescapeStringConn (conn, lat2, lat, MAXLINE, &error);
439  PQescapeStringConn (conn, alt2, alt, MAXLINE, &error);
440 
441  sprintf(statement," INSERT INTO waypoints "
442  " (flight_id,time,latitude,longitude,altitude) "
443  " VALUES ((SELECT id FROM flights WHERE callsign='%s' and status='OPEN'),'%s',%s,%s,%s);",callsign2,date2,lat2,lon2,alt2);
444 
445  res = PQexec(conn, statement);
446  if (PQresultStatus(res) != PGRES_COMMAND_OK)
447  SQL_Error(conn);
448  PQclear(res);
449 
450  return(0);
451 #endif // #ifdef NO_POSTGRESQL y/n
452 }
453 
454 /* =============================================
455  FIX20120812 - Due to the fact that at present
456  the CALLSIGN sent from fgfs to fgms, and
457  from fgms to fgt_server can contain SPACE
458  write a parser to not trip on the space.
459  BUT this parser depend on the FACT that
460  at the moment fgms uses ' test ' as the passwd
461  in the ASCII message transferred.
462  ============================================= */
463 
464 // TODO - For Windows must shift out strerror(errno)
465 // providing and alternative for windows sockets
466 
467 // establish message types
468 enum MsgType {
477 };
478 
479 // some easy very specific macros
480 #define EatSpace for ( ; i < len; i++ ) { \
481  if (msg[i] > ' ') break; }
482 
483 #define Collect(a) off = 0;\
484  for ( ; i < len; i++ ) { \
485  c = msg[i]; \
486  if ( c <= ' ' ) break; \
487  a[off++] = (char)c; \
488  } \
489  a[off] = 0
490 
491 #define ISUPPER(a) (( a >= 'A' )&&( a <= 'Z' ))
492 
493 int parse_message( char * msg, char *event,
494  char *callsign, char *passwd, char *model,
495  char *lat, char *lon, char *alt,
496  char *time1, char *time2 )
497 {
498  int iret = MT_UNKNOWN;
499  size_t len = strlen(msg);
500  size_t i, off, j;
501  int c;
502  char *cp;
503 
504  off = 0;
505  // forget some 'bad' message
506  if ( !ISUPPER(*msg) )
507  return MT_UNKNOWN; // does NOT start with upper
508 
509  for ( i = 0; i < len; i++ ) {
510  c = msg[i];
511  if (!ISUPPER(c))
512  break;
513  event[off++] = (char)c;
514  }
515  event[off] = 0; // zero terminate the string
516 
517  // deal with some short message types
518  if (strcmp(event,"NOWAIT") == 0)
519  return MT_NOWAIT; // all done
520  if (strcmp(event,"REPLY") == 0)
521  return MT_REPLY; // all done
522  else if (strcmp(event,"PING") == 0)
523  return MT_PING; // all done
524  else if (strcmp(event,"PONG") == 0)
525  return MT_PONG; // all done
526  else if (strcmp(event,"CONNECT") == 0)
527  iret = MT_CONNECT;
528  else if (strcmp(event,"DISCONNECT") == 0)
529  iret = MT_DISCONNECT;
530  else if (strcmp(event,"POSITION") == 0)
531  iret = MT_POSITION;
532  else
533  return MT_UNKNOWN; // should not happen, but...
534 
535  EatSpace;
536  // Expect up to an 8 character CALLSIGN, but
537  // unfortunatley CAN have spaces, so...
538  Collect(callsign);
539  // it WILL currently be followed by 'test '
540  // 123456
541  cp = strstr(&msg[i]," test ");
542  if (!cp) {
543  // TODO - could return unknown, but
544  //return MT_UNKNOWN;
545  cp = &msg[i];
546  }
547  j = (size_t)( cp - &msg[i] );
548  // collect BALANCE of the callsign
549  // TODO - Maybe here CHANGE spaces to some
550  // other character so no trouble with SQL
551  // commands as well...
552  for ( ; j && (i < len); i++) {
553  c = msg[i];
554  if (c <= ' ')
555  c = '-';
556  callsign[off++] = (char)c;
557  j--;
558  }
559  callsign[off] = 0;
560 
561  EatSpace;
562  Collect(passwd);
563  EatSpace;
564 
565  // now changes for type
566  if (iret == MT_POSITION) {
567  Collect(lat);
568  EatSpace;
569  Collect(lon);
570  EatSpace;
571  Collect(alt);
572  // TODO - Could validate these values
573  } else { // if ((iret == MT_CONNECT)||(iret == MT_DISCONNECT))
574  Collect(model);
575  }
576 
577  // collect time strings - TODO - could add validation
578  EatSpace;
579  Collect(time1); // date YYYY-MM-DD
580  EatSpace;
581  Collect(time2); // time HH:MM:SS
582  return iret;
583 }
584 // remove macros
585 #undef EatSpace
586 #undef Collect
587 
588 void doit(int fd)
589 {
590  // put these BIG buffers outside the function stack
591  static char debugstr[MAXLINE];
592  static char msg[MSGMAXLINE];
593  static char event[MAXLINE];
594  static char callsign[MAXLINE];
595  static char passwd[MAXLINE];
596  static char model[MAXLINE];
597  static char time1[MAXLINE];
598  static char time2[MAXLINE];
599  static char time[MAXLINE];
600  static char lon[MAXLINE];
601  static char lat[MAXLINE];
602  static char alt[MAXLINE];
603  static char *clientip;
604  char b;
605  uint16_t clientport =1;
606  int i=0;
607  int pg_reconn_counter;
608  short int time_out_counter_l=1;
609  unsigned int time_out_counter_u=0;
610  short int time_out_fraction=PORT_SCAN_SPEED;
611  int len;
612  pid_t mypid;
613  struct sockaddr_in clientaddr;
614  socklen_t clientaddrlen;
615  PGconn *conn = NULL;
616  short int reply = 0;
617  short int nowait = 0;
618  short int sockect_read_completed =0;
619  int res, sendok;
620  unsigned long no_of_line=0;
621 
622 #ifdef _MSC_VER
623  u_long opts = 1;
624  int status = ioctlsocket(fd, FIONBIO, &opts);
625  mypid = getpid();
626  if (SERROR(status)) {
627  sprintf(debugstr,"[%d] FAILED to set the socket to non-blocking mode. Exiting...",mypid);
628  exit (0);
629  } else {
630  sprintf(debugstr,"[%d] Socket set to non-blocking mode. %d scans per second",mypid,time_out_fraction);
631  }
632 #else // !_MSC_VER
633  mypid = getpid();
634  if(fcntl(fd, F_GETFL) & O_NONBLOCK)
635  {
636  // socket is non-blocking
637  sprintf(debugstr,"[%d] Socket is in non-blocking mode",mypid);
638  } else
639  {
640  sprintf(debugstr,"[%d] Socket is in blocking mode",mypid);
641  debug(2,debugstr);
642  if(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) < 0)
643  {
644  sprintf(debugstr,"[%d] FAILED to set the socket to non-blocking mode. Exiting...",mypid);
645  exit (0);
646  }
647  else
648  sprintf(debugstr,"[%d] Socket set to non-blocking mode. %d scans per second",mypid,time_out_fraction);
649 
650  }
651 #endif // _MSC_VER y/n
652  debug(2,debugstr);
653 
654  clientaddrlen = sizeof(struct sockaddr_in);
655  while (getpeername(fd, (SA *) &clientaddr, &clientaddrlen)==-1)
656  {
657  sprintf(debugstr,"[%d] Failed to get IP address of client! 1 sec to retry.",mypid);
658  debug(2,debugstr);
659  if (i>10)
660  {
661  sprintf(debugstr,"[%d] Stop retrying to get the client address.",mypid);
662  debug(2,debugstr);
663  clientip = "Unknown";
664  break;
665  }
666  sleep(1);
667  i++;
668  }
669  if (i<=10)
670  {
671  sprintf(debugstr,"[%d] Got IP address of client. CIP %s POR %d",mypid,inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
672  debug(2,debugstr);
673  clientip = inet_ntoa(clientaddr.sin_addr);
674  clientport = ntohs(clientaddr.sin_port);
675  }
676  i=0;
677 
678  while (1)
679  {
680  i=0;
681  len = strlen(msg);
682 
683  if (nowait==0)
684  {
685  len = SREAD(fd, msg, MSGMAXLINE-1);
686  if (len>0)
687  sockect_read_completed=1;
688  }
689  else
690  {
691  do
692  { /*Maximun character in a line : MSGMAXLINE-1. msg[MSGMAXLINE] = '\0'*/
693  if (len==MSGMAXLINE-1)
694  {
695  sockect_read_completed=1;
696  break;
697  }
698  i = recv( fd, &b, sizeof( b ), 0 );
699  msg[len]=b;
700  if (b=='\0' && i>=1)
701  {
702  sockect_read_completed=1;
703  break;
704  }
705  if (i<1)
706  break;
707  }while(len++);
708  }
709  i=0;
710  msg[len]='\0';
711 
712  if (sockect_read_completed==0)
713  {
714  usleep(1000000/time_out_fraction);
715  time_out_counter_l++;
716  if (time_out_counter_l==time_out_fraction)
717  {
718  time_out_counter_u++;
719  time_out_counter_l=0;
720  }
721  if (time_out_counter_u%60==0 && time_out_counter_u >=120 && time_out_counter_l==0)
722  { /*Print warning*/
723  snprintf(debugstr,MAXLINE,"[%d] %s:%d: Warning: No data receive from client for %d seconds",mypid,clientip,clientport,time_out_counter_u);
724  debug(1,debugstr);
725  }
726  if (time_out_counter_u%120==0 && time_out_counter_l==0)
727  { /*Send PING*/
728  if (SWRITE(fd,"PING",5) != 5)
729  {
730  sprintf(debugstr,"[%d] %s:%d: Write PING failed! - %s", mypid, clientip,clientport,strerror(errno));
731  sprintf(debugstr,"[%d] %s:%d: Connection lost. Exiting...", mypid, clientip,clientport);
732  debug(1,debugstr);
733  exit(0);
734  }
735  else
736  sprintf(debugstr,"[%d] %s:%d: Wrote PING. Waiting reply", mypid, clientip,clientport);
737  debug(1,debugstr);
738  }
739  if (time_out_counter_u%300==0 && time_out_counter_l==0)/*Exit*/
740  break;
741  continue;
742  }
743  sockect_read_completed=0;
744  time_out_counter_l=1;
745  time_out_counter_u=0;
746 
747  if (no_of_line!=4294967295)/*Prevent unsigned long overflow and return to zero count*/
748  no_of_line++;
749  snprintf(debugstr,MAXLINE,"[%d] %s:%d: Read %d bytes",mypid,clientip,clientport,len);
750  debug(3,debugstr);
751 
752  // no need to clear the WHOLE buffer - just first byte
753  event[0] = 0;
754  callsign[0] = 0;
755  passwd[0] = 0;
756  model[0] = 0;
757  time1[0] = 0;
758  time2[0] = 0;
759  time[0] = 0;
760  lon[0] = 0;
761  lat[0] = 0;
762  alt[0] = 0;
763 
764  // parse the message
765  res = parse_message( msg, event, callsign, passwd, model, lat, lon, alt, time1, time2 );
766  sprintf(debugstr,"[%d] %s:%d: msg: %s",mypid,clientip,clientport,msg);
767  debug(3,debugstr);
768 
769  pg_reconn_counter=0;
770 #ifdef NO_POSTGRESQL
771  write_message_log(msg,strlen(msg));
772 #else // !#ifdef NO_POSTGRESQL
773  while ( (PQstatus(conn) != CONNECTION_OK) && (no_of_line>2) ) /*line 1 =>ignore; line 2=REPLY/NOWAIT; line 3 and above=real stuff*/
774  {
775  sprintf(debugstr,"[%d] %s:%d: (Re)Connnet loop - %d",mypid,clientip,clientport,pg_reconn_counter);
776  debug(3,debugstr);
777  pg_reconn_counter++;
778  PQfinish(conn);
779  ConnectDB(&conn);
780  sleep(1);
781  if (PQstatus(conn)==CONNECTION_OK)
782  {
783  sprintf(debugstr,"[%d] %s:%d: (Re)Connected to PQ successful after %d tries",mypid,clientip,clientport,pg_reconn_counter);
784  debug(1,debugstr);
785  }
786  else
787  {
788  if (pg_reconn_counter%10==0)
789  {
790  sprintf(debugstr,"[%d] %s:%d: Reconnected to PQ failed after %d tries",mypid,clientip,clientport,pg_reconn_counter);
791  debug(1,debugstr);
792  }
793  if (pg_reconn_counter==120)
794  {
795  sprintf(debugstr,"[%d] %s:%d: Too much retries to PQ. Force Exit...",mypid,clientip,clientport);
796  debug(1,debugstr);
797  exit(0);
798  }
799  }
800  }
801 #endif // #ifdef NO_POSTGRESQL
802  pg_reconn_counter=0;
803 
804  sendok = 0; /* some messages require an 'OK' reply, if a 'REPLY' command was received*/
805 
806  switch (res)
807  {
808  case MT_NOWAIT: /*Introduced in fgms v0.10.22 */
809  reply = 1; /* Client want REPLY to each message*/
810  nowait = 1;/* Client will not wait ACK before sending another message*/
811  sprintf(debugstr,"[%d] %s:%d: NOWAIT mode is ON", mypid, clientip,clientport);
812  debug(1,debugstr);
813  break;
814  case MT_REPLY: /*fgms v0.10.21 and below*/
815  reply = 1; /*Client want REPLY to each message*/
816  sprintf(debugstr,"[%d] %s:%d: REPLY mode is ON", mypid, clientip,clientport);
817  debug(1,debugstr);
818  break;
819  case MT_UNKNOWN:
820  if (no_of_line!=1)
821  { /*first line from fgms will be ignored*/
822  sprintf(debugstr,"[%d] %s:%d: Unknown msg received", mypid, clientip,clientport);
823  debug(1,debugstr);
824  }
825  break;
826  case MT_PING:
827  if (SWRITE(fd,"PONG",5) != 5) {
828  sprintf(debugstr,"[%d] %s:%d: write PONG failed! - %s", mypid, clientip,clientport,strerror(errno));
829  debug(1,debugstr);
830  }
831  break;
832  case MT_PONG:
833  sprintf(debugstr,"[%d] %s:%d: PONG Received", mypid, clientip,clientport);
834  debug(1,debugstr);
835  break;
836  case MT_CONNECT:
837  sprintf(time,"%s %s Z",time1,time2);
838  if ((strncmp("mpdummy",callsign,7) != 0) && (strncmp("obscam",callsign,6) != 0))
839  logFlight(conn,callsign,model,time,1);
840  sendok = 1;
841  break;
842  case MT_DISCONNECT:
843  sprintf(time,"%s %s Z",time1,time2);
844  if ((strncmp("mpdummy",callsign,7) != 0) && (strncmp("obscam",callsign,6) != 0))
845  logFlight(conn,callsign,model,time,0);
846  sendok = 1;
847  break;
848  case MT_POSITION:
849  sprintf(time,"%s %s Z",time1,time2);
850  if (strncmp("mpdummy",callsign,7) != 0 && strncmp("obscam",callsign,6) != 0)
851  logPosition(conn,callsign,time,lon,lat,alt);
852  sendok = 1;
853  break;
854  default:
855  sprintf(debugstr,"[%d] %s:%d: Uncased message received!",mypid,clientip,clientport);
856  debug(1,debugstr);
857  sendok = 1; // not a valid message but server wating reply, so...
858  break;
859  }
860  if (sendok && reply) {
861  if (SWRITE(fd,"OK",3) != 3) {
862  sprintf(debugstr,"[%d] %s:%d: Write OK failed - %s", mypid, clientip,clientport,strerror(errno));
863  sprintf(debugstr,"[%d] %s:%d: Connection lost. Exiting...", mypid, clientip,clientport);
864  debug(1,debugstr);
865  exit(0);
866  } else {
867  sprintf(debugstr,"[%d] %s:%d: Reply sent.", mypid,clientip,clientport);
868  debug(3,debugstr);
869  }
870  }
871  if (!reply && no_of_line!=1)
872  { /*Force exit if the secord message does not flip reply switch*/
873  sprintf(debugstr,"[%d] %s:%d: Invalid message sequence. Exiting...",mypid,clientip,clientport);
874  debug(1,debugstr);
875  exit(0);
876  }
877  strcpy(msg,""); /*clear message*/
878  }
879  sprintf(debugstr,"[%d] %s:%d: Connection timeout after %d seconds. Exiting...", mypid, clientip,clientport,time_out_counter_u);
880  debug(1,debugstr);
881 }
882 
883 char *get_base_name(char *name)
884 {
885  char *bn = strdup(name);
886  size_t len = strlen(bn);
887  size_t i, off;
888  int c;
889  off = 0;
890  for (i = 0; i < len; i++) {
891  c = bn[i];
892  if (( c == '/' )||( c == '\\' ))
893  off = i + 1;
894  }
895  return &bn[off];
896 }
897 
898 void give_help(char *name)
899 {
900  char *bn = get_base_name(name);
901  printf("%s - version %s. Compiled at %s %s\n", bn, FGT_VERSION, __DATE__, __TIME__);
902 #ifndef NO_POSTGRESQL
903  printf("PostgreSQL Database Information\n");
904  printf(" --db database (-d) = Set the database name. (def=%s)\n",database);
905  printf(" --ip addr (-i) = Set the IP address of the postgresql server. (def=%s)\n",ip_address);
906  printf(" --port val (-p) = Set the port of the postgreql server. (def=%s)\n",port);
907  printf(" --user name (-u) = Set the user name. (def=%s)\n",user);
908  printf(" --word pwd (-w) = Set the password for the above user. (def=%s)\n",pwd);
909 #endif
910  printf("fgms connection\n");
911  printf(" --IP addr (-I) = Set IP address to connect to fgms. (def=IPADDR_ANY)\n");
912  printf(" --PORT val (-P) = Set PORT address to connect to fgms. (dep=%d)\n", server_port);
913  printf("General Options\n");
914  printf(" --help (-h. -?) = This help, and exit(0).\n");
915  printf(" --version (-v) = This help, and exit(0).\n");
916 #ifndef _MSC_VER
917  printf(" --DAEMON y|n (-D) = Run as daemon yes or no. (def=%s).\n", (run_as_daemon ? "y" : "n"));
918 #endif
919  printf(" %s will connect to an instance of 'fgms', receive flight and position messages.\n",bn);
920 #ifdef NO_POSTGRESQL
921  printf(" These will be written to a message log [%s].\n", msg_log );
922 #else
923  printf(" These will be stored in a PostgreSQL database, for later 'tracker' display.\n");
924 #endif
925 }
926 
927 int parse_commands( int argc, char **argv )
928 {
929  int i, i2;
930  char *arg;
931  char *sarg;
932 
933  for ( i = 1; i < argc; i++ ) {
934  i2 = i + 1;
935  arg = argv[i];
936  sarg = arg;
937  if ((strcmp(arg,"--help") == 0) || (strcmp(arg,"-h") == 0) ||
938  (strcmp(arg,"-?") == 0) || (strcmp(arg,"--version") == 0)||
939  (strcmp(arg,"-v") == 0)) {
940  give_help(argv[0]);
941  exit(0);
942  } else if (*sarg == '-') {
943  sarg++;
944  while (*sarg == '-') sarg++;
945  switch (*sarg)
946  {
947  case 'd':
948  if (i2 < argc) {
949  sarg = argv[i2];
950  database = strdup(sarg);
951  i++;
952  } else {
953  printf("database name must follow!\n");
954  goto Bad_ARG;
955  }
956  break;
957  case 'i':
958  if (i2 < argc) {
959  sarg = argv[i2];
960  ip_address = strdup(sarg);
961  i++;
962  } else {
963  printf("IP address must follow!\n");
964  goto Bad_ARG;
965  }
966  break;
967  case 'p':
968  if (i2 < argc) {
969  sarg = argv[i2];
970  port = strdup(sarg);
971  i++;
972  } else {
973  printf("port value must follow!\n");
974  goto Bad_ARG;
975  }
976  break;
977  case 'u':
978  if (i2 < argc) {
979  sarg = argv[i2];
980  user = strdup(sarg);
981  i++;
982  } else {
983  printf("user name must follow!\n");
984  goto Bad_ARG;
985  }
986  break;
987  case 'w':
988  if (i2 < argc) {
989  sarg = argv[i2];
990  pwd = strdup(sarg);
991  i++;
992  } else {
993  printf("password must follow!\n");
994  goto Bad_ARG;
995  }
996  break;
997  case 'I':
998  if (i2 < argc) {
999  sarg = argv[i2];
1000  server_addr = strdup(sarg);
1001  i++;
1002  } else {
1003  printf("fgms server IP address must follow!\n");
1004  goto Bad_ARG;
1005  }
1006  break;
1007  case 'P':
1008  if (i2 < argc) {
1009  sarg = argv[i2];
1010  server_port = atoi(sarg);
1011  i++;
1012  } else {
1013  printf("fgms server PORT value must follow!\n");
1014  goto Bad_ARG;
1015  }
1016  break;
1017 #ifndef _MSC_VER
1018  case 'D':
1019  if (i2 < argc) {
1020  sarg = argv[i2];
1021  if (strcmp(sarg,"y") == 0) {
1022  run_as_daemon = 1;
1023  } else if (strcmp(sarg,"n") == 0) {
1024  run_as_daemon = 0;
1025  } else {
1026  printf("Only 'y' or 'n' can follow -D!\n");
1027  goto Bad_ARG;
1028  }
1029  i++; // skip following argument
1030  } else {
1031  printf("either 'y' or 'n' must follow!\n");
1032  goto Bad_ARG;
1033  }
1034  break;
1035 #endif
1036  default:
1037  goto Bad_ARG;
1038  }
1039  } else {
1040 Bad_ARG:
1041  printf("ERROR: Unknown argument [%s]! Try -?\n",arg);
1042  exit(1);
1043  }
1044  }
1045  return 0;
1046 }
1047 
1048 #define PQ_EXEC_SUCCESS(res) ((PQresultStatus(res) == PGRES_COMMAND_OK)||(PQresultStatus(res) == PGRES_TUPLES_OK))
1049 int check_tables(PGconn *conn)
1050 {
1051 #ifdef NO_POSTGRESQL
1052  return 0;
1053 #else // !NO_POSTGRESQL
1054  PGresult *res;
1055  char buff[MAXLINE];
1056  char *cp = buff;
1057  char *val;
1058  int i, j, nFields, nRows;
1059  int got_flights = 0;
1060  int got_waypts = 0;
1061  if (PQstatus(conn) == CONNECTION_OK) {
1062  res = PQexec(conn,"BEGIN");
1063  if (PQresultStatus(res) != PGRES_COMMAND_OK) {
1064  PQclear(res);
1065  return 1;
1066  }
1067  /* should PQclear PGresult whenever it is no longer needed to avoid memory leaks */
1068  PQclear(res);
1069  strcpy(cp,"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';");
1070  res = PQexec(conn, cp);
1071  if (PQ_EXEC_SUCCESS(res)) {
1072  nFields = PQnfields(res);
1073  nRows = PQntuples(res);
1074  for (j = 0; j < nFields; j++) {
1075  for (i = 0; i < nRows; i++) {
1076  val = PQgetvalue(res, i, j);
1077  if (val) {
1078  if (strcmp(val,"flights") == 0)
1079  got_flights = 1;
1080  else if (strcmp(val,"waypoints") == 0)
1081  got_waypts = 1;
1082  }
1083  }
1084  }
1085  } else {
1086  return 1;
1087  }
1088  PQclear(res);
1089  /* end the transaction */
1090  res = PQexec(conn, "END");
1091  PQclear(res);
1092  } else {
1093  return 1;
1094  }
1095  return ((got_flights && got_waypts) ? 0 : 1);
1096 #endif // NO_POSTGRESQL y/n
1097 }
1098 
1100 {
1101  int iret = 1;
1102  PGconn *conn = NULL;
1103  if (ConnectDB(&conn)) {
1104  return 1; /* FAILED - conn closed */
1105  }
1106  iret = check_tables(conn);
1107  PQfinish(conn);
1108  return iret;
1109 }
1110 
1111 static void net_exit ( void )
1112 {
1113 #ifdef _MSC_VER
1114  /* Clean up windows networking */
1115  if ( WSACleanup() == SOCKET_ERROR ) {
1116  if ( WSAGetLastError() == WSAEINPROGRESS ) {
1117  WSACancelBlockingCall();
1118  WSACleanup();
1119  }
1120  }
1121 #endif
1122 }
1123 
1124 
1125 int net_init ()
1126 {
1127 #ifdef _MSC_VER
1128  /* Start up the windows networking */
1129  WORD version_wanted = MAKEWORD(1,1);
1130  WSADATA wsaData;
1131 
1132  if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
1133  printf("Couldn't initialize Winsock 1.1\n");
1134  return(1);
1135  }
1136 #endif
1137 
1138  atexit( net_exit ) ;
1139  return(0);
1140 }
1141 
1142 static pid_t pid,childpid;
1143 static int listenfd, connfd;
1144 
1145 #if defined(_MSC_VER) || defined(USE_PTHREAD)
1146 static pthread_t thread;
1147 void *func_child(void *vp)
1148 {
1149  static char debugstr2[MAXLINE];
1150 
1151  childpid=getpid();
1152 
1153  sprintf(debugstr2,"CLIENT[%5d] started",childpid);
1154  debug(2,debugstr2);
1155 
1156  doit(connfd);
1157 
1158  Close(connfd);
1159  sprintf(debugstr2,"CLIENT[%5d] stopped",childpid);
1160  debug(2,debugstr2);
1161 
1162  return ((void *)0xdead);
1163 }
1164 #endif // _MSC_VER || USE_PTHREAD
1165 
1166 int main (int argc, char **argv)
1167 {
1168  char debugstr[MAXLINE];
1169  struct sockaddr_in serveraddr,clientaddr;
1170  socklen_t clientaddrlen;
1171 
1172  parse_commands(argc,argv); /* parse user command line - no return if error */
1173 
1174  if (test_db_connection())
1175  {
1176  printf("PostgreSQL connection FAILED on [%s], port [%s], database [%s]. Aborting...\n",
1178  return 1;
1179  }
1180  printf("PostgreSQL connection test finished.\n");
1181 
1182  if ( net_init() ) {
1183  return 1;
1184  }
1185 
1186 #ifndef _MSC_VER
1187  openlog("fgtracker-server",LOG_PID,LOG_LOCAL1);
1188 #endif
1189 
1190  daemon_proc = 0;
1191 
1192  if (run_as_daemon)
1194 
1195  listenfd=Socket(AF_INET,SOCK_STREAM,0);
1196 
1197  bzero(&serveraddr,sizeof(serveraddr));
1198 
1199  serveraddr.sin_family = AF_INET;
1200  if (server_addr) {
1201  serveraddr.sin_addr.s_addr = inet_addr(server_addr);
1202  if (serveraddr.sin_addr.s_addr == INADDR_NONE) {
1203  struct hostent *hp = gethostbyname(server_addr);
1204  if (hp == NULL) {
1205  sprintf(debugstr,"FlightGear tracker unable to resolve address %s, reverting to INADDR_ANY!",server_addr);
1206  debug(1,debugstr);
1207  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
1208  server_addr = 0;
1209  } else {
1210  memcpy((char *)&serveraddr.sin_addr.s_addr, hp->h_addr, hp->h_length);
1211  }
1212  }
1213  } else {
1214  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
1215  }
1216 
1217  serveraddr.sin_port = htons(server_port);
1218 
1219  Bind(listenfd,(SA *)&serveraddr,sizeof(serveraddr));
1220 
1221  if (server_addr)
1222  sprintf(debugstr,"FlightGear tracker started listening on %s, port %d!",server_addr,server_port);
1223  else
1224  sprintf(debugstr,"FlightGear tracker started listening on INADDR_ANY, port %d!",server_port);
1225  debug(1,debugstr);
1226 
1227  Listen(listenfd,SERVER_LISTENQ);
1228 
1229 #ifndef _MSC_VER
1230  /*Installing signal handler*/
1231  signal(SIGCHLD, sigchld_handler);
1232  signal(SIGHUP, signal_handler);
1233  signal(SIGINT, signal_handler);
1234  signal(SIGQUIT, signal_handler);
1235  signal(SIGILL, signal_handler);
1236  signal(SIGTRAP, signal_handler);
1237  signal(SIGABRT, signal_handler);
1238  signal(SIGBUS, signal_handler);
1239  signal(SIGFPE, signal_handler);
1240  signal(SIGKILL, signal_handler);
1241  signal(SIGUSR1, signal_handler);
1242  signal(SIGSEGV, signal_handler);
1243  signal(SIGUSR2, signal_handler);
1244  signal(SIGPIPE, signal_handler);
1245  signal(SIGALRM, signal_handler);
1246  signal(SIGTERM, signal_handler);
1247  signal(SIGCONT, signal_handler);
1248  signal(SIGSTOP, signal_handler);
1249  signal(SIGTSTP, signal_handler);
1250 #endif // !_MSC_VER
1251 
1252  debug(1,"FlightGear tracker initialized. Waiting connection...");
1253  for ( ; ; )
1254  {
1255  clientaddrlen=sizeof(clientaddr);
1256 
1257  connfd=Accept(listenfd,(SA *) &clientaddr, &clientaddrlen);
1258 
1259 #if defined(_MSC_VER) || defined(USE_PTHREAD)
1260  // use a thread
1261  if (pthread_create( &thread, NULL, func_child, (void*)0 )) {
1262  debug(1,"ERROR: Failed to create child thread!");
1263  }
1264 #else // !_MSC_VER
1265  if ( (pid = Fork()) == 0 )
1266  { /* child */
1267  Close(listenfd);
1268 
1269  childpid=getpid();
1270 
1271  sprintf(debugstr,"CLIENT[%5d] started",childpid);
1272  debug(2,debugstr);
1273  doit(connfd);
1274  Close(connfd);
1275  sprintf(debugstr,"CLIENT[%5d] stopped",childpid);
1276  debug(2,debugstr);
1277  exit(0);
1278  }
1279  Close(connfd);
1280 #endif // _MSC_VER or USE_PTHREAD y/n
1281  }
1282 #ifndef _MSC_VER
1283  closelog();
1284 #endif // !_MSC_VER
1285 }
1286 
1287 /* eof - server.c */
int ConnectDB(PGconn **conn)
Definition: server.c:322
#define DEF_DATABASE
Definition: server.c:57
#define INADDR_NONE
Definition: netSocket.cxx:58
int main(int argc, char **argv)
Definition: server.c:1166
static char * database
Definition: server.c:70
void doit(int fd)
Definition: server.c:588
void give_help(char *name)
Definition: server.c:898
static char * server_addr
Definition: server.c:45
int check_tables(PGconn *conn)
Definition: server.c:1049
int Close(int sockfd)
Definition: wrappers.c:35
#define ISUPPER(a)
Definition: server.c:491
#define MSGMAXLINE
Definition: fg_common.hxx:180
#define DEF_USER_LOGIN
Definition: server.c:61
static char * pgtty
Definition: server.c:80
MsgType
Definition: server.c:468
int Fork()
Definition: wrappers.c:53
static void net_exit(void)
Definition: server.c:1111
#define MAXLINE
Definition: fg_common.hxx:179
#define PQ_EXEC_SUCCESS(res)
Definition: server.c:1048
static char * ip_address
Definition: server.c:68
char * get_base_name(char *name)
Definition: server.c:883
#define EatSpace
Definition: server.c:480
int test_db_connection()
Definition: server.c:1099
#define SWRITE
Definition: fgt_common.h:245
#define PORT_SCAN_SPEED
Definition: server.c:39
static int listenfd
Definition: server.c:1143
int logFlight(PGconn *conn, char *callsign, char *model, char *date, int connect)
Definition: server.c:387
int net_init()
Definition: server.c:1125
#define bzero(ptr, n)
Definition: fg_common.hxx:122
int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
Definition: wrappers.c:17
#define SERROR(a)
Definition: fgt_common.h:248
static int got_waypts
Definition: testdb.c:49
int Listen(int sockfd, int backlog)
Definition: wrappers.c:64
static int got_flights
Definition: testdb.c:48
#define SOCKET_ERROR
Definition: netSocket.h:80
#define SA
Definition: fg_common.hxx:190
static char * pwd
Definition: server.c:72
void SQL_Error(PGconn *conn)
Definition: server.c:361
int Bind(int sockfd, const struct sockaddr *serveraddr, socklen_t addrlen)
Definition: wrappers.c:26
#define DEF_PORT
Definition: server.c:53
#define FGT_VERSION
Definition: server.c:38
int logPosition(PGconn *conn, char *callsign, char *date, char *lon, char *lat, char *alt)
Definition: server.c:421
static char * port
Definition: server.c:69
#define DEF_IP_ADDRESS
Definition: server.c:49
static pid_t childpid
Definition: server.c:1142
#define Collect(a)
Definition: server.c:483
#define DEF_USER_PWD
Definition: server.c:65
void signal_handler(int s)
Signal handling.
Definition: server.c:143
static pid_t pid
Definition: server.c:1142
void sigchld_handler(int s)
Definition: server.c:129
static char * user
Definition: server.c:71
#define SERVER_LISTENQ
Definition: fgt_config.h:46
int daemon_proc
Definition: fgt_error.c:24
static uint32_t server_port
Definition: server.c:44
int parse_commands(int argc, char **argv)
Definition: server.c:927
void debug(int level, char *str)
Definition: fgt_error.c:196
#define SERVER_PORT
Definition: fgt_config.h:42
int parse_message(char *msg, char *event, char *callsign, char *passwd, char *model, char *lat, char *lon, char *alt, char *time1, char *time2)
Definition: server.c:493
int daemon_init(void)
Definition: server.c:107
int Socket(int family, int type, int protocol)
Definition: wrappers.c:73
static int run_as_daemon
Definition: server.c:42
static char * pgoptions
Definition: server.c:79
#define SREAD
Definition: fgt_common.h:246
static int connfd
Definition: server.c:1143