+ sockets reuse (*nix only)
[public/netxms.git] / src / server / core / admin.cpp
CommitLineData
9f881a19
AK
1/* $Id: admin.cpp,v 1.6 2005-01-18 15:51:42 alk Exp $ */
2
3e4e127f
VK
3/*
4** NetXMS - Network Management System
5** Copyright (C) 2003, 2004 Victor Kirhenshtein
6**
7** This program is free software; you can redistribute it and/or modify
8** it under the terms of the GNU General Public License as published by
9** the Free Software Foundation; either version 2 of the License, or
10** (at your option) any later version.
11**
12** This program is distributed in the hope that it will be useful,
13** but WITHOUT ANY WARRANTY; without even the implied warranty of
14** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15** GNU General Public License for more details.
16**
17** You should have received a copy of the GNU General Public License
18** along with this program; if not, write to the Free Software
19** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20**
21** $module: admin.cpp
22**
23**/
24
a551fe4d 25#include "nxcore.h"
3e4e127f
VK
26#include <local_admin.h>
27
28
29//
30// Send success or error notification
31//
32
33#define SEND_ERROR() \
34 { \
35 wCmd = LA_RESP_ERROR; \
36 send(sock, (char *)&wCmd, sizeof(WORD), 0); \
37 }
38#define SEND_SUCCESS() \
39 { \
40 wCmd = LA_RESP_SUCCESS; \
41 send(sock, (char *)&wCmd, sizeof(WORD), 0); \
42 }
43
44
45
46//
47// Receive string from client
48//
49
50static BOOL RecvString(SOCKET sock, char *pBuffer, int iBufSize)
51{
52 int iError;
53 WORD wSize = 0;
54
55 // Receive string length
56 iError = recv(sock, (char *)&wSize, 2, 0);
57 if ((iError != 2) || (wSize > iBufSize - 1))
58 return FALSE;
59
60 iError = recv(sock, pBuffer, wSize, 0);
61 if (iError != wSize)
62 return FALSE;
63 pBuffer[iError] = 0;
64 return TRUE;
65}
66
67
68//
69// Send string to client
70//
71
72static BOOL SendString(SOCKET sock, char *szString)
73{
74 WORD wLen;
75
76 wLen = strlen(szString);
77 if (send(sock, (char *)&wLen, sizeof(WORD), 0) != 2)
78 return FALSE;
79
80 return send(sock, szString, wLen, 0) == wLen;
81}
82
83
84//
85// Request processing thread
86//
87
ccdbbb52 88static THREAD_RESULT THREAD_CALL ProcessingThread(void *pArg)
3e4e127f
VK
89{
90 SOCKET sock = (SOCKET)pArg;
91 WORD wCmd;
92 int iError;
93 char szBuffer[256];
94 DWORD dwTemp;
95
96 while(1)
97 {
98 iError = recv(sock, (char *)&wCmd, sizeof(WORD), 0);
99 if (iError != 2)
100 break; // Communication error or closed connection
101
102 switch(wCmd)
103 {
104 case LA_CMD_LIST_CONFIG:
105 SEND_ERROR();
106 break;
107 case LA_CMD_GET_CONFIG:
108 // Receive variable name
109 if (RecvString(sock, szBuffer, 256))
110 {
111 char szValue[256];
112
113 if (ConfigReadStr(szBuffer, szValue, 255, ""))
114 SendString(sock, szValue);
115 else
116 SEND_ERROR();
117 }
118 else
119 {
120 goto close_connection;
121 }
122 break;
123 case LA_CMD_SET_CONFIG:
124 // Receive variable name
125 if (RecvString(sock, szBuffer, 256))
126 {
127 char szValue[256];
128
129 // Receive new value
130 if (RecvString(sock, szValue, 256))
131 {
132 if (ConfigWriteStr(szBuffer, szValue, TRUE))
133 {
134 SEND_SUCCESS();
135 }
136 else
137 {
138 SEND_ERROR();
139 }
140 }
141 else
142 {
143 goto close_connection;
144 }
145 }
146 else
147 {
148 goto close_connection;
149 }
150 break;
151 case LA_CMD_GET_FLAGS:
152 // Send value of application flags
153 send(sock, (char *)&g_dwFlags, sizeof(DWORD), 0);
154 break;
155 case LA_CMD_SET_FLAGS:
156 iError = recv(sock, (char *)&dwTemp, sizeof(DWORD), 0);
157 if (iError == sizeof(DWORD))
158 {
159 dwTemp &= ~AF_STANDALONE; // Standalone flag shouldn't be changed
160 g_dwFlags = dwTemp | (g_dwFlags & AF_STANDALONE);
161 SEND_SUCCESS();
162 }
163 else
164 {
165 goto close_connection;
166 }
167 break;
168 default:
169 break;
170 }
171 }
172
173close_connection:
174 shutdown(sock, 2);
175 closesocket(sock);
ccdbbb52 176 return THREAD_OK;
3e4e127f
VK
177}
178
179
180//
181// Local administrative interface listener thread
182//
183
ccdbbb52 184THREAD_RESULT THREAD_CALL LocalAdminListener(void *pArg)
3e4e127f
VK
185{
186 SOCKET sock, sockClient;
187 struct sockaddr_in servAddr;
b7271ccb
VK
188 int errorCount = 0;
189 socklen_t iSize;
3e4e127f
VK
190
191 // Create socket
192 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
193 {
194 WriteLog(MSG_SOCKET_FAILED, EVENTLOG_ERROR_TYPE, "s", "LocalAdminListener");
ccdbbb52 195 return THREAD_OK;
3e4e127f
VK
196 }
197
9f881a19
AK
198 SetSocketReuseFlag(sock);
199
3e4e127f
VK
200 // Fill in local address structure
201 memset(&servAddr, 0, sizeof(struct sockaddr_in));
202 servAddr.sin_family = AF_INET;
203 servAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
204 servAddr.sin_port = htons(LOCAL_ADMIN_PORT);
205
206 // Bind socket
207 if (bind(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) != 0)
208 {
209 WriteLog(MSG_BIND_ERROR, EVENTLOG_ERROR_TYPE, "dse", LOCAL_ADMIN_PORT, "LocalAdminListener", WSAGetLastError());
37c4d6aa
VK
210 closesocket(sock);
211 /* TODO: we should initiate shutdown from here */
212 return THREAD_OK;
3e4e127f
VK
213 }
214
215 // Set up queue
216 listen(sock, SOMAXCONN);
217
218 // Wait for connection requests
219 while(!ShutdownInProgress())
220 {
221 iSize = sizeof(struct sockaddr_in);
222 if ((sockClient = accept(sock, (struct sockaddr *)&servAddr, &iSize)) == -1)
223 {
224 int error;
225
226#ifdef _WIN32
227 error = WSAGetLastError();
228 if (error != WSAEINTR)
229#else
230 error = errno;
231 if (error != EINTR)
232#endif
233 WriteLog(MSG_ACCEPT_ERROR, EVENTLOG_ERROR_TYPE, "e", error);
234 errorCount++;
235 if (errorCount > 1000)
236 {
237 WriteLog(MSG_TOO_MANY_ACCEPT_ERRORS, EVENTLOG_WARNING_TYPE, NULL);
238 errorCount = 0;
239 }
240 ThreadSleepMs(500);
241 }
242
243 errorCount = 0; // Reset consecutive errors counter
244
245 // Create new session structure and threads
246 ThreadCreate(ProcessingThread, 0, (void *)sockClient);
247 }
248
249 closesocket(sock);
ccdbbb52 250 return THREAD_OK;
3e4e127f 251}
9f881a19
AK
252
253///////////////////////////////////////////////////////////////////////////////
254/*
255
256$Log: not supported by cvs2svn $
257
258*/