ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/ihost/ihost.c
Revision: 1.10
Committed: Fri May 17 13:43:48 2002 UTC (22 years ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.9: +22 -22 lines
Log Message:
Bug fix, and a minor change on the way i do things since it was broken :)

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 fflush(fm_fd_r);
278 fflush(fm_fd_w);
279
280 if(fclose(fm_fd_r) !=0){
281 errf("Failed to close read FD (%m)");
282 return -1;
283 }
284 if(fclose(fm_fd_w) !=0){
285 errf("Failed to close write FD (%m)");
286 return -1;
287 }
288
289 return exitcode;
290 }
291
292 char *stat_grab(ihost_state_t *ihost_state, int counter){
293 #define NUM_STATS 9
294 char *stats[NUM_STATS];
295 char *xml_data=NULL;
296 char *xml_data_p;
297 int x=0;
298
299 stats[0]=get_cpu_stats();
300 stats[1]=get_disk_stats();
301 stats[2]=get_load_stats();
302 stats[3]=get_memory_stats();
303 stats[4]=get_os_info();
304 stats[5]=get_page_stats();
305 stats[6]=get_process_stats();
306 stats[7]=get_swap_stats();
307 stats[8]=get_user_stats();
308
309 for(;x<NUM_STATS;x++){
310 if(stats[x]==NULL){
311 return NULL;
312 }
313 if(xml_data==NULL){
314 if((xml_data=strf("%s", stats[x])) == NULL){
315 errf("str failed (%m)");
316 return NULL;
317 }
318 }else{
319 xml_data_p=xml_data;
320 if((xml_data=strf("%s%s", xml_data, stats[x])) == NULL){
321 errf("str failed (%m)");
322 return NULL;
323 }
324 free(xml_data_p);
325 }
326 free(stats[x]);
327 }
328 xml_data_p=xml_data;
329 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);
330 free(xml_data_p);
331
332 return xml_data;
333 }
334
335 int send_stats(ihost_state_t *ihost_state, char *data_stream){
336 struct sockaddr_in addr;
337 struct in_addr haddr;
338
339 int sd;
340 size_t len;
341
342 len=strlen(data_stream);
343 if(len>UDP_MAX_PACKET_SIZE){
344 errf("Too big to send to server. Please reconfigure client and server and recompile");
345 exit(1);
346 }
347
348 if (get_host_addr(ihost_state->server_fqdn, &haddr) != 0){
349 errf("Failed to resolve address %s (%m)", ihost_state->fm_host);
350 return -1;
351 }
352
353 if((sd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
354 errf("failed to create UDP socket (%m)");
355 return -1;
356 }
357
358 memset(&addr, 0, sizeof(addr));
359 addr.sin_family=AF_INET;
360 memcpy((char *)&addr.sin_addr, &haddr, sizeof haddr);
361 addr.sin_port = htons(ihost_state->server_udp_port);
362
363 if((sendto(sd, data_stream, len, 0, (struct sockaddr *) &addr, sizeof(addr))) != len){
364 errf("Send the wrong number of bytes (%m)");
365 return -1;
366 }
367
368 close(sd);
369
370 return 0;
371 }
372
373 int main(int argc, char **argv){
374 ihost_state_t ihost_state;
375 int heartbeat_exit;
376 int counter=0;
377 long udp_time=0, tcp_time=0, stat_grab_time=0, cur_time=0;
378 int sleep_delay=0;
379 char *xml_stats;
380
381 /* NULL'ify so i can tell if i need to free it or not */
382 ihost_state.fm_host=NULL;
383 ihost_state.my_fqdn=NULL;
384 ihost_state.server_fqdn=NULL;
385 ihost_state.last_modified=NULL;
386 ihost_state.files_list=NULL;
387 ihost_state.key=NULL;
388
389 errf_set_progname(argv[0]);
390 if(argc!=3){
391 errf_usage("<host> <port>");
392 exit(1);
393 }
394
395 ihost_state.fm_host=argv[1];
396 ihost_state.fm_port=atoi(argv[2]);
397
398 if(ihost_configure(&ihost_state)!=0){
399 errf("configure failed");
400 /* Ok, ideally we prob should have 2 copies of the structure and carry on if this
401 happens.. But we dont :) (at the moment) */
402 exit(1);
403 }
404
405 for(;;){
406 cur_time=time(NULL);
407 if(cur_time>=tcp_time){
408 /*printf("sending TCP\n");*/
409 heartbeat_exit=heartbeat(&ihost_state);
410 if(heartbeat_exit==RECONFIGURE_RETURN_CODE){
411 /*errf("heartbeat needs to be reconfigured");*/
412 ihost_configure(&ihost_state);
413 /* So udp doesn't wait til next sending before updating */
414 udp_time=0;
415 }
416 if(heartbeat_exit==-1){
417 errf("ah crap");
418 exit(1);
419 }
420 tcp_time=time(NULL)+ihost_state.tcp_update_time;
421 }
422
423 if(cur_time>=udp_time){
424 /*printf("sending UDP\n");*/
425 stat_grab_time=time(NULL);
426 if((xml_stats=stat_grab(&ihost_state, counter)) == NULL){
427 errf("Failed to get stats (%m)");
428 exit(1);
429 }
430 stat_grab_time=time(NULL)-stat_grab_time;
431 send_stats(&ihost_state, xml_stats);
432 free(xml_stats);
433 udp_time=time(NULL)+ihost_state.udp_update_time-stat_grab_time;
434 }
435
436 if(tcp_time<udp_time){
437 sleep_delay=tcp_time-time(NULL);
438 }else{
439 sleep_delay=udp_time-time(NULL);
440 }
441
442 /*printf("tcp epoc: %ld \t udp epoc: %ld\ntime:%ld \tsleeping: %d\n", tcp_time, udp_time, time(NULL), sleep_delay);*/
443 if(sleep_delay>0) sleep(sleep_delay);
444 }
445 return 0;
446 }
447