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

Revision 239, 5.5 KB (checked in by alexcv, 9 years ago)

Fixed fd leak, added extra comments.

  • 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
50static void ping(void);
51
52/** Launches a thread that periodically checks in with the wifidog auth server to perform heartbeat function.
53@param arg NULL
54@todo This thread loops infinitely, need a watchdog to verify that it is still running?
55*/ 
56void
57thread_ping(void *arg)
58{
59        pthread_cond_t          cond = PTHREAD_COND_INITIALIZER;
60        pthread_mutex_t         cond_mutex = PTHREAD_MUTEX_INITIALIZER;
61        struct  timespec        timeout;
62       
63        while (1) {
64                /* Make sure we check the servers at the very begining */
65                /** @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 */
66                ping();
67               
68                /* Sleep for config.checkinterval seconds... */
69                timeout.tv_sec = time(NULL) +
70                                config_get_config()->checkinterval;
71                timeout.tv_nsec = 0;
72
73                /* Mutex must be locked for pthread_cond_timedwait... */
74                pthread_mutex_lock(&cond_mutex);
75               
76                /* Thread safe "sleep" */
77                pthread_cond_timedwait(&cond, &cond_mutex, &timeout);
78
79                /* No longer needs to be locked */
80                pthread_mutex_unlock(&cond_mutex);
81        }
82}
83
84/** @internal
85 * This function does the actual request.
86 */
87static void
88ping(void)
89{
90        size_t                  numbytes,
91                                totalbytes;
92        int                     sockfd;
93        t_auth_serv             *auth_server;
94        char                    request[MAX_BUF];
95        struct hostent          *he;
96        struct sockaddr_in      their_addr;
97
98        debug(LOG_DEBUG, "Entering ping()");
99       
100        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
101                debug(LOG_ERR, "socket(): %s", strerror(errno));
102                exit(1);
103        }
104
105        auth_server = get_auth_server();
106
107        debug(LOG_DEBUG, "Using auth server %s",
108                        auth_server->authserv_hostname);
109       
110        if ((he = gethostbyname(auth_server->authserv_hostname)) == NULL) {
111                debug(LOG_ERR, "Failed to resolve %s via gethostbyname"
112                                "(): %s", auth_server->authserv_hostname, 
113                                strerror(errno));
114                debug(LOG_ERR, "Bumping auth server to last in line.");
115                mark_auth_server_bad(auth_server);
116                close(sockfd);
117                return;
118        }
119
120        their_addr.sin_family = AF_INET;
121        their_addr.sin_port = htons(auth_server->authserv_http_port);
122        their_addr.sin_addr = *((struct in_addr *)he->h_addr);
123        memset(&(their_addr.sin_zero), '\0', sizeof(their_addr.sin_zero));
124
125        debug(LOG_INFO, "Connecting to auth server %s on port %d", 
126                        auth_server->authserv_hostname, 
127                        auth_server->authserv_http_port);
128
129        if (connect(sockfd, (struct sockaddr *)&their_addr,
130                                sizeof(struct sockaddr)) == -1) {
131                debug(LOG_ERR, "connect(): %s", strerror(errno));
132                debug(LOG_ERR, "Bumping auth server to last in line.");
133                mark_auth_server_bad(auth_server);
134                close(sockfd);
135                return;
136        }
137               
138        snprintf(request, sizeof(request) - 1, "GET %sping/?gw_id=%s HTTP/1.0\n"
139                        "User-Agent: WiFiDog %s\n"
140                        "Host: %s\n"
141                        "\n",
142                        auth_server->authserv_path,
143                        config_get_config()->gw_id,
144                        VERSION,
145                        auth_server->authserv_hostname);
146
147        debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request);
148       
149        send(sockfd, request, strlen(request), 0);
150
151        debug(LOG_DEBUG, "Reading response");
152       
153        numbytes = totalbytes = 0;
154        while ((numbytes = read(sockfd, request + totalbytes, 
155                                MAX_BUF - (totalbytes + 1))) > 0)
156                totalbytes =+ numbytes;
157       
158        if (numbytes == -1) {
159                debug(LOG_ERR, "read(): %s", strerror(errno));
160                mark_auth_server_bad(auth_server);
161                close(sockfd);
162                return;
163        }
164
165        numbytes = totalbytes;
166       
167        request[numbytes] = '\0';
168
169        close(sockfd);
170
171        debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request);
172       
173        if (!strstr(request, "Pong")) {
174                debug(LOG_ERR, "Primary auth server offline");
175                debug(LOG_ERR, "Bumping auth server to last in line.");
176                mark_auth_server_bad(auth_server);
177                return;
178        }
179       
180        debug(LOG_DEBUG, "Auth Server Says: Pong");
181        return; 
182}
Note: See TracBrowser for help on using the browser.