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 1243 2007-06-28 01:48:01Z 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 
00054 static void ping(void);
00055 
00056 extern time_t started_time;
00057 
00062 void
00063 thread_ping(void *arg)
00064 {
00065         pthread_cond_t          cond = PTHREAD_COND_INITIALIZER;
00066         pthread_mutex_t         cond_mutex = PTHREAD_MUTEX_INITIALIZER;
00067         struct  timespec        timeout;
00068         
00069         while (1) {
00070                 /* Make sure we check the servers at the very begining */
00071                 debug(LOG_DEBUG, "Running ping()");
00072                 ping();
00073                 
00074                 /* Sleep for config.checkinterval seconds... */
00075                 timeout.tv_sec = time(NULL) + config_get_config()->checkinterval;
00076                 timeout.tv_nsec = 0;
00077 
00078                 /* Mutex must be locked for pthread_cond_timedwait... */
00079                 pthread_mutex_lock(&cond_mutex);
00080                 
00081                 /* Thread safe "sleep" */
00082                 pthread_cond_timedwait(&cond, &cond_mutex, &timeout);
00083 
00084                 /* No longer needs to be locked */
00085                 pthread_mutex_unlock(&cond_mutex);
00086         }
00087 }
00088 
00092 static void
00093 ping(void)
00094 {
00095         size_t                  numbytes,
00096                                 totalbytes;
00097         int                     sockfd, nfds, done;
00098         char                    request[MAX_BUF];
00099         fd_set                  readfds;
00100         struct timeval          timeout;
00101         FILE * fh;
00102         unsigned long int sys_uptime  = 0;
00103         unsigned int      sys_memfree = 0;
00104         float             sys_load    = 0;
00105         t_auth_serv     *auth_server = NULL;
00106         auth_server = get_auth_server();
00107         
00108         debug(LOG_DEBUG, "Entering ping()");
00109         
00110         /*
00111          * The ping thread does not really try to see if the auth server is actually
00112          * working. Merely that there is a web server listening at the port. And that
00113          * is done by connect_auth_server() internally.
00114          */
00115         sockfd = connect_auth_server();
00116         if (sockfd == -1) {
00117                 /*
00118                  * No auth servers for me to talk to
00119                  */
00120                 return;
00121         }
00122 
00123         /*
00124          * Populate uptime, memfree and load
00125          */
00126         if ((fh = fopen("/proc/uptime", "r"))) {
00127                 fscanf(fh, "%lu", &sys_uptime);
00128                 fclose(fh);
00129         }
00130         if ((fh = fopen("/proc/meminfo", "r"))) {
00131                 while (!feof(fh)) {
00132                         if (fscanf(fh, "MemFree: %u", &sys_memfree) == 0) {
00133                                 /* Not on this line */
00134                                 while (!feof(fh) && fgetc(fh) != '\n');
00135                         }
00136                         else {
00137                                 /* Found it */
00138                                 break;
00139                         }
00140                 }
00141                 fclose(fh);
00142         }
00143         if ((fh = fopen("/proc/loadavg", "r"))) {
00144                 fscanf(fh, "%f", &sys_load);
00145                 fclose(fh);
00146         }
00147 
00148         /*
00149          * Prep & send request
00150          */
00151         snprintf(request, sizeof(request) - 1,
00152                         "GET %s%sgw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%.2f&wifidog_uptime=%lu HTTP/1.0\r\n"
00153                         "User-Agent: WiFiDog %s\r\n"
00154                         "Host: %s\r\n"
00155                         "\r\n",
00156                         auth_server->authserv_path,
00157                         auth_server->authserv_ping_script_path_fragment,
00158                         config_get_config()->gw_id,
00159                         sys_uptime,
00160                         sys_memfree,
00161                         sys_load,
00162                         (long unsigned int)((long unsigned int)time(NULL) - (long unsigned int)started_time),
00163                         VERSION,
00164                         auth_server->authserv_hostname);
00165 
00166         debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request);
00167         
00168         send(sockfd, request, strlen(request), 0);
00169 
00170         debug(LOG_DEBUG, "Reading response");
00171         
00172         numbytes = totalbytes = 0;
00173         done = 0;
00174         do {
00175                 FD_ZERO(&readfds);
00176                 FD_SET(sockfd, &readfds);
00177                 timeout.tv_sec = 30; /* XXX magic... 30 second */
00178                 timeout.tv_usec = 0;
00179                 nfds = sockfd + 1;
00180 
00181                 nfds = select(nfds, &readfds, NULL, NULL, &timeout);
00182 
00183                 if (nfds > 0) {
00186                         numbytes = read(sockfd, request + totalbytes, MAX_BUF - (totalbytes + 1));
00187                         if (numbytes < 0) {
00188                                 debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno));
00189                                 /* FIXME */
00190                                 close(sockfd);
00191                                 return;
00192                         }
00193                         else if (numbytes == 0) {
00194                                 done = 1;
00195                         }
00196                         else {
00197                                 totalbytes += numbytes;
00198                                 debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes);
00199                         }
00200                 }
00201                 else if (nfds == 0) {
00202                         debug(LOG_ERR, "Timed out reading data via select() from auth server");
00203                         /* FIXME */
00204                         close(sockfd);
00205                         return;
00206                 }
00207                 else if (nfds < 0) {
00208                         debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno));
00209                         /* FIXME */
00210                         close(sockfd);
00211                         return;
00212                 }
00213         } while (!done);
00214         close(sockfd);
00215 
00216         debug(LOG_DEBUG, "Done reading reply, total %d bytes", totalbytes);
00217 
00218         request[totalbytes] = '\0';
00219 
00220         debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request);
00221         
00222         if (strstr(request, "Pong") == 0) {
00223                 debug(LOG_WARNING, "Auth server did NOT say pong!");
00224                 /* FIXME */
00225         }
00226         else {
00227                 debug(LOG_DEBUG, "Auth Server Says: Pong");
00228         }
00229 
00230         return; 
00231 }

Generated on Thu Oct 18 17:15:19 2007 for WifiDog by  doxygen 1.5.3