Server shared library
[public/netxms.git] / src / agent / core / session.cpp
CommitLineData
e9580fef
VK
1/*
2** NetXMS multiplatform core agent
3** Copyright (C) 2003, 2004 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** $module: session.cpp
20**
21**/
22
23#include "nxagentd.h"
24
25
0a147f4b
VK
26//
27// Constants
28//
29
30#define RAW_MSG_SIZE 262144
31
32
e9580fef
VK
33//
34// Client session class constructor
35//
36
37CommSession::CommSession(SOCKET hSocket, DWORD dwHostAddr)
38{
39 m_pSendQueue = new Queue;
40 m_pMessageQueue = new Queue;
41 m_hSocket = hSocket;
42 m_dwIndex = INVALID_INDEX;
43 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
44 m_hCondWriteThreadStopped = ConditionCreate(FALSE);
45 m_hCondProcessingThreadStopped = ConditionCreate(FALSE);
46 m_dwHostAddr = dwHostAddr;
7c205c0c 47 m_bIsAuthenticated = (g_dwFlags & AF_REQUIRE_AUTH) ? FALSE : TRUE;
e9580fef
VK
48}
49
50
51//
52// Destructor
53//
54
55CommSession::~CommSession()
56{
57 shutdown(m_hSocket, 2);
58 closesocket(m_hSocket);
59 delete m_pSendQueue;
60 delete m_pMessageQueue;
61 safe_free(m_pMsgBuffer);
62 ConditionDestroy(m_hCondWriteThreadStopped);
63 ConditionDestroy(m_hCondProcessingThreadStopped);
64}
0a147f4b
VK
65
66
67//
68// Reading thread
69//
70
71void CommSession::ReadThread(void)
72{
73 CSCP_MESSAGE *pRawMsg;
74 CSCPMessage *pMsg;
75 int iErr;
7c205c0c 76 char szBuffer[32];
0a147f4b
VK
77
78 // Initialize raw message receiving function
79 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
80
81 pRawMsg = (CSCP_MESSAGE *)malloc(RAW_MSG_SIZE);
82 while(1)
83 {
84 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, RAW_MSG_SIZE)) <= 0)
85 break;
86
87 // Check if message is too large
88 if (iErr == 1)
89 continue;
90
91 // Check that actual received packet size is equal to encoded in packet
92 if ((int)ntohl(pRawMsg->dwSize) != iErr)
93 {
94 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
95 continue; // Bad packet, wait for next
96 }
97
98 // Create message object from raw message
99 pMsg = new CSCPMessage(pRawMsg);
100 m_pMessageQueue->Put(pMsg);
101 }
102 if (iErr < 0)
103 WriteLog(MSG_SESSION_BROKEN, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
104 free(pRawMsg);
105
106 // Notify other threads to exit
107 m_pSendQueue->Put(INVALID_POINTER_VALUE);
108 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
109
110 // Wait for other threads to finish
111 ConditionWait(m_hCondWriteThreadStopped, INFINITE);
112 ConditionWait(m_hCondProcessingThreadStopped, INFINITE);
7c205c0c
VK
113
114 DebugPrintf("Session with %s closed", IpToStr(m_dwHostAddr, szBuffer));
0a147f4b
VK
115}
116
117
118//
119// Writing thread
120//
121
122void CommSession::WriteThread(void)
123{
124 CSCP_MESSAGE *pMsg;
125 char szBuffer[128];
126
127 while(1)
128 {
129 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
130 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
131 break;
132
133 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
134 if (send(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
135 {
136 MemFree(pMsg);
137 break;
138 }
139 MemFree(pMsg);
140 }
141 ConditionSet(m_hCondWriteThreadStopped);
142}
143
144
145//
146// Message processing thread
147//
148
149void CommSession::ProcessingThread(void)
150{
151 CSCPMessage *pMsg;
152 char szBuffer[128];
7c205c0c 153 CSCPMessage msg;
0a147f4b
VK
154
155 while(1)
156 {
157 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
158 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
159 break;
0a147f4b 160 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
7c205c0c
VK
161
162 // Prepare responce message
163 msg.SetCode(CMD_REQUEST_COMPLETED);
164 msg.SetId(pMsg->GetId());
165
166 // Check if authentication required
167 if ((!m_bIsAuthenticated) && (pMsg->GetCode() != CMD_AUTHENTICATE))
168 {
169 msg.SetVariable(VID_RCC, ERR_AUTH_REQUIRED);
170 }
171 else
172 {
173 switch(pMsg->GetCode())
174 {
175 case CMD_AUTHENTICATE:
176 Authenticate(pMsg, &msg);
177 break;
178 case CMD_GET_PARAMETER:
179 GetParameter(pMsg, &msg);
180 break;
181 case CMD_GET_LIST:
182 msg.SetVariable(VID_RCC, ERR_NOT_IMPLEMENTED);
183 break;
6c426e3a
VK
184 case CMD_KEEPALIVE:
185 msg.SetVariable(VID_RCC, ERR_SUCCESS);
186 break;
7c205c0c
VK
187 default:
188 msg.SetVariable(VID_RCC, ERR_UNKNOWN_COMMAND);
189 break;
190 }
191 }
0a147f4b 192 delete pMsg;
7c205c0c
VK
193
194 // Send responce
195 SendMessage(&msg);
196 msg.DeleteAllVariables();
0a147f4b
VK
197 }
198 ConditionSet(m_hCondProcessingThreadStopped);
199}
7c205c0c
VK
200
201
202//
203// Authenticate peer
204//
205
206void CommSession::Authenticate(CSCPMessage *pRequest, CSCPMessage *pMsg)
207{
208 if (m_bIsAuthenticated)
209 {
210 // Already authenticated
211 pMsg->SetVariable(VID_RCC, (g_dwFlags & AF_REQUIRE_AUTH) ? ERR_ALREADY_AUTHENTICATED : ERR_AUTH_NOT_REQUIRED);
212 }
213 else
214 {
215 char szSecret[MAX_SECRET_LENGTH];
216 WORD wAuthMethod;
217
218 wAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
219 switch(wAuthMethod)
220 {
221 case AUTH_PLAINTEXT:
222 pRequest->GetVariableStr(VID_SHARED_SECRET, szSecret, MAX_SECRET_LENGTH);
223 if (!strcmp(szSecret, g_szSharedSecret))
224 {
225 m_bIsAuthenticated = TRUE;
226 pMsg->SetVariable(VID_RCC, ERR_SUCCESS);
227 }
228 else
229 {
230 WriteLog(MSG_AUTH_FAILED, EVENTLOG_WARNING_TYPE, "as", m_dwHostAddr, "PLAIN");
231 pMsg->SetVariable(VID_RCC, ERR_AUTH_FAILED);
232 }
233 break;
234 default:
235 pMsg->SetVariable(VID_RCC, ERR_NOT_IMPLEMENTED);
236 break;
237 }
238 }
239}
240
241
242//
243// Get parameter's value
244//
245
246void CommSession::GetParameter(CSCPMessage *pRequest, CSCPMessage *pMsg)
247{
248 char szParameter[MAX_PARAM_NAME], szValue[MAX_RESULT_LENGTH];
249 DWORD dwErrorCode;
250
251 pRequest->GetVariableStr(VID_PARAMETER, szParameter, MAX_PARAM_NAME);
252 dwErrorCode = GetParameterValue(szParameter, szValue);
253 pMsg->SetVariable(VID_RCC, dwErrorCode);
254 if (dwErrorCode == ERR_SUCCESS)
255 pMsg->SetVariable(VID_VALUE, szValue);
256}