Minor changes
[public/netxms.git] / src / server / core / session.cpp
CommitLineData
21e4b6f0
VK
1/*
2** NetXMS - Network Management System
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 "nms_core.h"
24
25
26//
27// Client session class constructor
28//
29
30ClientSession::ClientSession(SOCKET hSocket)
31{
32 m_pSendQueue = new Queue;
33 m_pMessageQueue = new Queue;
34 m_hSocket = hSocket;
35 m_dwIndex = INVALID_INDEX;
36 m_iState = STATE_CONNECTED;
37 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
38}
39
40
41//
42// Destructor
43//
44
45ClientSession::~ClientSession()
46{
47 shutdown(m_hSocket, 2);
48 closesocket(m_hSocket);
49 delete m_pSendQueue;
50 delete m_pMessageQueue;
51 if (m_pMsgBuffer != NULL)
52 free(m_pMsgBuffer);
53}
54
55
56//
57// Print debug information
58//
59
60void ClientSession::DebugPrintf(char *szFormat, ...)
61{
62 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
63 {
64 va_list args;
65
66 printf("*CSCP(%d)* ", m_dwIndex);
67 va_start(args, szFormat);
68 vprintf(szFormat, args);
69 va_end(args);
70 }
71}
72
73
74//
75// Post message to send queue
76//
77
78void ClientSession::SendMessage(CSCPMessage *pMsg)
79{
80 m_pSendQueue->Put(pMsg->CreateMessage());
81}
82
83
84//
85// ReadThread()
86//
87
88void ClientSession::ReadThread(void)
89{
90 CSCP_MESSAGE *pRawMsg;
91 CSCPMessage *pMsg;
92 int iErr;
93
94 // Initialize raw message receiving function
95 RecvCSCPMessage(0, NULL, m_pMsgBuffer);
96
97 pRawMsg = (CSCP_MESSAGE *)malloc(65536);
98 while(1)
99 {
100 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer)) <= 0)
101 break;
102
103 // Check that actual received packet size is equal to encoded in packet
104 if (ntohs(pRawMsg->wSize) != iErr)
105 {
106 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohs(pRawMsg->wSize));
107 continue; // Bad packet, wait for next
108 }
109
110 // Create message object from raw message
111 pMsg = new CSCPMessage(pRawMsg);
112 m_pMessageQueue->Put(pMsg);
113 }
114 if (iErr < 0)
115 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
116 free(pRawMsg);
117
118 // Notify other threads to exit
119 m_pSendQueue->Put(NULL);
120}
121
122
123//
124// WriteThread()
125//
126
127void ClientSession::WriteThread(void)
128{
129 CSCP_MESSAGE *pMsg;
130
131 while(1)
132 {
133 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
134 if (pMsg == NULL) // Session termination indicator
135 break;
136
137 if (send(m_hSocket, (const char *)pMsg, ntohs(pMsg->wSize), 0) <= 0)
138 {
7968a52d 139 MemFree(pMsg);
21e4b6f0
VK
140 break;
141 }
7968a52d 142 MemFree(pMsg);
21e4b6f0
VK
143 }
144}
145
146
147//
148// Message processing thread
149//
150
151void ClientSession::ProcessingThread(void)
152{
153 CSCPMessage *pMsg, *pReply;
154
155 while(1)
156 {
157 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
158 if (pMsg == NULL) // Session termination indicator
159 break;
160
161 DebugPrintf("Received message with code %d\n", pMsg->GetCode());
162 if ((m_iState != STATE_AUTHENTICATED) && (pMsg->GetCode() != CMD_LOGIN))
163 {
164 delete pMsg;
165 continue;
166 }
167
168 switch(pMsg->GetCode())
169 {
170 case CMD_LOGIN:
171 if (m_iState != STATE_AUTHENTICATED)
172 {
a5f8dbb8
VK
173 char *pszLogin = pMsg->GetVariableStr(VID_LOGIN_NAME);
174 char *pszPassword = pMsg->GetVariableStr(VID_PASSWORD);
21e4b6f0
VK
175
176 if (AuthenticateUser(pszLogin, pszPassword, &m_dwUserId, &m_dwSystemAccess))
177 m_iState = STATE_AUTHENTICATED;
178
7968a52d
VK
179 MemFree(pszLogin);
180 MemFree(pszPassword);
21e4b6f0
VK
181
182 // Send reply
183 pReply = new CSCPMessage;
184 pReply->SetCode(CMD_LOGIN_RESP);
185 pReply->SetId(pMsg->GetId());
a5f8dbb8 186 pReply->SetVariable(VID_LOGIN_RESULT, (DWORD)(m_iState == STATE_AUTHENTICATED));
21e4b6f0
VK
187 SendMessage(pReply);
188 delete pReply;
189 }
190 else
191 {
192 }
193 break;
194 case CMD_GET_OBJECTS:
195 SendAllObjects();
196 break;
197 case CMD_GET_EVENTS:
198 SendAllEvents();
199 break;
200 case CMD_GET_CONFIG_VARLIST:
201 SendAllConfigVars();
202 break;
203 default:
204 break;
205 }
206 delete pMsg;
207 }
208}
209
210
211//
212// Send all objects to client
213//
214
215void ClientSession::SendAllObjects(void)
216{
217 DWORD i;
218 CSCPMessage msg;
219
220 // Prepare message
221 msg.SetCode(CMD_OBJECT);
222
223 // Send objects, one per message
224 ObjectsGlobalLock();
225 for(i = 0; i < g_dwIdIndexSize; i++)
226 {
227 g_pIndexById[i].pObject->CreateMessage(&msg);
228 SendMessage(&msg);
229 msg.DeleteAllVariables();
230 }
231 ObjectsGlobalUnlock();
232
233 // Send end of list notification
234 msg.SetCode(CMD_OBJECT_LIST_END);
235 SendMessage(&msg);
236}
237
238
239//
240// Send all events to client
241//
242
243void ClientSession::SendAllEvents(void)
244{
245 DWORD i, dwNumRecords;
246 CSCPMessage msg;
247 DB_RESULT hResult;
9c36ef66 248 NXC_EVENT event;
21e4b6f0
VK
249
250 // Prepare message
a5f8dbb8 251// msg.SetCode(CMD_EVENT);
21e4b6f0
VK
252
253 // Retrieve events from database
c4495b00 254 hResult = DBSelect(g_hCoreDB, "SELECT event_id,timestamp,source,severity,message FROM EventLog ORDER BY timestamp");
21e4b6f0
VK
255 if (hResult != NULL)
256 {
257 // Send events, one per message
9c36ef66 258 dwNumRecords = DBGetNumRows(hResult);
21e4b6f0
VK
259 for(i = 0; i < dwNumRecords; i++)
260 {
9c36ef66
VK
261 event.dwEventId = htonl(DBGetFieldULong(hResult, i, 0));
262 event.dwTimeStamp = htonl(DBGetFieldULong(hResult, i, 1));
263 event.dwSourceId = htonl(DBGetFieldULong(hResult, i, 2));
264 event.dwSeverity = htonl(DBGetFieldULong(hResult, i, 3));
265 strncpy(event.szMessage, DBGetField(hResult, i, 4), MAX_EVENT_MSG_LENGTH);
266 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), &event, NULL));
267 }
21e4b6f0
VK
268 }
269
270 // Send end of list notification
271 msg.SetCode(CMD_EVENT_LIST_END);
272 SendMessage(&msg);
273}
274
275
276//
277// Send all configuration variables to client
278//
279
280void ClientSession::SendAllConfigVars(void)
281{
282 DWORD i, dwNumRecords;
283 CSCPMessage msg;
284 DB_RESULT hResult;
285
286 // Check user rights
287 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_VIEW_CONFIG) == 0))
288 {
289 // Access denied
290 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 291 msg.SetVariable(VID_ERROR, (DWORD)1);
21e4b6f0
VK
292 SendMessage(&msg);
293 }
294 else
295 {
296 // Prepare message
297 msg.SetCode(CMD_CONFIG_VARIABLE);
298
299 // Retrieve configuration variables from database
300 hResult = DBSelect(g_hCoreDB, "SELECT name,value FROM config");
301 if (hResult != NULL)
302 {
303 // Send events, one per message
304 dwNumRecords = DBGetNumRows(hResult);
305 for(i = 0; i < dwNumRecords; i++)
306 {
a5f8dbb8
VK
307 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
308 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
21e4b6f0
VK
309 SendMessage(&msg);
310 msg.DeleteAllVariables();
311 }
312 }
313
314 // Send end of list notification
315 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 316 msg.SetVariable(VID_ERROR, (DWORD)0);
21e4b6f0
VK
317 SendMessage(&msg);
318 }
319}