version 0.1.0
[fms.git] / src / nntp / nntplistener.cpp
diff --git a/src/nntp/nntplistener.cpp b/src/nntp/nntplistener.cpp
new file mode 100644 (file)
index 0000000..4d1c37d
--- /dev/null
@@ -0,0 +1,175 @@
+#include "../../include/nntp/nntplistener.h"\r
+#include "../../include/nntp/nntpconnection.h"\r
+#include "../../include/option.h"\r
+#include "../../include/logfile.h"\r
+#include "../../include/global.h"\r
+#include "../../include/stringfunctions.h"\r
+\r
+#ifdef _WIN32\r
+       #include <winsock2.h>\r
+       #include <ws2tcpip.h>\r
+#else\r
+\r
+#endif\r
+\r
+#ifdef XMEM\r
+       #include <xmem.h>\r
+#endif\r
+\r
+NNTPListener::NNTPListener()\r
+{\r
+\r
+}\r
+\r
+NNTPListener::~NNTPListener()\r
+{\r
+\r
+}\r
+\r
+void NNTPListener::run()\r
+{\r
+       int rval;\r
+       struct fd_set readfs;\r
+       struct timeval tv;\r
+       std::vector<SOCKET>::iterator listeni;\r
+       SOCKET highsocket;\r
+\r
+       StartListen();\r
+\r
+       do\r
+       {\r
+               // reset values\r
+               highsocket=0;\r
+               tv.tv_sec=1;\r
+               tv.tv_usec=0;\r
+\r
+               // clear fd set\r
+               FD_ZERO(&readfs);\r
+\r
+               // put all listen sockets on the fd set\r
+               for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)\r
+               {\r
+                       FD_SET((*listeni),&readfs);\r
+                       if((*listeni)>highsocket)\r
+                       {\r
+                               highsocket=(*listeni);\r
+                       }\r
+               }\r
+\r
+               // see if any connections are waiting\r
+               rval=select(highsocket+1,&readfs,0,0,&tv);\r
+\r
+               // check for new connections\r
+               if(rval>0)\r
+               {\r
+                       for(listeni=m_listensockets.begin(); listeni!=m_listensockets.end(); listeni++)\r
+                       {\r
+                               if(FD_ISSET((*listeni),&readfs))\r
+                               {\r
+                                       SOCKET newsock;\r
+                                       struct sockaddr_storage addr;\r
+                                       int addrlen=sizeof(addr);\r
+                                       newsock=accept((*listeni),(struct sockaddr *)&addr,&addrlen);\r
+                                       LogFile::instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::run NNTP client connected");\r
+                                       m_connections.execute(new NNTPConnection(newsock));\r
+                               }\r
+                       }\r
+               }\r
+\r
+       }while(!ZThread::Thread::interrupted() && m_listensockets.size()>0);\r
+\r
+       // see if any threads are still running - just calling interrupt without check would cause assert in debug mode\r
+       if(m_connections.wait(1)==false)\r
+       {\r
+               try\r
+               {\r
+                       m_connections.interrupt();\r
+               }\r
+               catch(...)\r
+               {\r
+               }\r
+               m_connections.wait();\r
+       }\r
+\r
+}\r
+\r
+void NNTPListener::StartListen()\r
+{\r
+       \r
+       std::string bindaddresses;\r
+       std::vector<std::string> listenaddresses;\r
+       std::string nntpport;\r
+       if(Option::instance()->Get("NNTPListenPort",nntpport)==false)\r
+       {\r
+               nntpport="1119";\r
+               Option::instance()->Set("NNTPListenPort",nntpport);\r
+       }\r
+       if(Option::instance()->Get("NNTPBindAddresses",bindaddresses)==false)\r
+       {\r
+               bindaddresses="127.0.0.1";\r
+               Option::instance()->Set("NNTPBindAddresses",bindaddresses);\r
+       }\r
+       StringFunctions::Split(bindaddresses,",",listenaddresses);\r
+       \r
+       for(std::vector<std::string>::iterator i=listenaddresses.begin(); i!=listenaddresses.end(); i++)\r
+       {\r
+               SOCKET sock;\r
+               int rval;\r
+               struct addrinfo hint,*result,*current;\r
+               result=current=NULL;\r
+               memset(&hint,0,sizeof(hint));\r
+               hint.ai_socktype=SOCK_STREAM;\r
+               hint.ai_protocol=IPPROTO_TCP;\r
+               hint.ai_flags=AI_PASSIVE;\r
+               \r
+               rval=getaddrinfo((*i).c_str(),nntpport.c_str(),&hint,&result);\r
+               if(rval==0)\r
+               {\r
+                       for(current=result; current!=NULL; current=current->ai_next)\r
+                       {\r
+                               sock=socket(current->ai_family,current->ai_socktype,current->ai_protocol);\r
+                               if(sock!=INVALID_SOCKET)\r
+                               {\r
+                                       if(bind(sock,current->ai_addr,current->ai_addrlen)==0)\r
+                                       {\r
+                                               if(listen(sock,10)==0)\r
+                                               {\r
+                                                       LogFile::instance()->WriteLog(LogFile::LOGLEVEL_INFO,"NNTPListener::StartListen started listening at "+(*i)+":"+nntpport);\r
+                                                       m_listensockets.push_back(sock);\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       LogFile::instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket listen failed");\r
+                                                       #ifdef _WIN32\r
+                                                       closesocket(sock);\r
+                                                       #else\r
+                                                       close(sock);\r
+                                                       #endif\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               LogFile::instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen socket bind failed");\r
+                                               #ifdef _WIN32\r
+                                               closesocket(sock);\r
+                                               #else\r
+                                               close(sock);\r
+                                               #endif\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       LogFile::instance()->WriteLog(LogFile::LOGLEVEL_ERROR,"NNTPListener::StartListen couldn't create socket");\r
+                               }\r
+                       }\r
+               }\r
+               if(result)\r
+               {\r
+                       freeaddrinfo(result);\r
+               }\r
+       }\r
+       if(m_listensockets.size()==0)\r
+       {\r
+               LogFile::instance()->WriteLog(LogFile::LOGLEVEL_FATAL,"NNTPListener::StartListen couldn't start listening on any sockets");\r
+       }\r
+}\r