8

Log service : server

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <errno.h>
  9. #include <string.h>
  10.  
  11. #include <signal.h>
  12.  
  13. #include <unistd.h>
  14.  
  15. #include <time.h>
  16.  
  17. #include "debug.h"
  18.  
  19. #if defined( DEBUG )
  20. int debug = 0;
  21. #endif
  22.  
  23. #define LOGFILE     "log.txt"
  24. #define PORTNUM     10123
  25. #define MAXCONN     32
  26. #define LINESIZE    1024
  27.  
  28. struct {
  29.     char *log_file;
  30.     int port_num;
  31.     int socket;
  32.     struct {
  33.         int sock;
  34.         FILE *fin;
  35.         char *ip;
  36.     } in_sockets[MAXCONN];
  37.     FILE *flog;
  38. } app;
  39.  
  40. static char *timestamp() {
  41.     time_t now = time( 0 );
  42.     struct tm *tm = localtime( &now );
  43.  
  44.     static char s[18]; /* dd/mm/yy hh:mm:ss */
  45.  
  46.     sprintf( s, "%02d/%02d/%02d %02d:%02d:%02d", tm->tm_mday, tm->tm_mon, tm->tm_year - 100,
  47.             tm->tm_hour, tm->tm_min, tm->tm_sec );
  48.  
  49.     return s;
  50. }
  51.  
  52. void open_log() {
  53.     FILE *fp;
  54.  
  55.     ONDEBUG9( fputs( "\n[open_socket]\n", stdout ); );
  56.  
  57.     if ( app.flog == 0 ) {
  58.         if ( (fp = fopen( app.log_file, "a" )) == 0 )
  59.             goto error;
  60.  
  61.         app.flog = fp;
  62.  
  63.         if ( fprintf( app.flog, "%s START\n", timestamp() ) == EOF )
  64.             goto error;
  65.     }
  66.     return;
  67.  
  68. error:
  69.  
  70.     perror( 0 );
  71.     exit( 1 );
  72. }
  73.  
  74. void close_log() {
  75.     ONDEBUG9( fputs( "\n[close_log]\n", stdout ); );
  76.  
  77.     if ( app.flog != 0 ) {
  78.         if ( fprintf( app.flog, "%s STOP\n", timestamp() ) == EOF )
  79.             goto error;
  80.  
  81.         fclose( app.flog );
  82.  
  83.         app.flog = 0;
  84.     }
  85.     return;
  86.  
  87. error:
  88.  
  89.     perror( 0 );
  90.     exit( 1 );
  91. }
  92.  
  93. void open_socket() {
  94.     int sd = -1;
  95.     struct sockaddr_in sd_address;
  96.     socklen_t addrlen = sizeof( struct sockaddr_in );
  97.  
  98.     int sockoptval, sockoptlen;
  99.  
  100.     ONDEBUG9( fputs( "\n[open_socket]\n", stdout ); );
  101.  
  102.     if ( (sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )) == -1 )
  103.         goto error;
  104.  
  105.     sockoptval = 1; /* on */
  106.     sockoptlen = sizeof ( sockoptval );
  107.     if ( setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sockoptlen ) < 0 )
  108.         goto error;
  109.  
  110.     sd_address.sin_family = AF_INET;
  111.     sd_address.sin_addr.s_addr = htonl( INADDR_ANY );
  112.     sd_address.sin_port = htons( app.port_num );
  113.  
  114.     if ( bind( sd, (struct sockaddr *)&sd_address, addrlen ) != 0 )
  115.         goto error;
  116.  
  117.     if ( listen( sd, 5 ) != 0)
  118.         goto error;
  119.  
  120.     app.socket = sd;
  121.  
  122.     return;
  123.  
  124. error:
  125.  
  126.     perror( 0 );
  127.     if ( sd != -1 )
  128.         close( sd );
  129.     exit( 1 );
  130. }
  131.  
  132. void close_socket( void ) {
  133.     ONDEBUG9( fputs( "\n[close_socket]\n", stdout ); );
  134.  
  135.     if ( app.socket != -1 ) {
  136.         close( app.socket );
  137.         app.socket = -1;
  138.     }
  139. }
  140.  
  141. void drop_conn( int socket ) {
  142.     int i;
  143.  
  144.     ONDEBUG9( fputs( "\n[drop_conn]\n", stdout ); );
  145.  
  146.     ONDEBUG2 ( fprintf( stdout, "-%d-\n", socket ); );
  147.  
  148.     for ( i = 0; i < MAXCONN; ++i ) {
  149.         if ( app.in_sockets[ i ].sock == socket ) {
  150.             fclose( app.in_sockets[ i ].fin );
  151.             app.in_sockets[ i ].sock = -1;
  152.             app.in_sockets[ i ].fin = 0;
  153.             free( app.in_sockets[ i ].ip );
  154.             return;
  155.         }
  156.     }
  157. }
  158.  
  159. void accept_conn( int socket ) {
  160.     int sd = -1;
  161.  
  162.     struct sockaddr_in sd_address;
  163.     unsigned addrlen = sizeof( struct sockaddr_in );
  164.  
  165.     int i;
  166.  
  167.     ONDEBUG9( fputs( "\n[accept_conn]\n", stdout ); );
  168.  
  169.     sd = accept( socket, (struct sockaddr *)&sd_address, &addrlen );
  170.     if ( sd == -1 )
  171.         goto error;
  172.  
  173.     for ( i = 0; i < MAXCONN; ++i ) {
  174.         if ( app.in_sockets[ i ].sock == -1 ) {
  175.             FILE *fin = fdopen( sd, "r" );
  176.             if ( fin == 0 )
  177.                 goto error;
  178.             app.in_sockets[ i ].sock = sd;
  179.             app.in_sockets[ i ].fin = fin;
  180.             app.in_sockets[ i ].ip = strdup( inet_ntoa( sd_address.sin_addr ));
  181.             return;
  182.         }
  183.     }
  184.  
  185.     close( sd );
  186.  
  187.     return;
  188.  
  189. error:
  190.  
  191.     perror( 0 );
  192.     if ( sd != -1 )
  193.         close( sd );
  194. }
  195.  
  196. void close_all_conns( void ) {
  197.     int i;
  198.  
  199.     ONDEBUG9( fputs( "\n[close_all_conns]\n",stdout ); );
  200.  
  201.     for ( i = 0; i < MAXCONN; ++i ) {
  202.         if ( app.in_sockets[ i ].sock != -1 ) {
  203.             fclose( app.in_sockets[ i ].fin );
  204.             app.in_sockets[ i ].sock = -1;
  205.             app.in_sockets[ i ].fin = 0;
  206.             free( app.in_sockets[ i ].ip );
  207.         }
  208.     }
  209. }
  210.  
  211. void log_stream( int socket, FILE *fin, char *ip ) {
  212.     char sline[ LINESIZE ];
  213.  
  214.     ONDEBUG9( fputs( "\n[log_stream]\n", stdout ); );
  215.  
  216.     if ( fgets( sline, sizeof( sline ), fin ) == 0 ) {
  217.         drop_conn( socket );
  218.         return;
  219.     }
  220.  
  221.     ONDEBUG2 ( fprintf( stdout, "<%d>%d (%d)\n", socket, strlen( sline ), sline[ strlen( sline )-1 ] ); );
  222.  
  223.     if ( sline[ 0 ] != 'L' || sline[ 1 ] != 'O' || sline[ 2 ] != 'G' || sline[ 3 ] != ' ' || sline[ strlen( sline )-1 ] != '\n' ) {
  224.         if ( fprintf( app.flog, "BADMSG %s %s\n", timestamp(), ip ) == EOF )
  225.             goto error;
  226.         drop_conn( socket );
  227.     }
  228.     else {
  229.         if ( fprintf( app.flog, "LOG %s %s", timestamp(), ip ) == EOF )
  230.             goto error;
  231.  
  232.         if ( fputs( sline+3, app.flog ) == EOF )
  233.             goto error;
  234.     }
  235.  
  236.     fflush( app.flog );
  237.  
  238.     return;
  239.  
  240. error:
  241.  
  242.     perror( 0 );
  243.     exit( 1 );
  244. }
  245.  
  246. void quit( int status ) {
  247.     ONDEBUG9( fputs( "\n[quit]\n", stdout ); );
  248.  
  249.     close_log();
  250.     close_socket();
  251.     close_all_conns();
  252.  
  253.     exit( status );
  254. }
  255.  
  256. void intr( int sig ) {
  257.     ONDEBUG9( fputs( "\n[intr]\n", stdout ); );
  258.     ONDEBUG8( fprintf( stdout, "<sig=%d>\n", sig); );
  259.  
  260.     if ( sig == SIGTERM )
  261.         quit( 0 );
  262.     signal( sig, intr ); /* catch again */
  263. }
  264.  
  265. void init( void ) {
  266.     int i;
  267.  
  268.     ONDEBUG9( fputs( "\n[init]\n", stdout ); );
  269.  
  270.     app.log_file = LOGFILE;
  271.     app.port_num = PORTNUM;
  272.     app.socket = -1;
  273.  
  274.     for ( i = 0; i < MAXCONN; ++i )
  275.         app.in_sockets[ i ].sock = -1;
  276. }
  277.  
  278. void startup( ) {
  279.     ONDEBUG9( fputs( "\n[startup]\n", stdout ); );
  280.  
  281.     open_log();
  282.     open_socket();
  283.  
  284.     signal( SIGHUP, intr );
  285. #if !defined( DEBUG )
  286.     signal( SIGINT, intr );
  287. #endif
  288.     signal( SIGTERM, intr );
  289. }
  290.  
  291. void main_loop( ) {
  292.     fd_set read_fds;
  293.     int n_fds = FD_SETSIZE;
  294.  
  295.     int sd, i;
  296.  
  297.     ONDEBUG9( fputs( "\n[main_loop]\n", stdout ); );
  298.  
  299.     for (;; ) { /* forever */
  300.         FD_ZERO( &read_fds );
  301.  
  302.         if ( app.socket != -1 )
  303.             FD_SET( app.socket, &read_fds );
  304.  
  305.         for ( i = 0; i < MAXCONN; ++i ) {
  306.             sd = app.in_sockets[ i ].sock;
  307.             if ( sd != -1 )
  308.                 FD_SET( sd, &read_fds );
  309.         }
  310.  
  311.         switch ( select( n_fds, &read_fds, 0, 0, 0 )) {
  312.         case -1: /* trouble */
  313.             ONDEBUG8( fprintf( stdout, "<errno=%d>\n", errno) );
  314.             if ( errno != EINTR ) {
  315.                 perror( 0 );
  316.                 quit( 1 );
  317.             }
  318.             break;
  319.         case 0: /* time out */
  320.             break;
  321.         default: /* event */
  322.  
  323.             /* connect? */
  324.             if ( app.socket != -1 && FD_ISSET( app.socket, &read_fds ))
  325.                 accept_conn( app.socket );
  326.  
  327.             /* data? */
  328.             for ( i = 0; i < MAXCONN; ++i ) {
  329.                 sd = app.in_sockets[ i ].sock;
  330.                 if ( sd != -1 && FD_ISSET( sd, &read_fds ))
  331.                     log_stream( sd, app.in_sockets[ i ].fin, app.in_sockets[ i ].ip );
  332.             }
  333.             break;
  334.         }
  335.     }
  336. }
  337.  
  338. int main( int argc, char **argv ) {
  339.     extern int opterr;
  340.     int c;
  341.  
  342.     init();
  343.  
  344.     opterr = 0;
  345.  
  346. #if defined( DEBUG )
  347.     while ( (c = getopt( argc, argv, "D:p:" )) != -1 )
  348. #else
  349.     while ( (c = getopt( argc, argv, "p:" )) != -1 )
  350. #endif
  351.     switch ( c ) {
  352. #if defined( DEBUG )
  353.     case 'D':
  354.         debug = atoi( optarg );
  355.         break;
  356. #endif
  357.     case 'p':
  358.         if ((app.port_num = atoi( optarg )) == 0) {
  359.             fputs( "portnum?\n", stderr );
  360.             exit( 1 );
  361.         }
  362.         break;
  363.     default:
  364.  
  365. usage:
  366. #if defined( DEBUG )
  367.         fprintf( stderr, "%s [-D level] [-p port_num] [log_file]\n", argv[ 0 ] );
  368. #else
  369.         fprintf( stderr, "%s [-p port_num] [log_file]\n", argv[ 0 ] );
  370. #endif
  371.         exit( 1 );
  372.     }
  373.  
  374.     switch ( argc - optind ) {
  375.     case 0:
  376.         break;
  377.     case 1:
  378.         app.log_file = argv[ optind ];
  379.         break;
  380.     default:
  381.         goto usage;
  382.     }
  383.  
  384.     setbuf( stdout, 0 );
  385.  
  386.     startup();
  387.     main_loop();
  388. }

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].