📄 netmanager.cpp~
字号:
//try to serve the request for (Client *tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next()) { getDebug()<<"NetManager::serveAndClean: trying to get info"<<endl; tmpClient->tryToGetInfo(); }; //try to delete served the clients for (Client* tmpClient=clients.first();tmpClient!=0; tmpClient=clients.next()) { //if we served the client or if he's already half a minute //connected remove it //this way we get rid of clients if something went wrong and //maybe it's even a security point, I don't know if ((tmpClient->done()) || (tmpClient->age()>30)) { getDebug()<<"NetManager::serveAndClean: removing Client"<<endl; clients.remove(tmpClient); tmpClient=clients.first(); }; };};void NetManager::scan(){ getDebug()<<"NetManager::scan()"<<endl; if (isBeingScanned()) return; time_t currentTime=time(0); getDebug()<<"currentTime: "<<currentTime<<" lastUpdate: "<<m_lastUpdate<<endl; if ((currentTime-m_lastUpdate)<m_refreshTime) return; getDebug()<<"NetManager::scan: scanning..."<<endl; m_isBeingScanned=1; int fileDescr[2]; ::pipe(fileDescr); getDebug()<<"NetScanner::scan: file-descr[0]: "<<fileDescr[0]<<endl; getDebug()<<"NetScanner::scan: file-descr[1]: "<<fileDescr[1]<<endl; int pid=fork(); if (pid==-1) { getDebug()<<"NetScanner::scan: error occured"<<endl; return; } else if (pid!=0) { //parent ::close(fileDescr[1]); m_pipeFD=fileDescr[0]; m_childPid=pid; return; }; //child procId="** child ** "; getDebug()<<" NetManager::scan: a child was born"<<endl; if (m_strictMode) { getDebug()<<" NetManager::scan: scanning myself in strict mode, becoming serverServer"<<endl; doScan(); //in the child we don't have to call setServerServer() //since this opens the listening socket, what has to be done //in the parent process m_serverServer=1; } else { int serverAddress=findServerServer(); if (serverAddress==0) { getDebug()<<" NetManager::scan: scanning myself, becoming serverServer"<<endl; doScan(); //in the child we don't have to call setServerServer() //since this opens the listening socket, what has to be done //in the parent process m_serverServer=1; } else { getDebug()<<" NetManager::scan: getting list from serverServer"<<endl; getListFromServerServer(serverAddress); m_serverServer=0; }; }; getDebug()<<" NetScanner::scan: sending information to parent process"<<endl; writeDataToFD(fileDescr[1],m_serverServer); getDebug()<<" NetScanner::scan: closed FD: "<<::close(fileDescr[1])<<endl; getDebug()<<" NetScanner::scan: exiting now"<<endl; ::exit(0);};int NetManager::writeDataToFD(int fd, int serverServer){ getDebug()<<" NetManager::writeDataToFD fd="<<fd<<endl; m_serveCount++; char buffer[1024]; int length; for (Node* tmpNode=hostList->first(); tmpNode!=0; tmpNode=hostList->next()) { sprintf(buffer,"%u %s\n",tmpNode->ip,tmpNode->name.left(1000).c_str()); length=strlen(buffer)+1; const char *currentBuf=buffer; //make sure that everything is written while (length>0) { int result=::write(fd,currentBuf,length); getDebug()<<"NetManager::writeDataToFD: wrote "<<result<<" bytes"<<endl; if (result==-1) { perror("hmmpf: "); return 0; }; length-=result; currentBuf+=result; }; }; //and a last line sprintf(buffer,"%d succeeded\n",serverServer); length=strlen(buffer)+1; const char *currentBuf=buffer; //make sure that everything is written while (length>0) { int result=::write(fd,currentBuf,length); if (result==-1) return 0; length-=result; currentBuf+=result; }; return 1;};int NetManager::readDataFromFD(int fd){ getDebug()<<"NetManager::readDataFromFD"<<endl; char tmpBuf[64*1024]; int result=::read(fd,tmpBuf,64*1024); getDebug()<<"NetManager::readDataFromFD: read "<<result<<" bytes"<<endl; if (result==-1) return -1; if (result==0) { getDebug()<<"NetManager::readDataFromFD: FD was closed"<<endl; return 0; }; char *newBuf=new char[m_receivedBytes+result]; if (m_receiveBuffer!=0) memcpy(newBuf,m_receiveBuffer,m_receivedBytes); memcpy(newBuf+m_receivedBytes,tmpBuf,result); m_receivedBytes+=result; if (m_receiveBuffer!=0) delete [] m_receiveBuffer; m_receiveBuffer=newBuf; return 1;};int NetManager::processScanResults(){ getDebug()<<"NetManager::processScanResults"<<endl; if (m_receiveBuffer==0) return 0; SimpleList<Node> *newNodes=new SimpleList<Node>; char *tmpBuf=m_receiveBuffer; int bytesLeft=m_receivedBytes; int tmpIP; getDebug()<<"m_receivedBytes: "<<m_receivedBytes<<" bytesLeft: "<<bytesLeft<<endl; //this should be large enough for a name //and the stuff which is inserted into the buffer //comes only from ourselves char tmpName[1024*4]; while (bytesLeft>0) { if ((memchr(tmpBuf,0,bytesLeft)==0) || (memchr(tmpBuf,int('\n'),bytesLeft)==0)) { delete newNodes; hostList->clear(); m_lastUpdate=time(0); delete [] m_receiveBuffer; m_receiveBuffer=0; m_receivedBytes=0; m_isInformed=1; m_isBeingScanned=0; return 0; }; //getDebug()<<"NetManager::processScanResults: processing -"<<tmpBuf; sscanf(tmpBuf,"%u %s\n",&tmpIP,tmpName); //since we check for 0 and \n with memchr() we can be sure //at this point that tmpBuf is correctly terminated int length=strlen(tmpBuf)+1; bytesLeft-=length; tmpBuf+=length; getDebug()<<"length: "<<length<<" bytesLeft: "<<bytesLeft<<endl; if ((bytesLeft==0) && (strstr(tmpName,"succeeded")!=0) && ((tmpIP==0) ||(tmpIP==1))) { getDebug()<<"NetManager::processScanResults: succeeded :-)"<<endl; delete hostList; hostList=newNodes; m_lastUpdate=time(0); delete [] m_receiveBuffer; m_receiveBuffer=0; m_receivedBytes=0; m_isInformed=1; m_isBeingScanned=0; adjustRefreshTime(tmpIP); enableServerServer(tmpIP); //m_serverServer=tmpIP; return 1; } else { //getDebug()<<"NetManager::processScanResults: adding host: "<<tmpName<<" with ip: "<<tmpIP<<endl; newNodes->append(Node(tmpName,tmpIP)); }; }; //something failed :-( delete newNodes; hostList->clear(); m_lastUpdate=time(0); delete [] m_receiveBuffer; m_receiveBuffer=0; m_receivedBytes=0; m_isInformed=1; m_isBeingScanned=0; getDebug()<<"NetScanner::processScanResult: finished"<<endl; return 0;};void NetManager::adjustRefreshTime(int serverServer){ //we are becoming server server if (((m_serverServer==0) && (serverServer)) || (m_servedThisPeriod)) { m_increasedRefreshTime=0; m_refreshTime=m_initialRefreshTime; } //nobody accessed the server since the last update //so increase the refresh time //this should happen more seldom to the serverServer //than to others else { //up to the 16 times refresh time if (m_increasedRefreshTime<4) { m_increasedRefreshTime++; m_refreshTime*=2; }; }; m_servedThisPeriod=0; };void NetManager::enableServerServer(int on){ getDebug()<<"NetManager::enableServerServer: "<<on<<endl; //in strictMode we don't listen to broadcasts from the network if (m_strictMode) return; m_serverServer=on; if (on) { //nothing has to be done if (m_bcFD!=-1) return; // otherwise create the socket which will listen for broadcasts sockaddr_in my_addr; my_addr.sin_family=AF_INET; my_addr.sin_port=htons(m_basePort); my_addr.sin_addr.s_addr=0; m_bcFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (m_bcFD==-1) { getDebug()<<"NetManager::enableServerServer: socket() failed"<<endl; m_serverServer=0; return; }; int on(1); int result=setsockopt(m_bcFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (result!=0) { getDebug()<<"NetManager::enableServerServer: setsockopt(SO_REUSEADDR) failed"<<endl; m_serverServer=0; ::close(m_bcFD); m_bcFD=-1; return; }; result=::bind(m_bcFD, (struct sockaddr *) &my_addr, sizeof(my_addr)); if (result!=0) { getDebug()<<"NetManager::enableServerServer: bind (UDP) failed"<<endl; m_serverServer=0; ::close(m_bcFD); m_bcFD=-1; return; }; } else { ::close(m_bcFD); m_bcFD=-1; };};int NetManager::findServerServer(){ getDebug()<<" NetManager::findServerServer"<<endl; //actually this should never be called in strictMode if (m_strictMode) return 0; if (!validator.isValid(m_broadcastAddress)) { getDebug()<<" NetManager::findServerServer: invalid broadcastAddress"<<endl; return 0; }; //create a socket for sending the broadcast //we don't have to set SO_REUSEADDR, since we don't call bind() //to this socket int requestFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (requestFD==-1) { getDebug()<<" NetManager::findServerServer: could not create request socket"<<endl; return 0; }; int on(1); //this is actually the only socket which will send broacasts int result=setsockopt(requestFD, SOL_SOCKET, SO_BROADCAST,&on, sizeof(on)); if (result!=0) { getDebug()<<"setsockopt(SO_BROADCAST) failed"<<endl; ::close(requestFD); return 0; }; //create a socket for receiving the answers int answerFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (answerFD==-1) { getDebug()<<" NetManager::findServerServer"<<endl; ::close(requestFD); return 0; }; //since this socket will be bound, we have to set SO_REUSEADDR result=setsockopt(answerFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (result!=0) { getDebug()<<"setsockopt(SO_REUSEADDR) failed"<<endl; ::close(answerFD); ::close(requestFD); return 0; }; sockaddr_in my_addr; my_addr.sin_family=AF_INET; my_addr.sin_port=htons(m_basePort+1); my_addr.sin_addr.s_addr=0; //this one has to be bound result=::bind(answerFD, (struct sockaddr *) &my_addr, sizeof(my_addr)); if (result!=0) { getDebug()<<"bind (UDP) failed"<<endl; ::close(answerFD); ::close(requestFD); return 0; }; //now send the broadcast struct sockaddr_in sAddr; sAddr.sin_addr.s_addr=m_broadcastAddress; sAddr.sin_family=AF_INET; sAddr.sin_port=htons(m_basePort); socklen_t length(sizeof(sockaddr_in)); getDebug()<<" NetManager::findServerServer: broadcasting to: " <<ios::hex<<m_broadcastAddress<<ios::dec<<endl; MyFrameType requestFrame; requestFrame.id=htonl(MY_ID); requestFrame.unused1=htonl(getppid()); requestFrame.unused2=htonl(m_startedAt); result=::sendto(requestFD,(void*)&requestFrame,sizeof(requestFrame),0,(sockaddr*)&sAddr,length); ::close(requestFD); if (result!=MYFRAMELENGTH) { getDebug()<<" NetManager::findServerServer: sent wrong number of bytes: "<<result<<endl; ::close(answerFD); return 0; }; //wait for an answer struct timeval tv; tv.tv_sec=0; tv.tv_usec=1000*250; //0.1 sec fd_set fdSet; FD_ZERO(&fdSet); FD_SET(answerFD,&fdSet); result=select(answerFD+1,&fdSet,0,0,&tv); if (result<0) { getDebug()<<" NetManager::findServerServer: select() failed: "<<result<<endl; getDebug()<<" NetManager::findServerServer: answerFD="<<answerFD<<endl; perror("select:"); ::close(answerFD); return 0; } if (result==0) { getDebug()<<" NetManager::findServerServer: nobody answered "<<endl; ::close(answerFD); return 0; } getDebug()<<"received offer "<<endl; struct sockaddr_in addr; length=sizeof(sockaddr_in); char buf[1024]; result=recvfrom(answerFD, (void*)buf, 1024, 0, (sockaddr*) &addr,&length); if (result!=MYFRAMELENGTH) { getDebug()<<" NetManager::findServerServer: wrong number of bytes: "<<result<<endl; ::close(answerFD); return 0; }; MyFrameType *frame=(MyFrameType*)(void*)buf; //wrong identifier ? if (ntohl(frame->id)!=MY_ID) { getDebug()<<" NetManager::findServerServer: wrong id"<<endl; ::close(answerFD); return 0; }; getDebug()<<"received from "<<inet_ntoa(addr.sin_addr)<<endl; ::close(answerFD); //return the ip of the server server in network byte order return addr.sin_addr.s_addr;};void NetManager::getListFromServerServer( int address){ getDebug()<<"NetManager::getListFromServerServer"<<endl; //actually we should never get here in strictMode if (m_strictMode) return; //open a tcp socket to the serverserver int serverServerFD=::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverServerFD==-1) return; sockaddr_in addr; //we get the address already in network byte order addr.sin_addr.s_addr=address; addr.sin_family=AF_INET; addr.sin_port=htons(m_basePort); int result=::connect(serverServerFD,(sockaddr*)&addr,sizeof(addr)); if (result!=0) { ::close(serverServerFD); return; }; do { result=readDataFromFD(serverServerFD); } while (result==1); ::close(serverServerFD); processScanResults(); getDebug()<<"NetManager::getListFromServerServer succeeded"<<endl;};void NetManager::printState(){ cerr<<"LAN Information Server Lisa 0.1\nAlexander Neundorf <neundorf@kde.org>\n"; cerr<<"Reading options from config file: "<<m_usedConfigFileName<<endl; cerr<<"StrictMode: "<<m_strictMode<<endl; cerr<<"ServerServer: "<<m_serverServer<<endl; cerr<<"UseNmblookup: "<<m_useNmblookup<<endl; cerr<<"Pinging: "<<ipRangeStr<<endl; cerr<<"Allowed hosts: "<<validator.validAddresses()<<endl; cerr<<"Broadcasting to: "<<ios::hex<<ntohl(m_broadcastAddress)<<ios::dec<<endl; cerr<<"Initial update period: "<<m_initialRefreshTime<<" seconds"<<endl; cerr<<"Current update period: "<<m_refreshTime<<" seconds"<<endl; cerr<<"Last update: "<<time(0)-m_lastUpdate<<" seconds over"<<endl; cerr<<"Waiting "<<m_firstWait<<" 1/100th seconds for echo answers on the first try"<<endl; cerr<<"Waiting "<<m_secondWait<<" 1/100th seconds for echo answers on the second try"<<endl; cerr<<"Sending "<<m_maxPings<<" echo requests at once"<<endl; cerr<<"Publishing unnamed hosts: "<<m_deliverUnnamedHosts<<endl; cerr<<"Already served "<<m_serveCount<<" times"<<endl;};//this one is not used at the moment/*int NetManager::uptime(){ return (time(0)-m_startedAt);};*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -