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