ping_thread.c

Go to the documentation of this file.
00001 /********************************************************************\
00002  * This program is free software; you can redistribute it and/or    *
00003  * modify it under the terms of the GNU General Public License as   *
00004  * published by the Free Software Foundation; either version 2 of   *
00005  * the License, or (at your option) any later version.              *
00006  *                                                                  *
00007  * This program is distributed in the hope that it will be useful,  *
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00010  * GNU General Public License for more details.                     *
00011  *                                                                  *
00012  * You should have received a copy of the GNU General Public License*
00013  * along with this program; if not, contact:                        *
00014  *                                                                  *
00015  * Free Software Foundation           Voice:  +1-617-542-5942       *
00016  * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
00017  * Boston, MA  02111-1307,  USA       gnu@gnu.org                   *
00018  *                                                                  *
00019 \********************************************************************/
00020 
00021 /* $Id: ping_thread.c 1305 2007-11-01 20:04:20Z benoitg $ */
00029 #define _GNU_SOURCE
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <pthread.h>
00034 #include <string.h>
00035 #include <stdarg.h>
00036 #include <sys/types.h>
00037 #include <sys/socket.h>
00038 #include <netinet/in.h>
00039 #include <arpa/inet.h>
00040 #include <netdb.h>
00041 #include <unistd.h>
00042 #include <syslog.h>
00043 #include <signal.h>
00044 #include <errno.h>
00045 
00046 #include "../config.h"
00047 #include "safe.h"
00048 #include "common.h"
00049 #include "conf.h"
00050 #include "debug.h"
00051 #include "ping_thread.h"
00052 #include "util.h"
00053 #include "centralserver.h"
00054 
00055 static void ping(void);
00056 
00057 extern time_t started_time;
00058 
00063 void
00064 thread_ping(void *arg)
00065 {
00066         pthread_cond_t          cond = PTHREAD_COND_INITIALIZER;
00067         pthread_mutex_t         cond_mutex = PTHREAD_MUTEX_INITIALIZER;
00068         struct  timespec        timeout;
00069         
00070         while (1) {
00071                 /* Make sure we check the servers at the very begining */
00072                 debug(LOG_DEBUG, "Running ping()");
00073                 ping();
00074                 
00075                 /* Sleep for config.checkinterval seconds... */
00076                 timeout.tv_sec = time(NULL) + config_get_config()->checkinterval;
00077                 timeout.tv_nsec = 0;
00078 
00079                 /* Mutex must be locked for pthread_cond_timedwait... */
00080                 pthread_mutex_lock(&cond_mutex);
00081                 
00082                 /* Thread safe "sleep" */
00083                 pthread_cond_timedwait(&cond, &cond_mutex, &timeout);
00084 
00085                 /* No longer needs to be locked */
00086                 pthread_mutex_unlock(&cond_mutex);
00087         }
00088 }
00089 
00093 static void
00094 ping(void)
00095 {
00096         size_t                  numbytes,
00097                                 totalbytes;
00098         int                     sockfd, nfds, done;
00099         char                    request[MAX_BUF];
00100         fd_set                  readfds;
00101         struct timeval          timeout;
00102         FILE * fh;
00103         unsigned long int sys_uptime  = 0;
00104         unsigned int      sys_memfree = 0;
00105         float             sys_load    = 0;
00106         t_auth_serv     *auth_server = NULL;
00107         auth_server = get_auth_server();
00108         
00109         debug(LOG_DEBUG, "Entering ping()");
00110         
00111         /*
00112          * The ping thread does not really try to see if the auth server is actually
00113          * working. Merely that there is a web server listening at the port. And that
00114          * is done by connect_auth_server() internally.
00115          */
00116         sockfd = connect_auth_server();
00117         if (sockfd == -1) {
00118                 /*
00119                  * No auth servers for me to talk to
00120                  */
00121                 return;
00122         }
00123 
00124         /*
00125          * Populate uptime, memfree and load
00126          */
00127         if ((fh = fopen("/proc/uptime", "r"))) {
00128                 fscanf(fh, "%lu", &sys_uptime);
00129                 fclose(fh);
00130         }
00131         if ((fh = fopen("/proc/meminfo", "r"))) {
00132                 while (!feof(fh)) {
00133                         if (fscanf(fh, "MemFree: %u", &sys_memfree) == 0) {
00134                                 /* Not on this line */
00135                                 while (!feof(fh) && fgetc(fh) != '\n');
00136                         }
00137                         else {
00138                                 /* Found it */
00139                                 break;
00140                         }
00141                 }
00142                 fclose(fh);
00143         }
00144         if ((fh = fopen("/proc/loadavg", "r"))) {
00145                 fscanf(fh, "%f", &sys_load);
00146                 fclose(fh);
00147         }
00148 
00149         /*
00150          * Prep & send request
00151          */
00152         snprintf(request, sizeof(request) - 1,
00153                         "GET %s%sgw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%.2f&wifidog_uptime=%lu HTTP/1.0\r\n"
00154                         "User-Agent: WiFiDog %s\r\n"
00155                         "Host: %s\r\n"
00156                         "\r\n",
00157                         auth_server->authserv_path,
00158                         auth_server->authserv_ping_script_path_fragment,
00159                         config_get_config()->gw_id,
00160                         sys_uptime,
00161                         sys_memfree,
00162                         sys_load,
00163                         (long unsigned int)((long unsigned int)time(NULL) - (long unsigned int)started_time),
00164                         VERSION,
00165                         auth_server->authserv_hostname);
00166 
00167         debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request);
00168         
00169         send(sockfd, request, strlen(request), 0);
00170 
00171         debug(LOG_DEBUG, "Reading response");
00172         
00173         numbytes = totalbytes = 0;
00174         done = 0;
00175         do {
00176                 FD_ZERO(&readfds);
00177                 FD_SET(sockfd, &readfds);
00178                 timeout.tv_sec = 30; /* XXX magic... 30 second */
00179                 timeout.tv_usec = 0;
00180                 nfds = sockfd + 1;
00181 
00182                 nfds = select(nfds, &readfds, NULL, NULL, &timeout);
00183 
00184                 if (nfds > 0) {
00187                         numbytes = read(sockfd, request + totalbytes, MAX_BUF - (totalbytes + 1));
00188                         if (numbytes < 0) {
00189                                 debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno));
00190                                 /* FIXME */
00191                                 close(sockfd);
00192                                 return;
00193                         }
00194                         else if (numbytes == 0) {
00195                                 done = 1;
00196                         }
00197                         else {
00198                                 totalbytes += numbytes;
00199                                 debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes);
00200                         }
00201                 }
00202                 else if (nfds == 0) {
00203                         debug(LOG_ERR, "Timed out reading data via select() from auth server");
00204                         /* FIXME */
00205                         close(sockfd);
00206                         return;
00207                 }
00208                 else if (nfds < 0) {
00209                         debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno));
00210                         /* FIXME */
00211                         close(sockfd);
00212                         return;
00213                 }
00214         } while (!done);
00215         close(sockfd);
00216 
00217         debug(LOG_DEBUG, "Done reading reply, total %d bytes", totalbytes);
00218 
00219         request[totalbytes] = '\0';
00220 
00221         debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request);
00222         
00223         if (strstr(request, "Pong") == 0) {
00224                 debug(LOG_WARNING, "Auth server did NOT say pong!");
00225                 /* FIXME */
00226         }
00227         else {
00228                 debug(LOG_DEBUG, "Auth Server Says: Pong");
00229         }
00230 
00231         return; 
00232 }

Generated on Sun Apr 13 21:55:00 2008 for WifiDog by  doxygen 1.5.3