fixed Windows build errors
[public/netxms.git] / src / nxcproxy / listener.cpp
CommitLineData
1a93e64a
VK
1/*
2** NetXMS client proxy
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: listener.cpp
20**
21**/
22
23#include "nxcproxy.h"
24
25/**
26 * Listener thread
27 */
28THREAD_RESULT THREAD_CALL ListenerThread(void *)
29{
30 SOCKET hSocket, hClientSocket;
31 struct sockaddr_in servAddr;
32 int iNumErrors = 0, nRet;
33 socklen_t iSize;
34 TCHAR szBuffer[256];
35 struct timeval tv;
36 fd_set rdfs;
37
38 // Create socket
39 if ((hSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
40 {
41 nxlog_write(MSG_SOCKET_ERROR, EVENTLOG_ERROR_TYPE, "e", WSAGetLastError());
42 exit(1);
43 }
44
45 SetSocketExclusiveAddrUse(hSocket);
46 SetSocketReuseFlag(hSocket);
47
48 // Fill in local address structure
49 memset(&servAddr, 0, sizeof(struct sockaddr_in));
50 servAddr.sin_family = AF_INET;
51 if (!_tcscmp(g_listenAddress, _T("*")))
52 {
53 servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
54 }
55 else
56 {
688b5dc2 57 servAddr.sin_addr.s_addr = InetAddress::resolveHostName(g_listenAddress, AF_INET).getAddressV4();
1a93e64a
VK
58 if (servAddr.sin_addr.s_addr == htonl(INADDR_NONE))
59 servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
60 }
61 servAddr.sin_port = htons(g_listenPort);
62
63 // Bind socket
64 DebugPrintf(1, _T("Trying to bind on %s:%d"), IpToStr(ntohl(servAddr.sin_addr.s_addr), szBuffer), ntohs(servAddr.sin_port));
65 if (bind(hSocket, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) != 0)
66 {
67 nxlog_write(MSG_BIND_ERROR, EVENTLOG_ERROR_TYPE, "e", WSAGetLastError());
68 exit(1);
69 }
70
71 // Set up queue
72 listen(hSocket, SOMAXCONN);
73 nxlog_write(MSG_LISTENING, EVENTLOG_INFORMATION_TYPE, "ad", ntohl(servAddr.sin_addr.s_addr), g_listenPort);
74
75 // Wait for connection requests
76 while(!(g_flags & AF_SHUTDOWN))
77 {
78 tv.tv_sec = 1;
79 tv.tv_usec = 0;
80 FD_ZERO(&rdfs);
81 FD_SET(hSocket, &rdfs);
82 nRet = select(SELECT_NFDS(hSocket + 1), &rdfs, NULL, NULL, &tv);
83 if ((nRet > 0) && (!(g_flags & AF_SHUTDOWN)))
84 {
85 iSize = sizeof(struct sockaddr_in);
86 if ((hClientSocket = accept(hSocket, (struct sockaddr *)&servAddr, &iSize)) == -1)
87 {
88 int error = WSAGetLastError();
89
90 if (error != WSAEINTR)
91 nxlog_write(MSG_ACCEPT_ERROR, EVENTLOG_ERROR_TYPE, "e", error);
92 iNumErrors++;
93 if (iNumErrors > 1000)
94 {
95 nxlog_write(MSG_TOO_MANY_ERRORS, EVENTLOG_WARNING_TYPE, NULL);
96 iNumErrors = 0;
97 }
98 ThreadSleepMs(500);
99 continue;
100 }
101
102 iNumErrors = 0; // Reset consecutive errors counter
103 DebugPrintf(5, _T("Incoming connection from %s"), IpToStr(ntohl(servAddr.sin_addr.s_addr), szBuffer));
104
105 SetSocketNonBlocking(hClientSocket);
106
107 ProxySession *session = new ProxySession(hClientSocket);
108 session->run();
109 }
110 else if (nRet == -1)
111 {
112 int error = WSAGetLastError();
113
114 // On AIX, select() returns ENOENT after SIGINT for unknown reason
115#ifdef _WIN32
116 if (error != WSAEINTR)
117#else
118 if ((error != EINTR) && (error != ENOENT))
119#endif
120 {
121 nxlog_write(MSG_SELECT_ERROR, EVENTLOG_ERROR_TYPE, "e", error);
122 ThreadSleepMs(100);
123 }
124 }
125 }
126
127 closesocket(hSocket);
128 DebugPrintf(1, _T("Listener thread terminated"));
129 return THREAD_OK;
130}