Initial revision
[remotetop.git] / topd.c
1 /*
2  * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *      notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *      notice, this list of conditions and the following disclaimer in the
12  *      documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the author nor the names of any co-contributors
14  *      may be used to endorse or promote products derived from this software
15  *      without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #include <errno.h>
35 #include <sys/sysctl.h>
36
37 #include "tlog.h"
38 #include "connection.h"
39 #include "top.h"
40 #include "tmalloc.h"
41
42 TCServer cfg;
43 static int continueWork=1;
44
45 static void
46 inquireExit(int s) {
47         continueWork=0;
48 }
49                                 
50 extern char *optarg;
51 extern int optind;
52
53 int
54 main( int argc, char *argv[] ) {
55         int ch;
56         int child=0, listenport = TOPD_SERVER_DEFAULT_PORT;
57         int n=1024;
58         char *host="127.0.0.1";
59
60         memset( &cfg, 0, sizeof(TCServer) );
61
62         while( (ch=getopt(argc, argv, "h:p:c:s:D"))!=-1) {
63                 switch(ch) {
64                         case 'D':
65                                 cfg.debug=1;
66                                 break;
67                         case 'h':
68                                 host=strdup(optarg);
69                                 break;
70                         case 'p':
71                                 listenport=atoi(optarg);
72                                 break;
73                         case 'n':
74                                 n=atoi(optarg);
75                                 break;
76                         default:
77                                 return 1;
78                 }
79         }
80
81         signal(SIGCHLD, SIG_IGN);
82
83         if ( cfg.debug )
84                 opentlog( TL_OPEN_STDERR,  TL_DEBUG, NULL);
85         else
86                 opentlog( TL_OPEN_SYSLOG, TL_INFO, NULL);
87
88         if ( cfg.debug || (child = fork()) == 0 ) {
89                 /* child */
90                 if ( cfg.debug || (child = fork()) == 0 ) {
91                         /*child*/
92                         TC_Connection *newconn;
93                         int i;
94
95                         signal(SIGINT, inquireExit);
96                         signal(SIGHUP, inquireExit);
97
98                         if ( n <= 0 )
99                                 n=1024;
100
101                         cfg.mu = allocUnits(n);
102
103                         TC_addConnection( &cfg.pool, TC_fillConnection(NULL, NULL, listenport) );
104                         TC_ClientInitConnection( cfg.pool.conn[0], NULL, listenport);
105                         cfg.pool.conn[0]->state = CS_READ;
106
107                         TC_addConnection( &cfg.pool, TC_fillConnection(NULL, NULL, listenport) );
108                         cfg.pool.conn[1]->fd = TC_AcceptUdp( host, listenport );
109                         cfg.pool.conn[1]->state = CS_READ; 
110
111                         while(continueWork) {
112                                 if ( TC_ReadyIO(cfg.pool.conn, cfg.pool.number, 100 ) ) {
113                                         if ( cfg.pool.conn[1]->readyio ) 
114                                                 gotMsg( cfg.pool.conn[1] );
115                                         else 
116                                                 tlog(TL_DEBUG,"Ready connection...");
117                                 }
118                                 ConnectionWorks();
119                                 if ( cfg.pool.conn[0]->readyio && (newconn=TC_AcceptTcp( cfg.pool.conn[0] )) != NULL ) {
120                                         if ( newconn->state == CS_CONNECTED ) {
121                                                 tlog(TL_DEBUG,"Accept new connection...");
122                                                 newconn->state = CS_READ;
123                                                 TC_addConnection( &cfg.pool, newconn );
124                                         }
125                                 }
126                         }
127                         TC_deleteConnectionByN(&cfg.pool, 0);
128                         close( cfg.pool.conn[1]->fd );
129                         for(i=TC_SERVER_CONN_START; i<cfg.pool.number; i++) 
130                                 TC_deleteConnectionByN(&cfg.pool,i);
131                 }
132         }
133         if (child == -1) 
134                 tlog(TL_CRIT,"Can't start child process");
135
136         return 0;
137 }
138