3 ** Copyright (C) 2003-2013 Victor Kirhenshtein
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.
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.
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.
28 THREAD_RESULT THREAD_CALL
ListenerThread(void *)
30 SOCKET hSocket
, hClientSocket
;
31 struct sockaddr_in servAddr
;
32 int iNumErrors
= 0, nRet
;
39 if ((hSocket
= socket(AF_INET
, SOCK_STREAM
, 0)) == INVALID_SOCKET
)
41 nxlog_write(MSG_SOCKET_ERROR
, EVENTLOG_ERROR_TYPE
, "e", WSAGetLastError());
45 SetSocketExclusiveAddrUse(hSocket
);
46 SetSocketReuseFlag(hSocket
);
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("*")))
53 servAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
57 servAddr
.sin_addr
.s_addr
= InetAddress::resolveHostName(g_listenAddress
, AF_INET
).getAddressV4();
58 if (servAddr
.sin_addr
.s_addr
== htonl(INADDR_NONE
))
59 servAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
61 servAddr
.sin_port
= htons(g_listenPort
);
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)
67 nxlog_write(MSG_BIND_ERROR
, EVENTLOG_ERROR_TYPE
, "e", WSAGetLastError());
72 listen(hSocket
, SOMAXCONN
);
73 nxlog_write(MSG_LISTENING
, EVENTLOG_INFORMATION_TYPE
, "ad", ntohl(servAddr
.sin_addr
.s_addr
), g_listenPort
);
75 // Wait for connection requests
76 while(!(g_flags
& AF_SHUTDOWN
))
81 FD_SET(hSocket
, &rdfs
);
82 nRet
= select(SELECT_NFDS(hSocket
+ 1), &rdfs
, NULL
, NULL
, &tv
);
83 if ((nRet
> 0) && (!(g_flags
& AF_SHUTDOWN
)))
85 iSize
= sizeof(struct sockaddr_in
);
86 if ((hClientSocket
= accept(hSocket
, (struct sockaddr
*)&servAddr
, &iSize
)) == -1)
88 int error
= WSAGetLastError();
90 if (error
!= WSAEINTR
)
91 nxlog_write(MSG_ACCEPT_ERROR
, EVENTLOG_ERROR_TYPE
, "e", error
);
93 if (iNumErrors
> 1000)
95 nxlog_write(MSG_TOO_MANY_ERRORS
, EVENTLOG_WARNING_TYPE
, NULL
);
102 iNumErrors
= 0; // Reset consecutive errors counter
103 DebugPrintf(5, _T("Incoming connection from %s"), IpToStr(ntohl(servAddr
.sin_addr
.s_addr
), szBuffer
));
105 SetSocketNonBlocking(hClientSocket
);
107 ProxySession
*session
= new ProxySession(hClientSocket
);
112 int error
= WSAGetLastError();
114 // On AIX, select() returns ENOENT after SIGINT for unknown reason
116 if (error
!= WSAEINTR
)
118 if ((error
!= EINTR
) && (error
!= ENOENT
))
121 nxlog_write(MSG_SELECT_ERROR
, EVENTLOG_ERROR_TYPE
, "e", error
);
127 closesocket(hSocket
);
128 DebugPrintf(1, _T("Listener thread terminated"));