ping_thread.c

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 1162 2007-01-06 23:51:02Z 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 
00106 
00107         debug(LOG_DEBUG, "Entering ping()");
00108         
00109         /*
00110          * The ping thread does not really try to see if the auth server is actually
00111          * working. Merely that there is a web server listening at the port. And that
00112          * is done by connect_auth_server() internally.
00113          */
00114         sockfd = connect_auth_server();
00115         if (sockfd == -1) {
00116                 /*
00117                  * No auth servers for me to talk to
00118                  */
00119                 return;
00120         }
00121 
00122         /*
00123          * Populate uptime, memfree and load
00124          */
00125         if ((fh = fopen("/proc/uptime", "r"))) {
00126                 fscanf(fh, "%lu", &sys_uptime);
00127                 fclose(fh);
00128         }
00129         if ((fh = fopen("/proc/meminfo", "r"))) {
00130                 while (!feof(fh)) {
00131                         if (fscanf(fh, "MemFree: %u", &sys_memfree) == 0) {
00132                                 /* Not on this line */
00133                                 while (!feof(fh) && fgetc(fh) != '\n');
00134                         }
00135                         else {
00136                                 /* Found it */
00137                                 break;
00138                         }
00139                 }
00140                 fclose(fh);
00141         }
00142         if ((fh = fopen("/proc/loadavg", "r"))) {
00143                 fscanf(fh, "%f", &sys_load);
00144                 fclose(fh);
00145         }
00146 
00147         /*
00148          * Prep & send request
00149          */
00150         snprintf(request, sizeof(request) - 1,
00151                         "GET %sping/?gw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%.2f&wifidog_uptime=%lu HTTP/1.0\r\n"
00152                         "User-Agent: WiFiDog %s\r\n"
00153                         "Host: %s\r\n"
00154                         "\r\n",
00155                         config_get_config()->auth_servers->authserv_path,
00156                         config_get_config()->gw_id,
00157                         sys_uptime,
00158                         sys_memfree,
00159                         sys_load,
00160                         (long unsigned int)((long unsigned int)time(NULL) - (long unsigned int)started_time),
00161                         VERSION,
00162                         config_get_config()->auth_servers->authserv_hostname);
00163 
00164         debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request);
00165         
00166         send(sockfd, request, strlen(request), 0);
00167 
00168         debug(LOG_DEBUG, "Reading response");
00169         
00170         numbytes = totalbytes = 0;
00171         done = 0;
00172         do {
00173                 FD_ZERO(&readfds);
00174                 FD_SET(sockfd, &readfds);
00175                 timeout.tv_sec = 30; /* XXX magic... 30 second */
00176                 timeout.tv_usec = 0;
00177                 nfds = sockfd + 1;
00178 
00179                 nfds = select(nfds, &readfds, NULL, NULL, &timeout);
00180 
00181                 if (nfds > 0) {
00184                         numbytes = read(sockfd, request + totalbytes, MAX_BUF - (totalbytes + 1));
00185                         if (numbytes < 0) {
00186                                 debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno));
00187                                 /* FIXME */
00188                                 close(sockfd);
00189                                 return;
00190                         }
00191                         else if (numbytes == 0) {
00192                                 done = 1;
00193                         }
00194                         else {
00195                                 totalbytes += numbytes;
00196                                 debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes);
00197                         }
00198                 }
00199                 else if (nfds == 0) {
00200                         debug(LOG_ERR, "Timed out reading data via select() from auth server");
00201                         /* FIXME */
00202                         close(sockfd);
00203                         return;
00204                 }
00205                 else if (nfds < 0) {
00206                         debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno));
00207                         /* FIXME */
00208                         close(sockfd);
00209                         return;
00210                 }
00211         } while (!done);
00212         close(sockfd);
00213 
00214         debug(LOG_DEBUG, "Done reading reply, total %d bytes", totalbytes);
00215 
00216         request[totalbytes] = '\0';
00217 
00218         debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request);
00219         
00220         if (strstr(request, "Pong") == 0) {
00221                 debug(LOG_WARNING, "Auth server did NOT say pong!");
00222                 /* FIXME */
00223         }
00224         else {
00225                 debug(LOG_DEBUG, "Auth Server Says: Pong");
00226         }
00227 
00228         return; 
00229 }

Generated on Sat Jan 6 18:51:44 2007 for WifiDog by  doxygen 1.5.1