|
@@ -1,10 +1,28 @@
|
1
|
1
|
#include "monitor.h"
|
2
|
2
|
|
|
3
|
+static pyfcgi_monitor_t pyfcgi_mon;
|
|
4
|
+
|
|
5
|
+static void clean_exit(int status)
|
|
6
|
+{
|
|
7
|
+ if(pyfcgi_mon.sockserv)
|
|
8
|
+ {
|
|
9
|
+ close(pyfcgi_mon.sockserv);
|
|
10
|
+ }
|
|
11
|
+ exit(status);
|
|
12
|
+}
|
3
|
13
|
|
4
|
14
|
pid_t pyfcgi_spawn_monitor()
|
5
|
15
|
{
|
6
|
16
|
pid_t res;
|
7
|
17
|
|
|
18
|
+ if(!PyFCGI_conf.mon_socket)
|
|
19
|
+ {
|
|
20
|
+ pyfcgi_log(LOG_ERR, "No socket url set but pyfcgi_spawn_monitor called !");
|
|
21
|
+ return -1;
|
|
22
|
+ }
|
|
23
|
+
|
|
24
|
+ memset(&pyfcgi_mon, 0, sizeof(pyfcgi_mon));
|
|
25
|
+
|
8
|
26
|
res = fork();
|
9
|
27
|
if(res == -1)
|
10
|
28
|
{
|
|
@@ -13,24 +31,119 @@ pid_t pyfcgi_spawn_monitor()
|
13
|
31
|
sleep(1);
|
14
|
32
|
}
|
15
|
33
|
if(!res)
|
16
|
|
- {
|
|
34
|
+ { //child process
|
17
|
35
|
pyfcgi_logger_set_ident("StatServ");
|
18
|
|
- pyfcgi_monitor_init();
|
19
|
36
|
pyfcgi_monitor_loop();
|
20
|
37
|
pyfcgi_log(LOG_ALERT, "Monitor loop should never return but just did it...");
|
21
|
|
- exit(PYFCGI_FATAL);
|
|
38
|
+ clean_exit(PYFCGI_FATAL);
|
22
|
39
|
}
|
23
|
40
|
return res;
|
24
|
41
|
}
|
25
|
42
|
|
26
|
|
-void pyfcgi_monitor_init()
|
|
43
|
+
|
|
44
|
+void pyfcgi_monitor_loop()
|
27
|
45
|
{
|
|
46
|
+ pyfcgi_monitor_addr_t addr;
|
|
47
|
+ int *sockargs;
|
|
48
|
+ socklen_t addrlen;
|
28
|
49
|
|
|
50
|
+ sockargs = pyfcgi_mon.sockargs;
|
|
51
|
+
|
|
52
|
+ if(pyfcgi_monitor_parse_sock(PyFCGI_conf.mon_socket, sockargs,
|
|
53
|
+ &addr) < 0)
|
|
54
|
+ {
|
|
55
|
+ pyfcgi_log(LOG_WARNING,
|
|
56
|
+ "Unable to parse socket URL, monitoring server not starting...");
|
|
57
|
+ free(PyFCGI_conf.mon_socket);
|
|
58
|
+ PyFCGI_conf.mon_socket = NULL;
|
|
59
|
+ clean_exit(PYFCGI_ERR);
|
|
60
|
+ }
|
|
61
|
+
|
|
62
|
+ if( (pyfcgi_mon.sockserv = socket(sockargs[0], sockargs[1],
|
|
63
|
+ sockargs[2])) < 0)
|
|
64
|
+ {
|
|
65
|
+ pyfcgi_log(LOG_ERR, "Unable to create socket : %s",
|
|
66
|
+ strerror(errno));
|
|
67
|
+ sleep(1);
|
|
68
|
+ clean_exit(PYFCGI_ERR);
|
|
69
|
+ }
|
|
70
|
+
|
|
71
|
+ if(sockargs[0] == AF_INET)
|
|
72
|
+ {
|
|
73
|
+ addrlen = sizeof(struct sockaddr_in);
|
|
74
|
+ }
|
|
75
|
+ else if(sockargs[0] == AF_INET6)
|
|
76
|
+ {
|
|
77
|
+ addrlen = sizeof(struct sockaddr_in6);
|
|
78
|
+ }
|
|
79
|
+ else
|
|
80
|
+ {
|
|
81
|
+ addrlen = sizeof(struct sockaddr_un);
|
|
82
|
+ }
|
|
83
|
+
|
|
84
|
+ if(bind(pyfcgi_mon.sockserv, (struct sockaddr*)&addr, addrlen) < 0)
|
|
85
|
+ {
|
|
86
|
+ pyfcgi_log(LOG_ERR, "Unable to bind socket... Retrying in 10s");
|
|
87
|
+ close(pyfcgi_mon.sockserv);
|
|
88
|
+ sleep(30);
|
|
89
|
+ clean_exit(PYFCGI_ERR);
|
|
90
|
+ }
|
|
91
|
+ pyfcgi_log(LOG_INFO, "Listening on %s", PyFCGI_conf.mon_socket);
|
|
92
|
+ //bind successfull, sending to appropriate response loop
|
|
93
|
+ if(pyfcgi_mon.sockargs[1] == SOCK_DGRAM)
|
|
94
|
+ {
|
|
95
|
+ pyfcgi_monitor_dgram_loop();
|
|
96
|
+ }
|
|
97
|
+ else
|
|
98
|
+ {
|
|
99
|
+ pyfcgi_monitor_stream_loop();
|
|
100
|
+ }
|
29
|
101
|
}
|
30
|
102
|
|
31
|
|
-void pyfcgi_monitor_loop()
|
|
103
|
+void pyfcgi_monitor_stream_loop(pyfcgi_monitor_addr_t addr_serv)
|
32
|
104
|
{
|
|
105
|
+ pyfcgi_monitor_addr_t cliaddr;
|
|
106
|
+ socklen_t addrlen;
|
|
107
|
+ int sockcli;
|
|
108
|
+ char ipstr[64];
|
|
109
|
+ char name[] = "PYFCGI_"VERSION"\n";
|
33
|
110
|
|
|
111
|
+ addrlen = sizeof(cliaddr);
|
|
112
|
+ if(listen(pyfcgi_mon.sockserv, PYFCGI_MONITOR_STREAM_BACKLOG) < 0)
|
|
113
|
+ {
|
|
114
|
+ pyfcgi_log(LOG_ERR, "Unable to listen on socket : %s",
|
|
115
|
+ strerror(errno));
|
|
116
|
+ clean_exit(PYFCGI_ERR);
|
|
117
|
+ }
|
|
118
|
+
|
|
119
|
+ while( (sockcli = accept(pyfcgi_mon.sockserv,
|
|
120
|
+ (struct sockaddr*)&cliaddr, &addrlen)) >= 0)
|
|
121
|
+ {
|
|
122
|
+ pyfcgi_log(LOG_DEBUG, "New client");
|
|
123
|
+ if(!inet_ntop(pyfcgi_mon.sockargs[0], (void*)&cliaddr, ipstr, 64))
|
|
124
|
+ {
|
|
125
|
+ pyfcgi_log(LOG_WARNING,
|
|
126
|
+ "inet_ntop fails to represent client address : %s",
|
|
127
|
+ strerror(errno));
|
|
128
|
+ strcpy(ipstr, "XXX");
|
|
129
|
+ }
|
|
130
|
+ pyfcgi_log(LOG_INFO, "Sending stats to %s", ipstr);
|
|
131
|
+
|
|
132
|
+ send(sockcli, name, strlen(name), 0);
|
|
133
|
+ close(sockcli);
|
|
134
|
+
|
|
135
|
+ addrlen = sizeof(cliaddr);
|
|
136
|
+ }
|
|
137
|
+ pyfcgi_log(LOG_ERR, "Unable to accept new connection on socket : %s",
|
|
138
|
+ strerror(errno));
|
|
139
|
+}
|
|
140
|
+
|
|
141
|
+void pyfcgi_monitor_dgram_loop()
|
|
142
|
+{
|
|
143
|
+ pyfcgi_log(LOG_ERR, "Dgram server not implemented.... exiting server");
|
|
144
|
+ free(PyFCGI_conf.mon_socket);
|
|
145
|
+ PyFCGI_conf.mon_socket = NULL;
|
|
146
|
+ clean_exit(PYFCGI_ERR);
|
34
|
147
|
}
|
35
|
148
|
|
36
|
149
|
int pyfcgi_monitor_check_sock(const char* sockurl)
|
|
@@ -141,10 +254,9 @@ int pyfcgi_monitor_parse_sock(const char *sockurl, int sockargs[3],
|
141
|
254
|
int pyfcgi_monitor_parse_inet_addr(const char* addr_str, int socktype,
|
142
|
255
|
pyfcgi_monitor_addr_t *listen_addr, int* domain)
|
143
|
256
|
{
|
144
|
|
- char *addr, *port, *ptr, *ipstr;
|
145
|
|
- char v6str[64];
|
|
257
|
+ char *addr, *port, *ptr, ipstr[64];
|
146
|
258
|
struct addrinfo *infos, hints, *info;
|
147
|
|
- short v4, v6, i;
|
|
259
|
+ short v4, v6;
|
148
|
260
|
int ret;
|
149
|
261
|
|
150
|
262
|
// initialize temporary address & port pointers
|
|
@@ -186,26 +298,23 @@ int pyfcgi_monitor_parse_inet_addr(const char* addr_str, int socktype,
|
186
|
298
|
{
|
187
|
299
|
memcpy(&listen_addr->in, info->ai_addr,
|
188
|
300
|
info->ai_addrlen);
|
189
|
|
- ipstr = inet_ntoa(listen_addr->in.sin_addr);
|
190
|
301
|
}
|
191
|
302
|
else if(info->ai_family == AF_INET6)
|
192
|
303
|
{
|
193
|
304
|
memcpy(&listen_addr->in6, info->ai_addr,
|
194
|
305
|
info->ai_addrlen);
|
195
|
|
- ptr = v6str;
|
196
|
|
- for(i=0; i<16; i++)
|
197
|
|
- {
|
198
|
|
- ptr += snprintf(ptr, 4,
|
199
|
|
- "%s%02X", ((i==0)?"":":"),
|
200
|
|
- listen_addr->in6.sin6_addr.s6_addr[i]);
|
201
|
|
- }
|
202
|
|
- ipstr = v6str;
|
203
|
306
|
}
|
204
|
307
|
else
|
205
|
308
|
{
|
206
|
309
|
continue;
|
207
|
310
|
}
|
208
|
311
|
*domain = info->ai_family;
|
|
312
|
+ if(!inet_ntop(*domain, info->ai_addr, ipstr, 64))
|
|
313
|
+ {
|
|
314
|
+ pyfcgi_log(LOG_ERR, "Unable to format IP in string : %s",
|
|
315
|
+ strerror(errno));
|
|
316
|
+ strcpy(ipstr, "IP");
|
|
317
|
+ }
|
209
|
318
|
pyfcgi_log(LOG_DEBUG, "Listen addr resolved to %s(%s)",
|
210
|
319
|
info->ai_canonname, ipstr);
|
211
|
320
|
|