/*
* Copyright (C), 2000-2007 by the monit project group.
* All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "monitor.h"
#include "socket.h"
#include "event.h"
/**
* Connect to a data collector server and send event or status message.
*
* @author Martin Pala, <martinp@tildeslash.com>
*
* @version \$Id: collector.c,v 1.15 2007/07/25 12:54:28 hauk Exp $
*
* @file
*/
/* -------------------------------------------------------------- Prototypes */
static int data_send(Collector_T, char *);
static int data_check(Collector_T);
/* ------------------------------------------------------------------ Public */
/**
* Post event or status data message to the collector
* @param E An event object or NULL for status data
* @return If failed, return HANDLER_COLLECTOR flag or HANDLER_PASSED flag if passed
*/
int handle_collector(Event_T E) {
char *D = NULL;
Collector_T C = Run.collectors;
sigset_t ns;
sigset_t os;
int rv = HANDLER_PASSED;
/* The event is send to the collector just once - only in the case
* that the state changed/matched */
if(!C || (E && !E->state_changed && (E->id != EVENT_CHANGED || E->id != EVENT_MATCH)))
{
return rv;
}
set_signal_block(&ns, &os);
while(!(C->socket=
socket_create_t(C->url->hostname, C->url->port, SOCKET_TCP, C->ssl, C->timeout)
))
{
LogError("Collector: cannot open a connection to %s -- %s\n",
C->url->url, STRERROR);
if((C= C->next))
{
LogInfo("Collector: trying next server %s\n", C->url->url);
continue;
}
else
{
LogError("Collector: no server available\n");
rv = HANDLER_COLLECTOR;
goto exit2;
}
}
D = status_xml(E, LEVEL_FULL);
if(!data_send(C, D))
{
LogError("Collector: communication failure\n");
rv = HANDLER_COLLECTOR;
goto exit1;
}
if(!data_check(C))
{
LogError("Collector: communication failure\n");
rv = HANDLER_COLLECTOR;
goto exit1;
}
DEBUG("Collector: %s message send to %s\n", E?"event":"status", C->url->url);
exit1:
FREE(D);
if(C->socket)
{
socket_free(&C->socket);
}
exit2:
unset_signal_block(&os);
return rv;
}
/* ----------------------------------------------------------------- Private */
/**
* Send message to the server
* @param C An collector object
* @param D Data to send
* @return TRUE if the message sending succeeded otherwise FALSE
*/
static int data_send(Collector_T C, char *D) {
int rv;
char *auth;
auth = Util_getBasicAuthHeader();
rv = socket_print(C->socket,
"POST %s HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"Content-Type: text/xml\r\n"
"Content-Length: %d\r\n"
"Pragma: no-cache\r\n"
"Accept: */*\r\n"
"User-Agent: %s/%s\r\n"
"Connection: close\r\n"
"%s"
"\r\n"
"%s",
C->url->path,
C->url->hostname, C->url->port,
strlen(D),
prog, VERSION,
auth?auth:"",
D);
FREE(auth);
if(rv <0)
{
LogError("Collector: error sending data to %s -- %s\n",
C->url->url, STRERROR);
return FALSE;
}
return TRUE;
}
/**
* Check that the server returns a valid HTTP response
* @param C An collector object
* @return TRUE if the response is valid otherwise FALSE
*/
static int data_check(Collector_T C) {
int n;
int status;
char buf[STRLEN];
if(!socket_readln(C->socket, buf, sizeof(buf))) {
LogError("Collector: error receiving data from %s -- %s\n",
C->url->url, STRERROR);
return FALSE;
}
Util_chomp(buf);
n = sscanf(buf, "%*s %d", &status);
if(n != 1 || (status >= 400)) {
LogError("Collector: message sending failed to %s -- %s\n",
C->url->url, buf);
return FALSE;
}
return TRUE;
}
syntax highlighted by Code2HTML, v. 0.9.1