#include #include #include #include #include #include #include #include #include #include "client.h" #include "../proto/xmon-proto-1.h" char *leafname, *host; struct sockaddr_in addr; int xid_sent_latest=-1, xid_recv_latest=-1, xid_hand_latest=-1; static struct timeval time_last_sent[2]; static int timeout_type=VALUE_UNAVAILABLE; static int sock; static int retransmited=0; int port=400; void packet_init(void) { addr.sin_family=AF_INET; addr.sin_port=htons(port); if ((sock=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) { fprintf(stderr, "socket: %s\n", strerror(errno)); exit(1); } if (connect(sock, (struct sockaddr *)&addr, sizeof(addr))) { fprintf(stderr, "socket: %s\n", strerror(errno)); exit(1); } packet_send(0); } void packet_send(int repeat) { static struct request request; retransmited=repeat; if (!repeat) { if (xid_sent_latest>xid_recv_latest) timeout_type=VALUE_UNAVAILABLE; xid_sent_latest++; request.version=htonl(XM_VERSION); request.magic=htonl(XM_MAGIC); request.calltype=htonl(XM_REQUEST); request.opcode=htonl(XM_OP_SYSINFO); } request.xid=repeat? (-1-xid_sent_latest):xid_sent_latest; send(sock, (char *)&request, sizeof(request), 0); gettimeofday(&time_last_sent[repeat], NULL); } void packet_preselect(int *maxfd, fd_set *fds, struct timeval *tvp) { static struct timeval tv; FD_SET(sock, fds); if (*maxfdxid_hand_latest) { struct timeval now; gettimeofday(&now, NULL); if (retransmited) { tv.tv_sec=time_last_sent[1].tv_sec+PKT_TIMEOUT_SEC; tv.tv_usec=time_last_sent[1].tv_usec+PKT_TIMEOUT_USEC; } else { tv.tv_sec=time_last_sent[0].tv_sec+PKT_RETRANSMIT_SEC; tv.tv_usec=time_last_sent[0].tv_usec+PKT_RETRANSMIT_USEC; } if (tv.tv_usec>=1000000) {tv.tv_sec++, tv.tv_usec-=1000000;} tv_expire(tvp, &tv); } } static int packet_decode(struct reply *reply, int bytes, struct xmsysinfo *info) { if (bytes<20) return 1; if (reply->magic!=htonl(XM_MAGIC)) return 1; if (reply->calltype!=htonl(XM_REPLY)) return 1; reply->status=ntohs(reply->status); reply->opcode=ntohs(reply->opcode); if (reply->status!=XM_STATUS_OK) { if (reply->status!=XM_STATUS_ERR) { fprintf(stderr, "Unknown error status\n"); } else { switch(reply->t.err.reason) { case XM_ERR_WRONGVER: fprintf(stderr, "Wrong version\n"); break; case XM_ERR_UNKNOWNOP: fprintf(stderr, "Unknown opcode\n"); break; case XM_ERR_FAULT: fprintf(stderr, "Server fault\n"); break; default: fprintf(stderr, "Unknown error\n"); } } return 1; } if (reply->opcode!=XM_OP_SYSINFO) { fprintf(stderr, "Unexpected opcode %i\n", reply->opcode); return 1; } if (bytes<20+(int)sizeof(struct reply_sysinfo)) { printf("Truncated sysinfo packet\n"); return 1; } info->flags=ntohl(reply->t.sysinfo.flags); info->uptime=ntohl(reply->t.sysinfo.uptime); info->loads[0]=ntohl(reply->t.sysinfo.loads[0]); info->loads[1]=ntohl(reply->t.sysinfo.loads[1]); info->loads[2]=ntohl(reply->t.sysinfo.loads[2]); info->totalram=ntohl(reply->t.sysinfo.totalram); info->freeram=ntohl(reply->t.sysinfo.freeram); info->sharedram=ntohl(reply->t.sysinfo.sharedram); info->bufferram=ntohl(reply->t.sysinfo.bufferram); info->totalswap=ntohl(reply->t.sysinfo.totalswap); info->freeswap=ntohl(reply->t.sysinfo.freeswap); info->procs=ntohl((long)reply->t.sysinfo.procs); return 0; } void packet_postselect(fd_set *fds) { int bytes; struct xmsysinfo info; struct reply reply; int isretransmission=0; struct timeval now, rtt; if (!FD_ISSET(sock, fds)) { if (xid_sent_latest>xid_hand_latest) { struct timeval tv; gettimeofday(&now, NULL); if (!retransmited) { tv.tv_sec=time_last_sent[0].tv_sec +PKT_RETRANSMIT_SEC-now.tv_sec; tv.tv_usec=time_last_sent[0].tv_usec +PKT_RETRANSMIT_USEC-now.tv_usec-1; if (tv.tv_usec<0) { tv.tv_sec--; tv.tv_usec+=1000000; } if (tv.tv_sec<0) { packet_send(1); } } else { tv.tv_sec=time_last_sent[1].tv_sec +PKT_TIMEOUT_SEC-now.tv_sec; tv.tv_usec=time_last_sent[1].tv_usec +PKT_TIMEOUT_USEC-now.tv_usec-1; if (tv.tv_usec<0) { tv.tv_sec--; tv.tv_usec+=1000000; } if (tv.tv_sec<0) { array_fill(xid_hand_latest+1, xid_sent_latest, timeout_type, time(NULL)); xid_hand_latest=xid_sent_latest; screen_update(xid_hand_latest); screen_rotate(xid_hand_latest -xid_display_last); } } } return; } gettimeofday(&now, NULL); bytes=recv(sock, (char *)&reply, sizeof(reply), 0); if (bytes==-1) { if (errno!=ECONNREFUSED) { fprintf(stderr, "recv: %s\n", strerror(errno)); exit(1); } timeout_type=VALUE_UNKNOWN; return; } timeout_type=VALUE_UNAVAILABLE; if (packet_decode(&reply, bytes, &info)) return; if (reply.xid<0) { reply.xid=-1-reply.xid; isretransmission=1; } if (reply.xidxid_sent_latest) return; if (xid_hand_latest=time_last_sent[isretransmission].tv_usec) { rtt.tv_usec=now.tv_usec-time_last_sent[isretransmission].tv_usec; } else { rtt.tv_usec=1000000+now.tv_usec-time_last_sent[isretransmission].tv_usec; rtt.tv_sec--; } info.rtt=(rtt.tv_sec*1000)+(rtt.tv_usec/1000); array_store(reply.xid, VALUE_KNOWN, &info, time_last_sent[isretransmission].tv_sec); screen_update(reply.xid); screen_rotate(reply.xid-xid_display_last); if (screen_need_rescale) screen_recalc(); }