4d1c37dba0fe8bdca85f22d0311068f5e15758a4
[fms.git] / src / nntp / nntplistener.cpp
1 #include "../../include/nntp/nntplistener.h"\r
2 #include "../../include/nntp/nntpconnection.h"\r
3 #include "../../include/option.h"\r
4 #include "../../include/logfile.h"\r
5 #include "../../include/global.h"\r
6 #include "../../include/stringfunctions.h"\r
7 \r
8 #ifdef _WIN32\r
9         #include <winsock2.h>\r
10         #include <ws2tcpip.h>\r
11 #else\r
12 \r
13 #endif\r
14 \r
15 #ifdef XMEM\r
16         #include <xmem.h>\r
17 #endif\r
18 \r
19 NNTPListener::NNTPListener()\r
20 {\r
21 \r
22 }\r
23 \r
24 NNTPListener::~NNTPListener()\r
25 {\r
26 \r
27 }\r
28 \r
29 void NNTPListener::run()\r
30 {\r
31         int rval;\r
32         struct fd_set readfs;\r
33         struct timeval tv;\r
34         std::vector<SOCKET>::iterator listeni;\r
35         SOCKET highsocket;\r
36 \r
37         StartListen();\r
38 \r
39         do\r
40         {\r
41                 // reset values\r
42                 highsocket=0;\r
43                 tv.tv_sec=1;\r
44                 tv.tv_usec=0;\r
45 \r
46                 // clear fd set\r
47                 FD_ZERO(&readfs);\r
48 \r
49                 // put all listen sockets on the fd set\r
50                 for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)\r
51                 {\r
52                         FD_SET((*listeni),&readfs);\r
53                         if((*listeni)>highsocket)\r
54                         {\r
55                                 highsocket=(*listeni);\r
56                         }\r
57                 }\r
58 \r
59                 // see if any connections are waiting\r
60                 rval=select(highsocket+1,&readfs,0,0,&tv);\r
61 \r
62                 // check for new connections\r
63                 if(rval>0)\r
64                 {\r
65                         for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)\r
66                         {\r
67                                 if(FD_ISSET((*listeni),&readfs))\r
68                                 {\r
69                                         SOCKET newsock;\r
70                                         struct sockaddr_storage addr;\r
71                                         int addrlen=sizeof(addr);\r
72                                         newsock=accept((*listeni),(struct sockaddr *)&addr,&addrlen);\r
73                                         LogFile::instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::run NNTP client connected");\r
74                                         m_connections.execute(new NNTPConnection(newsock));\r
75                                 }\r
76                         }\r
77                 }\r
78 \r
79         }while(!ZThread::Thread::interrupted() && m_listensockets.size()>0);\r
80 \r
81         // see if any threads are still running - just calling interrupt without check would cause assert in debug mode\r
82         if(m_connections.wait(1)==false)\r
83         {\r
84                 try\r
85                 {\r
86                         m_connections.interrupt();\r
87                 }\r
88                 catch(...)\r
89                 {\r
90                 }\r
91                 m_connections.wait();\r
92         }\r
93 \r
94 }\r
95 \r
96 void NNTPListener::StartListen()\r
97 {\r
98         \r
99         std::string bindaddresses;\r
100         std::vector<std::string> listenaddresses;\r
101         std::string nntpport;\r
102         if(Option::instance()->Get("NNTPListenPort",nntpport)==false)\r
103         {\r
104                 nntpport="1119";\r
105                 Option::instance()->Set("NNTPListenPort",nntpport);\r
106         }\r
107         if(Option::instance()->Get("NNTPBindAddresses",bindaddresses)==false)\r
108         {\r
109                 bindaddresses="127.0.0.1";\r
110                 Option::instance()->Set("NNTPBindAddresses",bindaddresses);\r
111         }\r
112         StringFunctions::Split(bindaddresses,",",listenaddresses);\r
113         \r
114         for(std::vector<std::string>::iterator i=listenaddresses.begin(); i!=listenaddresses.end(); i++)\r
115         {\r
116                 SOCKET sock;\r
117                 int rval;\r
118                 struct addrinfo hint,*result,*current;\r
119                 result=current=NULL;\r
120                 memset(&hint,0,sizeof(hint));\r
121                 hint.ai_socktype=SOCK_STREAM;\r
122                 hint.ai_protocol=IPPROTO_TCP;\r
123                 hint.ai_flags=AI_PASSIVE;\r
124                 \r
125                 rval=getaddrinfo((*i).c_str(),nntpport.c_str(),&hint,&result);\r
126                 if(rval==0)\r
127                 {\r
128                         for(current=result; current!=NULL; current=current->ai_next)\r
129                         {\r
130                                 sock=socket(current->ai_family,current->ai_socktype,current->ai_protocol);\r
131                                 if(sock!=INVALID_SOCKET)\r
132                                 {\r
133                                         if(bind(sock,current->ai_addr,current->ai_addrlen)==0)\r
134                                         {\r
135                                                 if(listen(sock,10)==0)\r
136                                                 {\r
137                                                         LogFile::instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::StartListen started listening at "+(*i)+":"+nntpport);\r
138                                                         m_listensockets.push_back(sock);\r
139                                                 }\r
140                                                 else\r
141                                                 {\r
142                                                         LogFile::instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket listen failed");\r
143                                                         #ifdef _WIN32\r
144                                                         closesocket(sock);\r
145                                                         #else\r
146                                                         close(sock);\r
147                                                         #endif\r
148                                                 }\r
149                                         }\r
150                                         else\r
151                                         {\r
152                                                 LogFile::instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket bind failed");\r
153                                                 #ifdef _WIN32\r
154                                                 closesocket(sock);\r
155                                                 #else\r
156                                                 close(sock);\r
157                                                 #endif\r
158                                         }\r
159                                 }\r
160                                 else\r
161                                 {\r
162                                         LogFile::instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen couldn't create socket");\r
163                                 }\r
164                         }\r
165                 }\r
166                 if(result)\r
167                 {\r
168                         freeaddrinfo(result);\r
169                 }\r
170         }\r
171         if(m_listensockets.size()==0)\r
172         {\r
173                 LogFile::instance()->WriteLog(LogFile::LOGLEVEL_FATAL,"NNTPListener::StartListen couldn't start listening on any sockets");\r
174         }\r
175 }\r