fixed broken non-unicode build
[public/netxms.git] / src / agent / core / trap.cpp
1 /*
2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2013 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: trap.cpp
20 **
21 **/
22
23 #include "nxagentd.h"
24 #include <stdarg.h>
25
26 /**
27 * Static data
28 */
29 static Queue *s_trapQueue = NULL;
30 static UINT64 s_genTrapCount = 0; // Number of generated traps
31 static UINT64 s_sentTrapCount = 0; // Number of sent traps
32 static UINT64 s_trapIdBase = 0;
33 static VolatileCounter s_trapIdCounter = 0;
34 static time_t s_lastTrapTime = 0;
35
36 /**
37 * Trap sender
38 */
39 THREAD_RESULT THREAD_CALL TrapSender(void *pArg)
40 {
41 NXCP_MESSAGE *pMsg;
42 UINT32 i;
43 bool trapSent;
44
45 s_trapQueue = new Queue;
46 s_trapIdBase = (QWORD)time(NULL) << 32;
47 while(1)
48 {
49 pMsg = (NXCP_MESSAGE *)s_trapQueue->getOrBlock();
50 if (pMsg == INVALID_POINTER_VALUE)
51 break;
52
53 trapSent = false;
54
55 if (g_dwFlags & AF_SUBAGENT_LOADER)
56 {
57 trapSent = SendRawMessageToMasterAgent(pMsg);
58 }
59 else
60 {
61 MutexLock(g_hSessionListAccess);
62 for(i = 0; i < g_dwMaxSessions; i++)
63 if (g_pSessionList[i] != NULL)
64 if (g_pSessionList[i]->canAcceptTraps())
65 {
66 g_pSessionList[i]->sendRawMessage(pMsg);
67 trapSent = true;
68 }
69 MutexUnlock(g_hSessionListAccess);
70 }
71
72 if (trapSent)
73 {
74 free(pMsg);
75 s_sentTrapCount++;
76 }
77 else
78 {
79 s_trapQueue->insert(pMsg); // Re-queue trap
80 ThreadSleep(1);
81 }
82 }
83 delete s_trapQueue;
84 s_trapQueue = NULL;
85 DebugPrintf(INVALID_INDEX, 1, _T("Trap sender thread terminated"));
86 return THREAD_OK;
87 }
88
89 /**
90 * Shutdown trap sender
91 */
92 void ShutdownTrapSender()
93 {
94 s_trapQueue->setShutdownMode();
95 }
96
97 /**
98 * Send trap to server
99 */
100 void SendTrap(UINT32 dwEventCode, const TCHAR *eventName, int iNumArgs, TCHAR **ppArgList)
101 {
102 int i;
103 NXCPMessage msg;
104
105 DebugPrintf(INVALID_INDEX, 5, _T("SendTrap(): event_code=%d, event_name=%s, num_args=%d, arg[0]=\"%s\" arg[1]=\"%s\" arg[2]=\"%s\""),
106 dwEventCode, CHECK_NULL(eventName), iNumArgs,
107 (iNumArgs > 0) ? ppArgList[0] : _T("(null)"),
108 (iNumArgs > 1) ? ppArgList[1] : _T("(null)"),
109 (iNumArgs > 2) ? ppArgList[2] : _T("(null)"));
110
111 msg.setCode(CMD_TRAP);
112 msg.setId(0);
113 msg.setField(VID_TRAP_ID, s_trapIdBase | (UINT64)InterlockedIncrement(&s_trapIdCounter));
114 msg.setField(VID_EVENT_CODE, dwEventCode);
115 if (eventName != NULL)
116 msg.setField(VID_EVENT_NAME, eventName);
117 msg.setField(VID_NUM_ARGS, (WORD)iNumArgs);
118 for(i = 0; i < iNumArgs; i++)
119 msg.setField(VID_EVENT_ARG_BASE + i, ppArgList[i]);
120 if (s_trapQueue != NULL)
121 {
122 s_genTrapCount++;
123 s_lastTrapTime = time(NULL);
124 s_trapQueue->put(msg.createMessage());
125 }
126 }
127
128 /**
129 * Send trap - variant 2
130 * Arguments:
131 * dwEventCode - Event code
132 * eventName - event name; to send event by name, eventCode must be set to 0
133 * pszFormat - Parameter format string, each parameter represented by one character.
134 * The following format characters can be used:
135 * s - String
136 * m - Multibyte (non-UNICODE) string
137 * d - Decimal integer
138 * x - Hex integer
139 * a - IP address
140 * i - Object ID
141 * D - 64-bit decimal integer
142 * X - 64-bit hex integer
143 */
144 void SendTrap(UINT32 dwEventCode, const TCHAR *eventName, const char *pszFormat, va_list args)
145 {
146 int i, iNumArgs;
147 TCHAR *ppArgList[64];
148 static TCHAR badFormat[] = _T("BAD FORMAT");
149
150 iNumArgs = (pszFormat == NULL) ? 0 : (int)strlen(pszFormat);
151 for(i = 0; i < iNumArgs; i++)
152 {
153 switch(pszFormat[i])
154 {
155 case 's':
156 ppArgList[i] = va_arg(args, TCHAR *);
157 break;
158 case 'm':
159 #ifdef UNICODE
160 ppArgList[i] = WideStringFromMBString(va_arg(args, char *));
161 #else
162 ppArgList[i] = va_arg(args, char *);
163 #endif
164 break;
165 case 'd':
166 ppArgList[i] = (TCHAR *)malloc(16 * sizeof(TCHAR)); //
167 _sntprintf(ppArgList[i], 16, _T("%d"), va_arg(args, LONG)); //
168 break;
169 case 'D':
170 ppArgList[i] = (TCHAR *)malloc(32 * sizeof(TCHAR)); //
171 _sntprintf(ppArgList[i], 32, INT64_FMT, va_arg(args, INT64)); //
172 break;
173 case 'x':
174 case 'i':
175 ppArgList[i] = (TCHAR *)malloc(16 * sizeof(TCHAR)); //
176 _sntprintf(ppArgList[i], 16, _T("0x%08X"), va_arg(args, UINT32)); //
177 break;
178 case 'X':
179 ppArgList[i] = (TCHAR *)malloc(32 * sizeof(TCHAR));
180 _sntprintf(ppArgList[i], 32, UINT64X_FMT(_T("016")), va_arg(args, QWORD));
181 break;
182 case 'a':
183 ppArgList[i] = (TCHAR *)malloc(16 * sizeof(TCHAR));
184 IpToStr(va_arg(args, UINT32), ppArgList[i]);
185 break;
186 default:
187 ppArgList[i] = badFormat;
188 break;
189 }
190 }
191
192 SendTrap(dwEventCode, eventName, iNumArgs, ppArgList);
193
194 for(i = 0; i < iNumArgs; i++)
195 if ((pszFormat[i] == 'd') || (pszFormat[i] == 'x') ||
196 (pszFormat[i] == 'D') || (pszFormat[i] == 'X') ||
197 (pszFormat[i] == 'i') || (pszFormat[i] == 'a')
198 #ifdef UNICODE
199 || (pszFormat[i] == 'm')
200 #endif
201 )
202 free(ppArgList[i]);
203
204 }
205
206 /**
207 * Send trap - variant 3
208 * Same as variant 2, but uses argument list instead of va_list
209 */
210 void SendTrap(UINT32 dwEventCode, const TCHAR *eventName, const char *pszFormat, ...)
211 {
212 va_list args;
213
214 va_start(args, pszFormat);
215 SendTrap(dwEventCode, eventName, pszFormat, args);
216 va_end(args);
217
218 }
219
220 /**
221 * Forward trap from external subagent to server
222 */
223 void ForwardTrap(NXCPMessage *msg)
224 {
225 msg->setField(VID_TRAP_ID, s_trapIdBase | (UINT64)InterlockedIncrement(&s_trapIdCounter));
226 if (s_trapQueue != NULL)
227 {
228 s_genTrapCount++;
229 s_lastTrapTime = time(NULL);
230 s_trapQueue->put(msg->createMessage());
231 }
232 }
233
234 /**
235 * Handler for trap statistic DCIs
236 */
237 LONG H_AgentTraps(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
238 {
239 switch(arg[0])
240 {
241 case 'G':
242 ret_uint64(value, s_genTrapCount);
243 break;
244 case 'S':
245 ret_uint64(value, s_sentTrapCount);
246 break;
247 case 'T':
248 ret_uint64(value, (QWORD)s_lastTrapTime);
249 break;
250 default:
251 return SYSINFO_RC_UNSUPPORTED;
252 }
253 return SYSINFO_RC_SUCCESS;
254 }