source: nscp/modules/NSCAAgent/NSCAThread.cpp @ 5aebda1

0.4.00.4.10.4.2stable
Last change on this file since 5aebda1 was 5aebda1, checked in by Michael Medin <michael@…>, 5 years ago

+ Added host-lookupos for NSCA server

+ Added option (cache_hostname=1|0) to cache the NSCA host name (Ie. only lookup once)

  • Property mode set to 100644
File size: 7.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////
2// PDH Collector
3//
4// Functions from this file collects data from the PDH subsystem and stores
5// it for later use
6// *NOTICE* that this is done in a separate thread so threading issues has
7// to be handled. I handle threading issues in the CounterListener's get/
8// set accessors.
9//
10// Copyright (c) 2004 MySolutions NORDIC (http://www.medin.nu)
11//
12// Date: 2004-03-13
13// Author: Michael Medin - <michael@medin.name>
14//
15// This software is provided "AS IS", without a warranty of any kind.
16// You are free to use/modify this code but leave this header intact.
17//
18//////////////////////////////////////////////////////////////////////////
19
20#include "stdafx.h"
21#include "NSCAThread.h"
22#include <Settings.h>
23
24
25NSCAThread::NSCAThread() : hStopEvent_(NULL) {
26        checkIntervall_ = NSCModuleHelper::getSettingsInt(NSCA_AGENT_SECTION_TITLE, NSCA_INTERVAL, NSCA_INTERVAL_DEFAULT);
27        hostname_ = NSCModuleHelper::getSettingsString(NSCA_AGENT_SECTION_TITLE, NSCA_HOSTNAME, NSCA_HOSTNAME_DEFAULT);
28        nscahost_ = NSCModuleHelper::getSettingsString(NSCA_AGENT_SECTION_TITLE, NSCA_SERVER, NSCA_SERVER_DEFAULT);
29        nscaport_ = NSCModuleHelper::getSettingsInt(NSCA_AGENT_SECTION_TITLE, NSCA_PORT, NSCA_PORT_DEFAULT);
30        encryption_method_ = NSCModuleHelper::getSettingsInt(NSCA_AGENT_SECTION_TITLE, NSCA_ENCRYPTION, NSCA_ENCRYPTION_DEFAULT);
31        password_ = strEx::wstring_to_string(NSCModuleHelper::getSettingsString(NSCA_AGENT_SECTION_TITLE, NSCA_PASSWORD, NSCA_PASSWORD_DEFAULT));
32        cacheNscaHost_ = NSCModuleHelper::getSettingsInt(NSCA_AGENT_SECTION_TITLE, NSCA_CACHE_HOST, NSCA_CACHE_HOST_DEFAULT) == 1;
33        std::list<std::wstring> items = NSCModuleHelper::getSettingsSection(NSCA_CMD_SECTION_TITLE);
34        for (std::list<std::wstring>::const_iterator cit = items.begin(); cit != items.end(); ++cit) {
35                addCommand(*cit);
36        }
37        if (hostname_.empty()) {
38                TCHAR *buf = new TCHAR[MAX_COMPUTERNAME_LENGTH + 2];
39                DWORD size = MAX_COMPUTERNAME_LENGTH+1;
40                if (!GetComputerName(buf, &size)) {
41                        NSC_LOG_ERROR(_T("Failed to get computer name: setting it to <unknown>"));
42                        hostname_ = _T("<unknown>");
43                } else {
44                        buf[size] = 0;
45                        hostname_ = buf;
46                        NSC_DEBUG_MSG_STD(_T("Autodetected hostname: ") + hostname_);
47                }
48                delete[] buf;
49        }
50}
51
52NSCAThread::~NSCAThread()
53{
54        if (hStopEvent_)
55                CloseHandle(hStopEvent_);
56}
57Command::Result Command::execute(std::wstring host) const {
58        Result result(host);
59        std::wstring msg;
60        std::wstring perf;
61        NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectCommand(cmd_.c_str(), args_.getLen(), args_.get(), msg, perf);
62        result.service = alias_;
63        if (ret == NSCAPI::returnIgnored) {
64                result.result = _T("Command was not found: ") + cmd_;
65                result.code = NSCAPI::returnUNKNOWN;
66        } else if (ret == NSCAPI::returnInvalidBufferLen) {
67                result.result = _T("Result was to long: ") + cmd_;
68                result.code = NSCAPI::returnUNKNOWN;
69        } else {
70                result.result = msg + _T("|") + perf;
71                result.code = conv_code(ret);
72                if (result.result.length() >= NSCA_MAX_PLUGINOUTPUT_LENGTH) {
73                        NSC_LOG_ERROR(_T("NSCA return data truncated"));
74                        result.result = result.result.substr(0, NSCA_MAX_PLUGINOUTPUT_LENGTH-1);
75                }
76        }
77        return result;
78}
79
80
81void NSCAThread::addCommand(std::wstring key) {
82        std::wstring value = NSCModuleHelper::getSettingsString(NSCA_CMD_SECTION_TITLE, key, _T(""));
83        if ((key.length() > 4) && (key.substr(0,4) == _T("host")))
84                commands_.push_back(Command(_T(""), value));
85        else
86                commands_.push_back(Command(key, value));
87}
88
89
90/**
91* Thread that collects the data every "CHECK_INTERVAL" seconds.
92*
93* @param lpParameter Not used
94* @return thread exit status
95*
96* @author mickem
97*
98* @date 03-13-2004               
99*
100* @bug If we have "custom named" counters ?
101* @bug This whole concept needs work I think.
102*
103*/
104DWORD NSCAThread::threadProc(LPVOID lpParameter) {
105        hStopEvent_ = CreateEvent(NULL, TRUE, FALSE, NULL);
106        if (!hStopEvent_) {
107                NSC_LOG_ERROR_STD(_T("Create StopEvent failed: ") + error::lookup::last_error());
108                return 0;
109        }
110
111        srand( reinterpret_cast<int>(lpParameter) );
112
113        DWORD waitStatus = 0;
114        int drift = (checkIntervall_*rand())/RAND_MAX ;
115        NSC_DEBUG_MSG_STD(_T("Drifting: ") + strEx::itos(drift));
116        waitStatus = WaitForSingleObject(hStopEvent_, drift*1000);
117        if (waitStatus != WAIT_TIMEOUT)  {
118                NSC_LOG_ERROR_STD(_T("Drift failed... strange..."));
119        }
120        int remain = checkIntervall_;
121        while (((waitStatus = WaitForSingleObject(hStopEvent_, remain*1000)) == WAIT_TIMEOUT)) {
122                MutexLock mutex(mutexHandler);
123                if (!mutex.hasMutex())
124                        NSC_LOG_ERROR(_T("Failed to get Mutex!"));
125                else {
126                        __int64 start, stop;
127                        _time64( &start );
128
129                        std::list<Command::Result> results;
130                        for (std::list<Command>::const_iterator cit = commands_.begin(); cit != commands_.end(); ++cit) {
131                                results.push_back((*cit).execute(hostname_));
132                        }
133                        send(results);
134                        _time64( &stop );
135                        __int64 elapsed = stop-start;
136                        remain = checkIntervall_-static_cast<int>(elapsed);
137                        if (remain < 0)
138                                remain = 0;
139                }
140        }
141
142        if (waitStatus != WAIT_OBJECT_0) {
143                NSC_LOG_ERROR(_T("Something odd happened, terminating NSCA submission thread!"));
144        }
145
146        {
147                MutexLock mutex(mutexHandler);
148                if (!mutex.hasMutex()) {
149                        NSC_LOG_ERROR(_T("Failed to get Mute when closing thread!"));
150                }
151
152                if (!CloseHandle(hStopEvent_)) {
153                        NSC_LOG_ERROR_STD(_T("Failed to close stopEvent handle: ") + error::lookup::last_error());
154                } else
155                        hStopEvent_ = NULL;
156        }
157        return 0;
158}
159void NSCAThread::send(const std::list<Command::Result> &results) {
160        try {
161                nsca_encrypt crypt_inst;
162                simpleSocket::Socket socket(true);
163                simpleSocket::DataBuffer inc;
164                if (!cacheNscaHost_ || nscaaddr_.empty()) {
165                        nscaaddr_ = socket.getHostByName(nscahost_);
166                        NSC_DEBUG_MSG_STD(_T("Looked up ") + nscahost_ + _T(" to ") + nscaaddr_);
167                }
168                if (nscaaddr_.empty()) {
169                        NSC_LOG_ERROR_STD(_T("Failed to lookup host: ") + nscahost_);
170                        return;
171                }
172                if (socket.connect(nscaaddr_, nscaport_) == SOCKET_ERROR) {
173                        NSC_LOG_ERROR_STD(_T("<<< Could not connect to: ") + nscaaddr_ + _T(":") + strEx::itos(nscaport_) + _T(" ") + socket.getLastError());
174                        return;
175                }
176                if (!socket.readAll(inc, sizeof(NSCAPacket::init_packet_struct), sizeof(NSCAPacket::init_packet_struct))) {
177                        NSC_LOG_ERROR_STD(_T("<<< Failed to read header from: ") + nscaaddr_ + _T(":") + strEx::itos(nscaport_) + _T(" ") + socket.getLastError());
178                        return;
179                }
180                NSCAPacket::init_packet_struct *packet_in = (NSCAPacket::init_packet_struct*) inc.getBuffer();
181                try {
182                        crypt_inst.encrypt_init(password_.c_str(),encryption_method_,reinterpret_cast<unsigned char*>(packet_in->iv));
183                } catch (nsca_encrypt::encryption_exception &e) {
184                        NSC_LOG_ERROR_STD(_T("<<< Failed to initalize encryption header: ") + e.getMessage());
185                        return;
186                } catch (...) {
187                        NSC_LOG_ERROR_STD(_T("<<< Failed to initalize encryption header!"));
188                        return;
189                }
190
191                try {
192                        for (std::list<Command::Result>::const_iterator cit = results.begin(); cit != results.end(); ++cit) {
193                                try {
194                                        socket.send((*cit).getBuffer(crypt_inst));
195                                } catch (NSCAPacket::NSCAException &e) {
196                                        NSC_LOG_ERROR_STD(_T("Failed to make command: ") + e.getMessage() );
197                                }
198                        }
199                } catch (nsca_encrypt::encryption_exception &e) {
200                        NSC_LOG_ERROR_STD(_T("<<< Failed to encrypt packet: ") + e.getMessage());
201                        return;
202                } catch (...) {
203                        NSC_LOG_ERROR_STD(_T("<<< Failed to encrypt packet!"));
204                        return;
205                }
206                socket.close();
207        } catch (...) {
208                NSC_LOG_ERROR_STD(_T("<<< Failed to initalize encryption header!"));
209                return;
210        }
211}
212
213
214
215/**
216* Request termination of the thread (waiting for thread termination is not handled)
217*/
218void NSCAThread::exitThread(void) {
219        if (hStopEvent_ == NULL) {
220                NSC_LOG_ERROR(_T("Stop event is not created!"));
221        } else {
222                if (!SetEvent(hStopEvent_)) {
223                        NSC_LOG_ERROR_STD(_T("SetStopEvent failed"));
224                }
225        }
226}
Note: See TracBrowser for help on using the repository browser.