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

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

Thread safe version of gethostbyname()

  • 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 in_addr          *h_addr;
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 ((h_addr = wd_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 = *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                free(h_addr);
136                return;
137        }
138        free(h_addr);
139               
140        snprintf(request, sizeof(request) - 1, "GET %sping/?gw_id=%s HTTP/1.0\n"
141                        "User-Agent: WiFiDog %s\n"
142                        "Host: %s\n"
143                        "\n",
144                        auth_server->authserv_path,
145                        config_get_config()->gw_id,
146                        VERSION,
147                        auth_server->authserv_hostname);
148
149        debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request);
150       
151        send(sockfd, request, strlen(request), 0);
152
153        debug(LOG_DEBUG, "Reading response");
154       
155        numbytes = totalbytes = 0;
156        while ((numbytes = read(sockfd, request + totalbytes, 
157                                MAX_BUF - (totalbytes + 1))) > 0)
158                totalbytes =+ numbytes;
159       
160        if (numbytes == -1) {
161                debug(LOG_ERR, "read(): %s", strerror(errno));
162                mark_auth_server_bad(auth_server);
163                close(sockfd);
164                return;
165        }
166
167        numbytes = totalbytes;
168       
169        request[numbytes] = '\0';
170
171        close(sockfd);
172
173        debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request);
174       
175        if (!strstr(request, "Pong")) {
176                debug(LOG_ERR, "Primary auth server offline");
177                debug(LOG_ERR, "Bumping auth server to last in line.");
178                mark_auth_server_bad(auth_server);
179                return;
180        }
181       
182        debug(LOG_DEBUG, "Auth Server Says: Pong");
183        return; 
184}
Note: See TracBrowser for help on using the browser.