NamedPipe class splitted into NAmedPipe and NamedPipeListener; nxapush switched to...
[public/netxms.git] / src / agent / core / master.cpp
1 /*
2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2017 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: master.cpp
20 **
21 **/
22
23 #include "nxagentd.h"
24
25 /**
26 * Restart agent
27 */
28 LONG RestartAgent();
29
30 /**
31 * Handler for CMD_GET_PARAMETER command
32 */
33 static void H_GetParameter(NXCPMessage *pRequest, NXCPMessage *pMsg)
34 {
35 TCHAR name[MAX_PARAM_NAME];
36 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
37
38 TCHAR value[MAX_RESULT_LENGTH];
39 VirtualSession session(0);
40 UINT32 rcc = GetParameterValue(name, value, &session);
41 pMsg->setField(VID_RCC, rcc);
42 if (rcc == ERR_SUCCESS)
43 pMsg->setField(VID_VALUE, value);
44 }
45
46 /**
47 * Handler for CMD_GET_TABLE command
48 */
49 static void H_GetTable(NXCPMessage *pRequest, NXCPMessage *pMsg)
50 {
51 TCHAR name[MAX_PARAM_NAME];
52 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
53
54 Table value;
55 VirtualSession session(0);
56 UINT32 rcc = GetTableValue(name, &value, &session);
57 pMsg->setField(VID_RCC, rcc);
58 if (rcc == ERR_SUCCESS)
59 value.fillMessage(*pMsg, 0, -1);
60 }
61
62 /**
63 * Handler for CMD_GET_LIST command
64 */
65 static void H_GetList(NXCPMessage *pRequest, NXCPMessage *pMsg)
66 {
67 TCHAR name[MAX_PARAM_NAME];
68 pRequest->getFieldAsString(VID_PARAMETER, name, MAX_PARAM_NAME);
69
70 StringList value;
71 VirtualSession session(0);
72 UINT32 rcc = GetListValue(name, &value, &session);
73 pMsg->setField(VID_RCC, rcc);
74 if (rcc == ERR_SUCCESS)
75 {
76 pMsg->setField(VID_NUM_STRINGS, (UINT32)value.size());
77 for(int i = 0; i < value.size(); i++)
78 pMsg->setField(VID_ENUM_VALUE_BASE + i, value.get(i));
79 }
80 }
81
82 /**
83 * Pipe to master agent
84 */
85 static NamedPipe *s_pipe = NULL;
86
87 /**
88 * Listener thread for master agent commands
89 */
90 THREAD_RESULT THREAD_CALL MasterAgentListener(void *arg)
91 {
92 while(!(g_dwFlags & AF_SHUTDOWN))
93 {
94 TCHAR pipeName[MAX_PATH];
95 _sntprintf(pipeName, MAX_PIPE_NAME_LEN, _T("nxagentd.subagent.%s"), g_masterAgent);
96 s_pipe = NamedPipe::connect(pipeName, 5000);
97
98 if (s_pipe != NULL)
99 {
100 AgentWriteDebugLog(1, _T("Connected to master agent"));
101
102 PipeMessageReceiver receiver(s_pipe->handle(), 8192, 1048576); // 8K initial, 1M max
103 while(!(g_dwFlags & AF_SHUTDOWN))
104 {
105 MessageReceiverResult result;
106 NXCPMessage *msg = receiver.readMessage(INFINITE, &result);
107 if ((msg == NULL) || (g_dwFlags & AF_SHUTDOWN))
108 {
109 AgentWriteDebugLog(6, _T("MasterAgentListener: receiver failure (%s)"), AbstractMessageReceiver::resultToText(result));
110 break;
111 }
112
113 TCHAR buffer[256];
114 AgentWriteDebugLog(6, _T("Received message %s from master agent"), NXCPMessageCodeName(msg->getCode(), buffer));
115
116 NXCPMessage response;
117 response.setCode(CMD_REQUEST_COMPLETED);
118 response.setId(msg->getId());
119 switch(msg->getCode())
120 {
121 case CMD_GET_PARAMETER:
122 H_GetParameter(msg, &response);
123 break;
124 case CMD_GET_TABLE:
125 H_GetTable(msg, &response);
126 break;
127 case CMD_GET_LIST:
128 H_GetList(msg, &response);
129 break;
130 case CMD_GET_PARAMETER_LIST:
131 response.setField(VID_RCC, ERR_SUCCESS);
132 GetParameterList(&response);
133 break;
134 case CMD_GET_ENUM_LIST:
135 response.setField(VID_RCC, ERR_SUCCESS);
136 GetEnumList(&response);
137 break;
138 case CMD_GET_TABLE_LIST:
139 response.setField(VID_RCC, ERR_SUCCESS);
140 GetTableList(&response);
141 break;
142 case CMD_SHUTDOWN:
143 Shutdown();
144 ThreadSleep(10);
145 exit(0);
146 break;
147 case CMD_RESTART:
148 RestartAgent();
149 ThreadSleep(10);
150 exit(0);
151 break;
152 default:
153 response.setField(VID_RCC, ERR_UNKNOWN_COMMAND);
154 break;
155 }
156 delete msg;
157
158 // Send response to pipe
159 NXCP_MESSAGE *rawMsg = response.createMessage();
160 bool sendSuccess = s_pipe->write(rawMsg, ntohl(rawMsg->size));
161 free(rawMsg);
162 if (!sendSuccess)
163 break;
164 }
165 delete_and_null(s_pipe);
166 AgentWriteDebugLog(1, _T("Disconnected from master agent"));
167 }
168 else
169 {
170 AgentWriteDebugLog(1, _T("Cannot connect to master agent, will retry in 5 seconds"));
171 ThreadSleep(5);
172 }
173 }
174 AgentWriteDebugLog(1, _T("Master agent listener stopped"));
175 return THREAD_OK;
176 }
177
178 /**
179 * Send message to master agent
180 */
181 bool SendMessageToMasterAgent(NXCPMessage *msg)
182 {
183 NXCP_MESSAGE *rawMsg = msg->createMessage();
184 bool success = SendRawMessageToMasterAgent(rawMsg);
185 free(rawMsg);
186 return success;
187 }
188
189 /**
190 * Send raw message to master agent
191 */
192 bool SendRawMessageToMasterAgent(NXCP_MESSAGE *msg)
193 {
194 if (s_pipe == NULL)
195 return false;
196 return s_pipe->write(msg, ntohl(msg->size));
197 }