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
11 #include <winsock2.h>
\r
12 #include <ws2tcpip.h>
\r
14 #include <netinet/in.h> // gcc - IPPROTO_ consts
\r
15 #include <netdb.h> // gcc - addrinfo
\r
22 NNTPListener::NNTPListener()
\r
27 NNTPListener::~NNTPListener()
\r
32 void NNTPListener::Run()
\r
37 std::vector<SOCKET>::iterator listeni;
\r
40 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run thread started.");
\r
54 // put all listen sockets on the fd set
\r
55 for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)
\r
57 FD_SET((*listeni),&readfs);
\r
58 if((*listeni)>highsocket)
\r
60 highsocket=(*listeni);
\r
64 // see if any connections are waiting
\r
65 rval=select(highsocket+1,&readfs,0,0,&tv);
\r
67 // check for new connections
\r
70 for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)
\r
72 if(FD_ISSET((*listeni),&readfs))
\r
75 struct sockaddr_storage addr;
\r
76 socklen_t addrlen=sizeof(addr);
\r
77 newsock=accept((*listeni),(struct sockaddr *)&addr,&addrlen);
\r
78 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::run NNTP client connected");
\r
79 //m_connections.execute(new NNTPConnection(newsock));
\r
80 //m_connectionthreads.push_back(new PThread::Thread(new NNTPConnection(newsock)));
\r
81 m_connections.Execute(new NNTPConnection(newsock));
\r
86 // check for any non-running connection threads that we can delete
\r
87 for(std::vector<PThread::Thread *>::iterator i=m_connectionthreads.begin(); i!=m_connectionthreads.end(); )
\r
89 if((*i)->IsRunning()==false)
\r
92 i=m_connectionthreads.erase(i);
\r
94 if(i!=m_connectionthreads.end())
\r
101 //}while(!ZThread::Thread::interrupted() && m_listensockets.size()>0);
\r
102 }while(!IsCancelled() && m_listensockets.size()>0);
\r
104 // see if any threads are still running - just calling interrupt without check would cause assert in debug mode
\r
106 if(m_connections.wait(1)==false)
\r
108 LogFile::instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run interrupting connection threads and waiting 60 seconds for exit.");
\r
111 m_connections.interrupt();
\r
115 LogFile::instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run caught unhandled exception.");
\r
117 if(m_connections.wait(60000)==false)
\r
119 LogFile::instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run connection threads did not exit after 60 seconds.");
\r
124 for(std::vector<PThread::Thread *>::iterator i=m_connectionthreads.begin(); i!=m_connectionthreads.end(); i++)
\r
126 if((*i)->IsRunning())
\r
128 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::Run waiting for connection thread to exit.");
\r
135 m_connections.Cancel();
\r
136 m_connections.Join();
\r
138 for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)
\r
141 closesocket((*listeni));
\r
146 m_listensockets.clear();
\r
148 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"NNTPListener::run thread exiting.");
\r
152 void NNTPListener::StartListen()
\r
155 std::string bindaddresses;
\r
156 std::vector<std::string> listenaddresses;
\r
157 std::string nntpport;
\r
158 if(Option::Instance()->Get("NNTPListenPort",nntpport)==false)
\r
161 Option::Instance()->Set("NNTPListenPort",nntpport);
\r
163 if(Option::Instance()->Get("NNTPBindAddresses",bindaddresses)==false)
\r
165 bindaddresses="127.0.0.1";
\r
166 Option::Instance()->Set("NNTPBindAddresses",bindaddresses);
\r
168 StringFunctions::Split(bindaddresses,",",listenaddresses);
\r
170 for(std::vector<std::string>::iterator i=listenaddresses.begin(); i!=listenaddresses.end(); i++)
\r
174 struct addrinfo hint,*result,*current;
\r
175 result=current=NULL;
\r
176 memset(&hint,0,sizeof(hint));
\r
177 hint.ai_socktype=SOCK_STREAM;
\r
178 hint.ai_protocol=IPPROTO_TCP;
\r
179 hint.ai_flags=AI_PASSIVE;
\r
181 rval=getaddrinfo((*i).c_str(),nntpport.c_str(),&hint,&result);
\r
184 for(current=result; current!=NULL; current=current->ai_next)
\r
186 sock=socket(current->ai_family,current->ai_socktype,current->ai_protocol);
\r
187 if(sock!=INVALID_SOCKET)
\r
190 const char optval='1';
\r
191 setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&optval,1);
\r
193 if(bind(sock,current->ai_addr,current->ai_addrlen)==0)
\r
195 if(listen(sock,10)==0)
\r
197 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::StartListen started listening at "+(*i)+":"+nntpport);
\r
198 m_listensockets.push_back(sock);
\r
202 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket listen failed");
\r
212 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket bind failed");
\r
222 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen couldn't create socket");
\r
228 freeaddrinfo(result);
\r
231 if(m_listensockets.size()==0)
\r
233 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_FATAL,"NNTPListener::StartListen couldn't start listening on any sockets");
\r