MOOS 0.2375
|
00001 00002 // 00003 // MOOS - Mission Oriented Operating Suite 00004 // 00005 // A suit of Applications and Libraries for Mobile Robotics Research 00006 // Copyright (C) 2001-2005 Massachusetts Institute of Technology and 00007 // Oxford University. 00008 // 00009 // This software was written by Paul Newman at MIT 2001-2002 and Oxford 00010 // University 2003-2005. email: pnewman@robots.ox.ac.uk. 00011 // 00012 // This file is part of a MOOS Core Component. 00013 // 00014 // This program is free software; you can redistribute it and/or 00015 // modify it under the terms of the GNU General Public License as 00016 // published by the Free Software Foundation; either version 2 of the 00017 // License, or (at your option) any later version. 00018 // 00019 // This program is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00022 // General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with this program; if not, write to the Free Software 00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00027 // 02111-1307, USA. 00028 // 00030 // MOOSCommServer.cpp: implementation of the CMOOSCommServer class. 00031 // 00033 00034 #ifdef _WIN32 00035 #pragma warning(disable : 4786) 00036 #pragma warning(disable : 4503) 00037 #endif 00038 00039 #include <MOOSGenLib/MOOSGenLib.h> 00040 #include "MOOSGlobalHelper.h" 00041 #include "MOOSCommServer.h" 00042 #include "MOOSCommPkt.h" 00043 #include "MOOSException.h" 00044 #include "XPCTcpSocket.h" 00045 #include <iostream> 00046 00047 using namespace std; 00048 00049 #ifdef _WIN32 00050 #define INVALID_SOCKET_SELECT WSAEINVAL 00051 #else 00052 #define INVALID_SOCKET_SELECT EBADF 00053 #endif 00054 00055 00057 // Construction/Destruction 00059 00060 00061 bool ServerListenLoopProc(void * pParameter) 00062 { 00063 00064 CMOOSCommServer* pMe = (CMOOSCommServer*)pParameter; 00065 00066 return pMe->ListenLoop(); 00067 } 00068 00069 bool ServerLoopProc( void * pParameter) 00070 { 00071 00072 CMOOSCommServer* pMe = (CMOOSCommServer*)pParameter; 00073 00074 return pMe->ServerLoop(); 00075 } 00076 00077 bool TimerLoopProc( void * pParameter) 00078 { 00079 00080 CMOOSCommServer* pMe = (CMOOSCommServer*)pParameter; 00081 00082 return pMe->TimerLoop(); 00083 } 00084 00085 bool CMOOSCommServer::StartThreads() 00086 { 00087 m_bQuit = false; 00088 00089 if(!m_ListenThread.Initialise(ServerListenLoopProc, this)) 00090 return false; 00091 if(!m_ServerThread.Initialise(ServerLoopProc, this)) 00092 return false; 00093 if(!m_TimerThread.Initialise(TimerLoopProc, this)) 00094 return false; 00095 00096 if(!m_ListenThread.Start()) 00097 return false; 00098 if(!m_ServerThread.Start()) 00099 return false; 00100 if(!m_TimerThread.Start()) 00101 return false; 00102 00103 return true; 00104 00105 } 00106 00107 CMOOSCommServer::CMOOSCommServer() 00108 { 00109 m_nMaxSocketFD = 0; 00110 m_pfnRxCallBack = NULL; 00111 m_pfnDisconnectCallBack = NULL; 00112 m_sCommunityName = "!£"; 00113 m_bQuiet = false; 00114 m_bDisableNameLookUp = false; 00115 } 00116 00117 CMOOSCommServer::~CMOOSCommServer() 00118 { 00119 00120 } 00121 00122 00123 bool CMOOSCommServer::Run(long lPort, const string & sCommunityName,bool bDisableNameLookUp) 00124 { 00125 00126 m_sCommunityName = sCommunityName; 00127 00128 m_lListenPort = lPort; 00129 00130 m_bDisableNameLookUp = bDisableNameLookUp; 00131 00132 if(!m_bQuiet) 00133 DoBanner(); 00134 00135 m_nTotalActions = 0; 00136 SocketsInit(); 00137 StartThreads(); 00138 00139 return true; 00140 } 00141 00142 00143 bool CMOOSCommServer::TimerLoop() 00144 { 00145 //ignore broken pipes as is standard for network apps 00146 #ifndef _WIN32 00147 signal(SIGPIPE,SIG_IGN); 00148 #endif 00149 00150 //optionally inhibit all MOOSTrace.. 00151 if(m_bQuiet) 00152 InhibitMOOSTraceInThisThread(true); 00153 00154 int nPeriod = 3000; 00155 00156 double dfTimeOut = 4.0; 00157 00158 SOCKETLIST::iterator p,q; 00159 00160 while(!m_bQuit) 00161 { 00162 MOOSPause(nPeriod); 00163 00164 double dfTimeNow = MOOSTime(); 00165 00166 m_SocketListLock.Lock(); 00167 00168 p = m_ClientSocketList.begin(); 00169 while(p!=m_ClientSocketList.end()) 00170 { 00171 00172 double dfLastCalled = (*p)->GetReadTime(); 00173 q = p; 00174 ++q; 00175 if(dfTimeNow-dfLastCalled>dfTimeOut) 00176 { 00177 MOOSTrace("its been %f seconds since my last confession:\n",dfTimeNow-dfLastCalled); 00178 MOOSTrace("\tTime Now %f\n\tLastReadTime %f\n",dfTimeNow,dfLastCalled ); 00179 if(OnAbsentClient(*p)) 00180 { 00181 m_ClientSocketList.erase(p); 00182 } 00183 } 00184 p=q; 00185 } 00186 00187 m_SocketListLock.UnLock(); 00188 } 00189 00190 return true; 00191 00192 } 00193 00194 bool CMOOSCommServer::OnAbsentClient(XPCTcpSocket* pClient) 00195 { 00196 MOOSTrace("\n------------ABSENT CLIENT---------\n"); 00197 00198 SOCKETFD_2_CLIENT_NAME_MAP::iterator p; 00199 00200 string sWho; 00201 p = m_Socket2ClientMap.find(pClient->iGetSocketFd()); 00202 00203 if(p!=m_Socket2ClientMap.end()) 00204 { 00205 sWho = p->second; 00206 00207 MOOSTrace("Client \"%s\" is being disconnected - where are you?.\n",p->second.c_str()); 00208 00209 m_Socket2ClientMap.erase(p); 00210 } 00211 00212 GetMaxSocketFD(); 00213 00214 pClient->vCloseSocket(); 00215 00216 delete pClient; 00217 00218 if(m_pfnDisconnectCallBack!=NULL) 00219 { 00220 MOOSTrace("Invoking user OnDisconnect callback...\n"); 00221 00222 if(m_bQuiet) 00223 InhibitMOOSTraceInThisThread(false); 00224 00225 (*m_pfnDisconnectCallBack)(sWho,m_pDisconnectCallBackParam); 00226 00227 if(m_bQuiet) 00228 InhibitMOOSTraceInThisThread(true); 00229 } 00230 00231 MOOSTrace("--------------------------------\n"); 00232 00233 return true; 00234 } 00235 00236 bool CMOOSCommServer::ListenLoop() 00237 { 00238 00239 //ignore broken pipes as is standard for network apps 00240 #ifndef _WIN32 00241 signal(SIGPIPE,SIG_IGN); 00242 #endif 00243 00244 00245 //optionally inhibit all MOOSTrace.. 00246 if(m_bQuiet) 00247 InhibitMOOSTraceInThisThread(true); 00248 00249 00250 00251 m_pListenSocket = new XPCTcpSocket(m_lListenPort); 00252 00253 try 00254 { 00255 //PMN removes this after noticing it allows multiple 00256 //servers to run simultaneously on Win32 00257 #ifndef _WIN32 00258 m_pListenSocket->vSetReuseAddr(1); 00259 #endif 00260 m_pListenSocket->vBindSocket(); 00261 } 00262 catch(XPCException e) 00263 { 00264 #if _WIN32 00265 e; 00266 #endif 00267 00268 MOOSTrace("Error binding to listen socket - Is there another CommServer Running?\n"); 00269 MOOSTrace("This Server Is Quitting\n"); 00270 00271 m_bQuit = true; 00272 00273 delete m_pListenSocket; 00274 00275 m_pListenSocket = NULL; 00276 00277 return false; 00278 } 00279 00280 while(1) 00281 { 00282 00283 try 00284 { 00285 char sClientName[255]; 00286 00287 m_pListenSocket->vListen(); 00288 XPCTcpSocket * pNewSocket = NULL; 00289 #ifdef MOOS_DISABLE_NAMES_LOOKUP 00290 pNewSocket = m_pListenSocket->Accept(); 00291 sClientName[0]='\0'; 00292 #else 00293 if(!m_bDisableNameLookUp) 00294 { 00295 pNewSocket = m_pListenSocket->Accept(sClientName); 00296 } 00297 else 00298 { 00299 MOOSTrace("not waiting for name lookup\n"); 00300 pNewSocket = m_pListenSocket->Accept(); 00301 sClientName[0]='\0'; 00302 } 00303 #endif 00304 00305 m_SocketListLock.Lock(); 00306 00307 if(OnNewClient(pNewSocket,sClientName)) 00308 { 00309 //store new socket 00310 m_ClientSocketList.push_front(pNewSocket); 00311 pNewSocket->SetReadTime(MOOSTime()); 00312 00313 GetMaxSocketFD(); 00314 } 00315 00316 m_SocketListLock.UnLock(); 00317 } 00318 catch(XPCException e) 00319 { 00320 MOOSTrace("Exception Thrown in listen loop: %s\n",e.sGetException()); 00321 } 00322 00323 } 00324 00325 delete m_pListenSocket; 00326 } 00327 00328 00329 bool CMOOSCommServer::ServerLoop() 00330 { 00331 00332 //ignore broken pipes as is standard for network apps 00333 #ifndef _WIN32 00334 signal(SIGPIPE,SIG_IGN); 00335 #endif 00336 00337 //optionally inhibit all MOOSTrace.. 00338 if(m_bQuiet) 00339 InhibitMOOSTraceInThisThread(true); 00340 00341 struct timeval timeout; // The timeout value for the select system call 00342 fd_set fdset; // Set of "watched" file descriptors 00343 00344 00345 00346 while(!m_bQuit) 00347 { 00348 00349 if(m_ClientSocketList.empty()) 00350 { 00351 MOOSPause(1); 00352 continue; 00353 } 00354 00355 // The socket file descriptor set is cleared and the socket file 00356 // descriptor contained within tcpSocket is added to the file 00357 // descriptor set. 00358 FD_ZERO(&fdset); 00359 00360 SOCKETLIST::iterator p,q; 00361 00362 m_SocketListLock.Lock(); 00363 00364 //rotate list.. 00365 if(!m_ClientSocketList.empty()) 00366 { 00367 m_ClientSocketList.push_front(m_ClientSocketList.back()); 00368 m_ClientSocketList.pop_back(); 00369 00370 for(p = m_ClientSocketList.begin();p!=m_ClientSocketList.end();p++) 00371 { 00372 FD_SET((*p)->iGetSocketFd(), &fdset); 00373 } 00374 } 00375 m_SocketListLock.UnLock(); 00376 00377 // The select system call is set to timeout after 1 seconds with no data existing 00378 // on the socket. This has to be here, within the loop as Linux actually writes over 00379 // the timeout structure on completion of select (no that was a hard bug to find) 00380 timeout.tv_sec = 1; 00381 timeout.tv_usec = 0; 00382 00383 00384 00385 // A select is setup to return when data is available on the socket 00386 // for reading. If data is not available after 1000 useconds, select 00387 // returns with a value of 0. If data is available on the socket, 00388 // the select returns and data can be retrieved off the socket. 00389 int iSelectRet = select(m_nMaxSocketFD + 1, 00390 &fdset, 00391 NULL, 00392 NULL, 00393 &timeout); 00394 00395 // If select returns a -1, then it failed and the thread exits. 00396 switch(iSelectRet) 00397 { 00398 case -1: 00399 if(XPCSocket::iGetLastError()==INVALID_SOCKET_SELECT) 00400 { 00401 //this can be caused by absenteeism between set up of fdset and select 00402 //prefer to catch and tolerate than block other threads for duration 00403 //of select and processing - added by PMN in Jan 2008 to address a 00404 //race condition which took a long time to show up... 00405 break; 00406 } 00407 else 00408 { 00409 return false; 00410 } 00411 00412 case 0: 00413 //timeout...nothing to read 00414 break; 00415 00416 default: 00417 //something to read: 00418 m_SocketListLock.Lock(); 00419 for(p = m_ClientSocketList.begin();p!=m_ClientSocketList.end();p++) 00420 { 00421 m_pFocusSocket = *p; 00422 00423 if (FD_ISSET(m_pFocusSocket->iGetSocketFd(), &fdset) != 0) 00424 { 00425 //something to do read: 00426 if(!ProcessClient()) 00427 { 00428 //client disconnected! 00429 OnClientDisconnect(); 00430 m_ClientSocketList.erase(p); 00431 break; 00432 } 00433 } 00434 } 00435 m_SocketListLock.UnLock(); 00436 break; 00437 } 00438 00439 //zero socket set.. 00440 FD_ZERO(&fdset); 00441 00442 } 00443 return 0; 00444 } 00445 00446 00447 bool CMOOSCommServer::ProcessClient() 00448 { 00449 bool bResult = true; 00450 00451 try 00452 { 00453 m_pFocusSocket->SetReadTime(MOOSTime()); 00454 00455 //now we act on that packet 00456 //by way of the user supplied called back 00457 if(m_pfnRxCallBack!=NULL) 00458 { 00459 00460 CMOOSCommPkt PktRx,PktTx; 00461 MOOSMSG_LIST MsgLstRx,MsgLstTx; 00462 00463 //read input 00464 ReadPkt(m_pFocusSocket,PktRx); 00465 00466 //convert to list of messages 00467 PktRx.Serialize(MsgLstRx,false); 00468 00469 std::string sWho = m_Socket2ClientMap[m_pFocusSocket->iGetSocketFd()]; 00470 //let owner figure out what to do ! 00471 //this is a user supplied call back 00472 00473 if(m_bQuiet) 00474 InhibitMOOSTraceInThisThread(false); 00475 00476 if(!(*m_pfnRxCallBack)(sWho,MsgLstRx,MsgLstTx,m_pRxCallBackParam)) 00477 { 00478 //client call back failed!! 00479 MOOSTrace(" CMOOSCommServer::ProcessClient() pfnCallback failed\n"); 00480 } 00481 00482 if(m_bQuiet) 00483 InhibitMOOSTraceInThisThread(true); 00484 00485 00486 //we must send something back... just to keep the link alive 00487 //PMN changes this in 2007 as part of the new timing scheme 00488 //every packet will no begin with a NULL message the double val 00489 //of which will be the current time on the BD's machine 00490 if( 1 || MsgLstTx.size()==0) 00491 { 00492 //add a default packet so client doesn't block 00493 CMOOSMsg NullMsg; 00494 NullMsg.m_dfVal = MOOSLocalTime(); 00495 MsgLstTx.push_front(NullMsg); 00496 } 00497 00498 //stuff reply mesage into a packet 00499 PktTx.Serialize(MsgLstTx,true); 00500 00501 //send packet 00502 SendPkt(m_pFocusSocket,PktTx); 00503 00504 } 00505 } 00506 catch(CMOOSException e) 00507 { 00508 MOOSTrace("ProcessClient() Exception: %s\n", e.m_sReason); 00509 bResult = false; 00510 } 00511 00512 return bResult; 00513 00514 } 00515 00516 bool CMOOSCommServer::OnNewClient(XPCTcpSocket * pNewClient,char * sName) 00517 { 00518 MOOSTrace("\n------------CONNECT-------------\n"); 00519 00520 00521 MOOSTrace("New client connected from machine \"%s\"\n",sName); 00522 MOOSTrace("Handshaking...."); 00523 00524 00525 00526 if(HandShake(pNewClient)) 00527 { 00528 MOOSTrace("done\n"); 00529 00530 string sName = GetClientName(pNewClient); 00531 00532 if(!sName.empty()) 00533 { 00534 MOOSTrace("clients name is \"%s\"\n",sName.c_str()); 00535 } 00536 } 00537 else 00538 { 00539 MOOSTrace("Handshaking failed - client is spurned\n"); 00540 pNewClient->vCloseSocket(); 00541 delete pNewClient; 00542 MOOSTrace("--------------------------------\n"); 00543 return false; 00544 } 00545 00546 MOOSTrace("There are now %d clients connected.\n",m_ClientSocketList.size()+1); 00547 00548 MOOSTrace("--------------------------------\n"); 00549 00550 00551 00552 return true; 00553 } 00554 00555 bool CMOOSCommServer::OnClientDisconnect() 00556 { 00557 00558 00559 MOOSTrace("\n------------DISCONNECT-------------\n"); 00560 00561 SOCKETFD_2_CLIENT_NAME_MAP::iterator p; 00562 00563 string sWho; 00564 p = m_Socket2ClientMap.find(m_pFocusSocket->iGetSocketFd()); 00565 00566 if(p!=m_Socket2ClientMap.end()) 00567 { 00568 sWho = p->second; 00569 00570 MOOSTrace("Client \"%s\" has disconnected.\n",p->second.c_str()); 00571 00572 m_Socket2ClientMap.erase(p); 00573 } 00574 00575 GetMaxSocketFD(); 00576 00577 m_pFocusSocket->vCloseSocket(); 00578 00579 delete m_pFocusSocket; 00580 00581 if(m_pfnDisconnectCallBack!=NULL) 00582 { 00583 MOOSTrace("Invoking user OnDisconnect callback...\n"); 00584 if(m_bQuiet) 00585 InhibitMOOSTraceInThisThread(false); 00586 00587 (*m_pfnDisconnectCallBack)(sWho,m_pDisconnectCallBackParam); 00588 00589 if(m_bQuiet) 00590 InhibitMOOSTraceInThisThread(true); 00591 00592 } 00593 00594 MOOSTrace("--------------------------------\n"); 00595 00596 00597 return true; 00598 } 00599 00600 //void CMOOSCommServer::SetOnRxCallBack(bool (__cdecl *pfn)(MOOSMSG_LIST & MsgListRx,MOOSMSG_LIST & MsgListTx, void * pParam), void * pParam) 00601 void CMOOSCommServer::SetOnRxCallBack(bool ( *pfn)(const std::string & ,MOOSMSG_LIST & MsgListRx,MOOSMSG_LIST & MsgListTx, void * pParam), void * pParam) 00602 { 00603 //address of function to invoke (static) 00604 m_pfnRxCallBack=pfn; 00605 00606 //store the address of the object invoking the callback -> needed for scope 00607 //resolution when callback is invoked 00608 m_pRxCallBackParam = pParam; 00609 } 00610 00611 //void CMOOSCommServer::SetOnDisconnectCallBack(bool (__cdecl *pfn)(string & MsgListRx, void * pParam), void * pParam) 00612 void CMOOSCommServer::SetOnDisconnectCallBack(bool (*pfn)(string & MsgListRx, void * pParam), void * pParam) 00613 { 00614 //address of function to invoke (static) 00615 m_pfnDisconnectCallBack=pfn; 00616 00617 //store the address of the object invoking the callback -> needed for scope 00618 //resolution when callback is invoked 00619 m_pDisconnectCallBackParam = pParam; 00620 } 00621 00622 bool CMOOSCommServer::IsUniqueName(string &sClientName) 00623 { 00624 SOCKETFD_2_CLIENT_NAME_MAP::iterator p; 00625 00626 for(p = m_Socket2ClientMap.begin();p!=m_Socket2ClientMap.end();p++) 00627 { 00628 if(p->second==sClientName) 00629 { 00630 return false; 00631 } 00632 } 00633 00634 return true; 00635 } 00636 00637 00638 //here we can check that the client is speaking the correct wire protocol 00639 //we begin by reading a string and checking it is what we are expecting 00640 //note we are only reading a few bytes so this lets us catch the case where 00641 //an old client that doesn't send a string simpy sends a COmmPkt first 00642 //chances of a comm packete spelling at a ptotocl name are pretty damns slim..... 00643 bool CheckProtocol(XPCTcpSocket *pNewClient) 00644 { 00645 char sProtocol[MOOS_PROTOCOL_STRING_BUFFER_SIZE+1]; 00646 sProtocol[MOOS_PROTOCOL_STRING_BUFFER_SIZE]='\0'; 00647 int nRead = pNewClient->iRecieveMessage(sProtocol, MOOS_PROTOCOL_STRING_BUFFER_SIZE ); 00648 if (nRead <=0 || !MOOSStrCmp(sProtocol, MOOS_PROTOCOL_STRING)) 00649 { 00650 //this is bad - wrong flavour of comms - perhaps client needs to be recompiled... 00651 return MOOSFail("Incompatible wire protocol between DB and Client:\n Expecting protocol named \"%s\".\n Client is using a protocol called \"%s\"\n\n Make sure the client and MOOSDB are linking against a MOOSLIB which uses the same protocol \n",MOOS_PROTOCOL_STRING,sProtocol); 00652 } 00653 00654 return true; 00655 00656 } 00657 00658 00659 bool CMOOSCommServer::HandShake(XPCTcpSocket *pNewClient) 00660 { 00661 CMOOSMsg Msg; 00662 00663 double dfSkew = 0; 00664 00665 try 00666 { 00667 00668 if(!CheckProtocol(pNewClient)) 00669 { 00670 throw CMOOSException("protocol error"); 00671 } 00672 00673 if(ReadMsg(pNewClient,Msg,5)) 00674 { 00675 double dfClientTime = Msg.m_dfTime; 00676 00677 dfSkew = MOOSTime()-dfClientTime; 00678 00679 if(IsUniqueName(Msg.m_sVal)) 00680 { 00681 m_Socket2ClientMap[pNewClient->iGetSocketFd()] = Msg.m_sVal; 00682 } 00683 else 00684 { 00685 PoisonClient(pNewClient, 00686 MOOSFormat("A client of this name (\"%s\") already exists", 00687 Msg.m_sVal.c_str()) 00688 ); 00689 00690 return false; 00691 } 00692 } 00693 else 00694 { 00695 PoisonClient(pNewClient,"Failed to read receive clients name"); 00696 return false; 00697 } 00698 00699 //send a message back to the client saying welcome 00700 CMOOSMsg MsgW(MOOS_WELCOME,"",dfSkew); 00701 SendMsg(pNewClient,MsgW); 00702 00703 return true; 00704 } 00705 catch (CMOOSException e) 00706 { 00707 MOOSTrace("\nException caught [%s]\n",e.m_sReason); 00708 return false; 00709 } 00710 } 00711 00712 void CMOOSCommServer::PoisonClient(XPCTcpSocket *pSocket, const std::string & sReason) 00713 { 00714 //kill the client... 00715 CMOOSMsg MsgK(MOOS_POISON,"",sReason); 00716 SendMsg(pSocket,MsgK); 00717 } 00718 00719 string CMOOSCommServer::GetClientName(XPCTcpSocket *pSocket) 00720 { 00721 SOCKETFD_2_CLIENT_NAME_MAP::iterator p; 00722 00723 p = m_Socket2ClientMap.find(pSocket->iGetSocketFd()); 00724 00725 if(p!=m_Socket2ClientMap.end()) 00726 { 00727 return p->second; 00728 } 00729 else 00730 { 00731 MOOSTrace("CMOOSCommServer::GetClientName() failed!\n"); 00732 return ""; 00733 } 00734 00735 } 00736 00737 void CMOOSCommServer::DoBanner() 00738 { 00739 MOOSTrace("***************************************************\n"); 00740 MOOSTrace("* This is MOOS Server for Community \"%s\" \n",m_sCommunityName.c_str()); 00741 MOOSTrace("* c. P Newman 2001 \n"); 00742 MOOSTrace("* \n"); 00743 MOOSTrace("* Binding on %d \n",m_lListenPort); 00744 #ifdef _WIN32 00745 MOOSTrace("* built on %s\n",__TIMESTAMP__); 00746 #endif 00747 MOOSTrace("* \n"); 00748 MOOSTrace("* This machine is %s endian \n",IsLittleEndian()?"Little":"Big"); 00749 MOOSTrace("***************************************************\n"); 00750 00751 } 00752 00753 int CMOOSCommServer::GetMaxSocketFD() 00754 { 00755 SOCKETLIST::iterator p; 00756 00757 m_nMaxSocketFD = 0; 00758 for(p=m_ClientSocketList.begin();p!=m_ClientSocketList.end();p++) 00759 { 00760 m_nMaxSocketFD = m_nMaxSocketFD > (*p)->iGetSocketFd() 00761 ? m_nMaxSocketFD : 00762 (*p)->iGetSocketFd(); 00763 } 00764 00765 return m_nMaxSocketFD; 00766 00767 } 00768 00769 00770 bool CMOOSCommServer::GetClientNames(STRING_LIST &sList) 00771 { 00772 sList.clear(); 00773 00774 SOCKETFD_2_CLIENT_NAME_MAP::iterator p; 00775 00776 for(p = m_Socket2ClientMap.begin();p!=m_Socket2ClientMap.end();p++) 00777 { 00778 sList.push_front(p->second); 00779 } 00780 00781 return true; 00782 }