ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/ihost/ihost.c
Revision: 1.9
Committed: Fri May 17 11:21:17 2002 UTC (22 years ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.8: +132 -20 lines
Log Message:
Now basic working version. Only tested on solaris.

File Contents

# Content
1 #include <stdio.h>
2 #include <sys/socket.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <syslog.h>
6 #include <netinet/in.h>
7 #include "ukcprog.h"
8 #include <netdb.h>
9 #include <strings.h>
10 #include "statgrab.h"
11
12 #define RECONFIGURE_RETURN_CODE 2
13 #define UDP_MAX_PACKET_SIZE 8192
14
15 typedef struct{
16 int fm_port;
17 char *fm_host;
18
19 char *my_fqdn;
20 char *server_fqdn;
21 int server_udp_port;
22 int server_tcp_port;
23 char *last_modified;
24 char *files_list;
25 char *key;
26 int udp_update_time;
27 int tcp_update_time;
28
29 }ihost_state_t;
30
31 char* sock_comm(FILE *f_r, FILE *f_w, char *sendString){
32 char *reply;
33 fprintf(f_w, "%s\n", sendString);
34 fflush(f_w);
35 reply=fpgetline(f_r);
36 /* Returns pointer to static buffer */
37 return reply;
38 }
39
40 int ihost_configure(ihost_state_t *ihost_state){
41 struct sockaddr_in addr;
42 struct in_addr haddr;
43 int sd;
44 FILE *fm_fd_r, *fm_fd_w;
45 char *reply;
46 char *reply_ptr;
47
48 /* Check to see if anything needs to be free'd */
49 if (ihost_state->my_fqdn!=NULL) free(ihost_state->my_fqdn);
50 if (ihost_state->server_fqdn!=NULL) free(ihost_state->server_fqdn);
51 if (ihost_state->last_modified!=NULL) free(ihost_state->last_modified);
52 if (ihost_state->files_list!=NULL) free(ihost_state->files_list);
53
54 if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
55 errf("Can't create AF_INET socket (%m)");
56 return -1;
57 }
58
59 if (get_host_addr(ihost_state->fm_host, &haddr) != 0){
60 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
61 return -1;
62 }
63
64 memset(&addr, 0, sizeof addr);
65 addr.sin_family = AF_INET;
66 memcpy(&addr.sin_addr, &haddr, sizeof haddr);
67 addr.sin_port = htons(ihost_state->fm_port);
68
69 if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) {
70 errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port);
71 return -1;
72 }
73
74 /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */
75 if ((fm_fd_r=fdopen(sd,"r")) == NULL){
76 errf("Failed to open read stream (%m)");
77 return -1;
78 }
79
80 if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){
81 errf("Failed to open write stream (%m)");
82 return -1;
83 }
84
85 reply=sock_comm(fm_fd_r, fm_fd_w, "STARTCONFIG");
86 if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) {
87 errf("Server error");
88 return -1;
89 }
90
91 reply=sock_comm(fm_fd_r, fm_fd_w, "LASTMODIFIED");
92 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){
93 errf("Server error (%m)");
94 return -1;
95 }
96 if((ihost_state->last_modified=strdup(reply)) == NULL){
97 errf("strdup failed (%m)");
98 return -1;
99 }
100
101 reply=sock_comm(fm_fd_r, fm_fd_w, "FILELIST");
102 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0)){
103 errf("Server error (%m)");
104 return -1;
105 }
106 if((ihost_state->files_list=strdup(reply)) == NULL){
107 errf("strdup failed (%m)");
108 return -1;
109 }
110
111 reply=sock_comm(fm_fd_r, fm_fd_w, "FQDN");
112 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){
113 errf("Server error (%m)");
114 return -1;
115 }
116 if((ihost_state->my_fqdn=strdup(reply)) == NULL){
117 errf("strdup failed (%m)");
118 return -1;
119 }
120
121 reply=sock_comm(fm_fd_r, fm_fd_w, "UDPUpdateTime");
122 if(reply== NULL){
123 errf("Server error (%m)");
124 return -1;
125 }
126 if (strncasecmp(reply, "ERROR", 5) != 0){
127 ihost_state->udp_update_time=atoi(reply);
128 }
129
130 reply=sock_comm(fm_fd_r, fm_fd_w, "TCPUpdateTime");
131 if(reply== NULL){
132 errf("Server error (%m)");
133 return -1;
134 }
135 if (strncasecmp(reply, "ERROR", 5) != 0){
136 ihost_state->tcp_update_time=atoi(reply);
137 }
138
139 reply=sock_comm(fm_fd_r, fm_fd_w, "ENDCONFIG");
140 if(reply== NULL){
141 errf("Server error (%m)");
142 return -1;
143 }
144
145 reply=sock_comm(fm_fd_r, fm_fd_w, "FILTER");
146 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5)==0)){
147 errf("Server error FILTER failed (%m)");
148 return -1;
149 }
150 reply_ptr=strchr(reply,';');
151 if (reply_ptr==NULL){
152 errf("Incorrect data returned");
153 return -1;
154 }
155 *reply_ptr='\0';
156 if((ihost_state->server_fqdn=strdup(reply)) == NULL){
157 errf("strdup failed (%m)");
158 return -1;
159 }
160 reply=reply_ptr + 1;
161 reply_ptr=strchr(reply,';');
162 if (reply_ptr==NULL){
163 errf("Incorrect data returned 2");
164 return -1;
165 }
166 *reply_ptr='\0';
167 ihost_state->server_udp_port=atoi(reply);
168 reply=reply_ptr+1;
169 ihost_state->server_tcp_port=atoi(reply);
170 if ((ihost_state->server_tcp_port==0) || (ihost_state->server_udp_port==0)){
171 errf("Incorrect data returned 3 ");
172 return -1;
173 }
174
175 reply=sock_comm(fm_fd_r, fm_fd_w, "END");
176 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){
177 errf("Server error (%m)");
178 return -1;
179 }
180
181 if(fclose(fm_fd_r) !=0){
182 errf("Failed to close read FD (%m)");
183 return -1;
184 }
185 if(fclose(fm_fd_w) !=0){
186 errf("Failed to close write FD (%m)");
187 return -1;
188 }
189
190 return 0;
191 }
192
193 int heartbeat(ihost_state_t *ihost_state){
194 struct sockaddr_in addr;
195 struct in_addr haddr;
196 int sd;
197 FILE *fm_fd_r, *fm_fd_w;
198 char *reply;
199 int exitcode=0;
200
201 if ((sd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
202 errf("Can't create AF_INET socket (%m)");
203 return -1;
204 }
205
206 if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){
207 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
208 return -1;
209 }
210
211 memset(&addr, 0, sizeof addr);
212 addr.sin_family = AF_INET;
213 memcpy(&addr.sin_addr, &haddr, sizeof haddr);
214 addr.sin_port = htons(ihost_state->server_tcp_port);
215
216 if (connect(sd, (struct sockaddr *)&addr, sizeof addr) != 0) {
217 errf("Failed to connect to %s on port %d (%m)", ihost_state->fm_host, ihost_state->fm_port);
218 return -1;
219 }
220
221 /* Need to open 2 files, one for reading one for writing, as it gets confused if we only use 1 :) */
222 if ((fm_fd_r=fdopen(sd,"r")) == NULL){
223 errf("Failed to open stream (%m)");
224 return -1;
225 }
226
227 if ((fm_fd_w=fdopen(dup(sd),"w")) == NULL){
228 errf("Failed to open stream (%m)");
229 return -1;
230 }
231
232 reply=sock_comm(fm_fd_r, fm_fd_w, "HEARTBEAT");
233 if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
234 errf("Server error");
235 return -1;
236 }
237
238 reply=sock_comm(fm_fd_r, fm_fd_w, "CONFIG");
239 if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
240 errf("Server error");
241 return -1;
242 }
243
244 reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->files_list);
245 if ((reply==NULL) || (strncasecmp(reply, "OK", 2) != 0) ) {
246 errf("Server error");
247 return -1;
248 }
249
250 reply=sock_comm(fm_fd_r, fm_fd_w, ihost_state->last_modified);
251 if (reply==NULL) {
252 errf("Server error");
253 return -1;
254 }
255 if (strncasecmp(reply, "ERROR", 5) == 0){
256 /* Means the config has changed */
257 exitcode=RECONFIGURE_RETURN_CODE;
258 }
259 reply=sock_comm(fm_fd_r, fm_fd_w, "KEY");
260 if ((reply==NULL) || (strncasecmp(reply, "ERROR", 5) == 0) ) {
261 errf("Server error");
262 return -1;
263 }
264 if (ihost_state->key!=NULL) free(ihost_state->key);
265
266 if((ihost_state->key=strdup(reply)) == NULL){
267 errf("strdup failed (%m)");
268 return -1;
269 }
270
271 reply=sock_comm(fm_fd_r, fm_fd_w, "ENDHEARTBEAT");
272 if((reply== NULL) || (strncasecmp(reply, "ERROR", 5) ==0 )){
273 errf("Server error (%m)");
274 return -1;
275 }
276
277 if(fclose(fm_fd_r) !=0){
278 errf("Failed to close read FD (%m)");
279 return -1;
280 }
281 if(fclose(fm_fd_w) !=0){
282 errf("Failed to close write FD (%m)");
283 return -1;
284 }
285
286 return exitcode;
287 }
288
289 char *stat_grab(ihost_state_t *ihost_state, int counter){
290 #define NUM_STATS 9
291 char *stats[NUM_STATS];
292 char *xml_data=NULL;
293 char *xml_data_p;
294 int x=0;
295
296 stats[0]=get_cpu_stats();
297 stats[1]=get_disk_stats();
298 stats[2]=get_load_stats();
299 stats[3]=get_memory_stats();
300 stats[4]=get_os_info();
301 stats[5]=get_page_stats();
302 stats[6]=get_process_stats();
303 stats[7]=get_swap_stats();
304 stats[8]=get_user_stats();
305
306 for(;x<NUM_STATS;x++){
307 if(stats[x]==NULL){
308 return NULL;
309 }
310 if(xml_data==NULL){
311 if((xml_data=strf("%s", stats[x])) == NULL){
312 errf("str failed (%m)");
313 return NULL;
314 }
315 }else{
316 xml_data_p=xml_data;
317 if((xml_data=strf("%s%s", xml_data, stats[x])) == NULL){
318 errf("str failed (%m)");
319 return NULL;
320 }
321 free(xml_data_p);
322 }
323 free(stats[x]);
324 }
325 xml_data_p=xml_data;
326 xml_data=strf("<packet seq_no=\"%d\" machine_name=\"%s\" date=\"%ld\" type=\"data\" ip=\"%s\" key=\"%s\">%s</packet>", counter, ihost_state->my_fqdn, time(NULL), "127.0.0.1", ihost_state->key, xml_data);
327 free(xml_data_p);
328
329 return xml_data;
330 }
331
332 int send_stats(ihost_state_t *ihost_state, char *data_stream){
333 struct sockaddr_in addr;
334 struct in_addr haddr;
335
336 int sd;
337 size_t len;
338
339 len=strlen(data_stream);
340 if(len>UDP_MAX_PACKET_SIZE){
341 errf("Too big to send to server. Please reconfigure client and server and recompile");
342 exit(1);
343 }
344
345 if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){
346 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
347 return -1;
348 }
349
350 if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
351 errf("failed to create UDP socket (%m)");
352 return -1;
353 }
354
355 memset(&addr, 0, sizeof(addr));
356 addr.sin_family=AF_INET;
357 memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr);
358 addr.sin_port = htons(ihost_state->server_udp_port);
359
360 if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){
361 errf("Send the wrong number of bytes (%m)");
362 return -1;
363 }
364
365 return 0;
366 }
367
368 int main(int argc, char **argv){
369 ihost_state_t ihost_state;
370 int heartbeat_exit;
371 int counter=0;
372 long udp_time=0, tcp_time=0, cur_time=0;
373 int sleep_delay=0;
374 char *xml_stats;
375
376 /* NULL'ify so i can tell if i need to free it or not */
377 ihost_state.fm_host=NULL;
378 ihost_state.my_fqdn=NULL;
379 ihost_state.server_fqdn=NULL;
380 ihost_state.last_modified=NULL;
381 ihost_state.files_list=NULL;
382 ihost_state.key=NULL;
383
384 errf_set_progname(argv[0]);
385 if(argc!=3){
386 errf_usage("<host> <port>");
387 exit(1);
388 }
389
390 ihost_state.fm_host=argv[1];
391 ihost_state.fm_port=atoi(argv[2]);
392
393 if(ihost_configure(&ihost_state)!=0){
394 errf("configure failed");
395 /* Ok, ideally we prob should have 2 copies of the structure and carry on if this
396 happens.. But we dont :) (at the moment) */
397 exit(1);
398 }
399
400 /* get starting stats */
401 if((heartbeat(&ihost_state)) == -1){
402 errf("inital heartbeat failed (%m)");
403 exit(1);
404 }
405
406
407 if((xml_stats=stat_grab(&ihost_state, counter)) == NULL){
408 errf("Failed to get stats (%m)");
409 exit(1);
410 }
411
412
413 for(;;){
414 cur_time=time(NULL);
415 if(cur_time>=tcp_time){
416 heartbeat_exit=heartbeat(&ihost_state);
417 if(heartbeat_exit==RECONFIGURE_RETURN_CODE){
418 errf("heartbeat needs to be reconfigured");
419 ihost_configure(&ihost_state);
420 /* So udp doesn't wait til next sending before updating */
421 udp_time=0;
422 }
423 if(heartbeat_exit==-1){
424 errf("ah crap");
425 exit(1);
426 }
427 tcp_time=time(NULL)+ihost_state.tcp_update_time;
428 }
429 if(cur_time>=udp_time){
430 send_stats(&ihost_state, xml_stats);
431 free(xml_stats);
432 if((xml_stats=stat_grab(&ihost_state, counter)) == NULL){
433 errf("Failed to get stats (%m)");
434 exit(1);
435 }
436 udp_time=time(NULL)+ihost_state.udp_update_time;
437 }
438 if(tcp_time>udp_time){
439 sleep_delay=time(NULL)-tcp_time;
440 }else{
441 sleep_delay=time(NULL)-udp_time;
442 }
443 sleep(sleep_delay);
444 }
445 return 0;
446 }
447