root/trunk/wifidog/src/ping_thread.c @ 450

Revision 450, 7.7 KB (checked in by minaguib, 8 years ago)

When pinging auth server now also sends sys_uptime, sys_memfree and sys_load

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/********************************************************************\
2 * This program is free software; you can redistribute it and/or    *
3 * modify it under the terms of the GNU General Public License as   *
4 * published by the Free Software Foundation; either version 2 of   *
5 * the License, or (at your option) any later version.              *
6 *                                                                  *
7 * This program is distributed in the hope that it will be useful,  *
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
10 * GNU General Public License for more details.                     *
11 *                                                                  *
12 * You should have received a copy of the GNU General Public License*
13 * along with this program; if not, contact:                        *
14 *                                                                  *
15 * Free Software Foundation           Voice:  +1-617-542-5942       *
16 * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
17 * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
18 *                                                                  *
19\********************************************************************/
20
21/* $Header$ */
22/** @file ping_thread.c
23    @brief Periodically checks in with the central auth server to make sure everything is running properly.
24    @author Copyright (C) 2004 Alexandre Carmel-Veilleux <acv@acv.ca>
25*/
26
27#define _GNU_SOURCE
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <pthread.h>
32#include <string.h>
33#include <stdarg.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <netdb.h>
39#include <unistd.h>
40#include <syslog.h>
41#include <signal.h>
42#include <errno.h>
43
44#include "../config.h"
45#include "common.h"
46#include "conf.h"
47#include "debug.h"
48#include "ping_thread.h"
49#include "util.h"
50
51static void ping(void);
52
53/** Launches a thread that periodically checks in with the wifidog auth server to perform heartbeat function.
54@param arg NULL
55@todo This thread loops infinitely, need a watchdog to verify that it is still running?
56*/ 
57void
58thread_ping(void *arg)
59{
60        pthread_cond_t          cond = PTHREAD_COND_INITIALIZER;
61        pthread_mutex_t         cond_mutex = PTHREAD_MUTEX_INITIALIZER;
62        struct  timespec        timeout;
63       
64        while (1) {
65                /* Make sure we check the servers at the very begining */
66                /** @todo  Note that this will only help if the second server responds.  The logic of the ping itslef should be changed so it iterates in the list until it finds one that responds ox exausts the list */
67                debug(LOG_DEBUG, "Running ping()");
68                ping();
69               
70                /* Sleep for config.checkinterval seconds... */
71                timeout.tv_sec = time(NULL) +
72                                config_get_config()->checkinterval;
73                timeout.tv_nsec = 0;
74
75                /* Mutex must be locked for pthread_cond_timedwait... */
76                pthread_mutex_lock(&cond_mutex);
77               
78                /* Thread safe "sleep" */
79                pthread_cond_timedwait(&cond, &cond_mutex, &timeout);
80
81                /* No longer needs to be locked */
82                pthread_mutex_unlock(&cond_mutex);
83        }
84}
85
86/** @internal
87 * This function does the actual request.
88 */
89static void
90ping(void)
91{
92        size_t                  numbytes,
93                                totalbytes;
94        int                     sockfd,
95                                nfds,
96                                done,
97                                i;
98        t_auth_serv             *auth_server;
99        char                    request[MAX_BUF],
100                                *tmp_addr;
101        struct in_addr          *h_addr;
102        struct sockaddr_in      their_addr;
103        fd_set                  readfds;
104        struct timeval          timeout;
105        FILE * fh;
106        unsigned long int sys_uptime  = 0;
107        unsigned int      sys_memfree = 0;
108        float             sys_load    = 0;
109
110
111        debug(LOG_DEBUG, "Entering ping()");
112       
113        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
114                debug(LOG_ERR, "socket(): %s", strerror(errno));
115                exit(1);
116        }
117
118        auth_server = get_auth_server();
119
120        debug(LOG_DEBUG, "Using auth server %s",
121                        auth_server->authserv_hostname);
122       
123        debug(LOG_DEBUG, "Resolving IP");
124        if ((h_addr = (struct in_addr *)wd_gethostbyname(auth_server->authserv_hostname)) == NULL) {
125                debug(LOG_ERR, "Failed to resolve %s via gethostbyname"
126                                "(): %s", auth_server->authserv_hostname, 
127                                strerror(errno));
128                debug(LOG_ERR, "Bumping auth server to last in line.");
129                mark_auth_server_bad(auth_server);
130                close(sockfd);
131                return;
132        }
133
134        if (auth_server->last_ip == NULL) {
135                auth_server->last_ip = strdup(inet_ntoa(*h_addr));
136                if (auth_server->last_ip == NULL) {
137                        debug(LOG_CRIT, "Could not allocate memory, Banzai!");
138                        exit(-1);
139                }
140        } else {
141                tmp_addr = strdup(inet_ntoa(*h_addr));
142                if (strcmp(auth_server->last_ip, tmp_addr) != 0) {
143                        free(auth_server->last_ip);
144                        auth_server->last_ip = tmp_addr;
145                        fw_clear_authservers();
146                        fw_set_authservers();
147                } else {
148                        free(tmp_addr);
149                }
150        }
151
152        their_addr.sin_family = AF_INET;
153        their_addr.sin_port = htons(auth_server->authserv_http_port);
154        their_addr.sin_addr = *h_addr;
155        memset(&(their_addr.sin_zero), '\0', sizeof(their_addr.sin_zero));
156
157        debug(LOG_INFO, "Connecting to auth server %s on port %d", 
158                        auth_server->authserv_hostname, 
159                        auth_server->authserv_http_port);
160
161        if (connect(sockfd, (struct sockaddr *)&their_addr,
162                                sizeof(struct sockaddr)) == -1) {
163                debug(LOG_ERR, "connect(): %s", strerror(errno));
164                debug(LOG_ERR, "Bumping auth server to last in line.");
165                mark_auth_server_bad(auth_server);
166                close(sockfd);
167                free(h_addr);
168                return;
169        }
170        free(h_addr);
171               
172        mark_online();
173
174        /*
175         * Populate uptime, memfree and load
176         */
177        if ((fh = fopen("/proc/uptime", "r"))) {
178                fscanf(fh, "%lu", &sys_uptime);
179                fclose(fh);
180        }
181        if ((fh = fopen("/proc/meminfo", "r"))) {
182                while (!feof(fh)) {
183                        if (fscanf(fh, "MemFree: %u", &sys_memfree) == 0) {
184                                /* Not on this line */
185                                while (!feof(fh) && fgetc(fh) != '\n');
186                        }
187                        else {
188                                /* Found it */
189                                break;
190                        }
191                }
192                fclose(fh);
193        }
194        if ((fh = fopen("/proc/loadavg", "r"))) {
195                fscanf(fh, "%*s %f", &sys_load);
196                fclose(fh);
197        }
198
199        snprintf(request, sizeof(request) - 1, "GET %sping/?gw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%f HTTP/1.0\n"
200                        "User-Agent: WiFiDog %s\n"
201                        "Host: %s\n"
202                        "\n",
203                        auth_server->authserv_path,
204                        config_get_config()->gw_id,
205                        sys_uptime,
206                        sys_memfree,
207                        sys_load,
208                        VERSION,
209                        auth_server->authserv_hostname);
210
211        debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request);
212       
213        send(sockfd, request, strlen(request), 0);
214
215        debug(LOG_DEBUG, "Reading response");
216       
217        numbytes = totalbytes = 0;
218        done = 0;
219        do {
220                FD_ZERO(&readfds);
221                FD_SET(sockfd, &readfds);
222                timeout.tv_sec = 30; /* XXX magic... 30 second */
223                timeout.tv_usec = 0;
224                nfds = sockfd + 1;
225
226                nfds = select(nfds, &readfds, NULL, NULL, &timeout);
227
228                if (nfds > 0) {
229                        /** We don't have to use FD_ISSET() because there
230                         *  was only one fd. */
231                        numbytes = read(sockfd, request + totalbytes,
232                                        MAX_BUF - (totalbytes + 1));
233                        if (numbytes < 0) {
234                                debug(LOG_ERR, "read(): %s", strerror(errno));
235                                mark_auth_server_bad(auth_server);
236                                close(sockfd);
237                                return;
238                        } else if (numbytes == 0) {
239                                done = 1;
240                        } else {
241                                totalbytes += numbytes;
242                                debug(LOG_DEBUG, "Read %d bytes, total now %d",
243                                                numbytes, totalbytes);
244                        }
245                } else if (nfds == 0) {
246                        debug(LOG_ERR, "select() timed out");
247                        mark_auth_server_bad(auth_server);
248                        close(sockfd);
249                        return;
250                } else if (nfds < 0) {
251                        debug(LOG_ERR, "select(): %s", strerror(errno));
252                        mark_auth_server_bad(auth_server);
253                        close(sockfd);
254                        return;
255                }
256        } while (!done);
257
258        debug(LOG_DEBUG, "Done reading reply, total %d bytes", totalbytes);
259
260        numbytes = totalbytes;
261       
262        request[numbytes] = '\0';
263
264        close(sockfd);
265
266        debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request);
267       
268        if (!strstr(request, "Pong")) {
269                debug(LOG_ERR, "Primary auth server offline");
270                debug(LOG_ERR, "Bumping auth server to last in line.");
271                mark_auth_server_bad(auth_server);
272                return;
273        }
274       
275        debug(LOG_DEBUG, "Auth Server Says: Pong");
276        return; 
277}
Note: See TracBrowser for help on using the browser.