Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

netcontrol.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*-
00002    this file is part of rcssserver3D
00003    Fri May 9 2003
00004    Copyright (C) 2003 Koblenz University
00005    $Id: netcontrol.cpp,v 1.5 2004/12/21 23:04:46 tomhoward Exp $
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; version 2 of the License.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 #include "netcontrol.h"
00021 #include "netmessage.h"
00022 #include <zeitgeist/logserver/logserver.h>
00023 #include <netinet/in.h>
00024 #include <rcssnet/exception.hpp>
00025 #include <rcssnet/tcpsocket.hpp>
00026 #include <rcssnet/udpsocket.hpp>
00027 #include <sstream>
00028 #include <cerrno>
00029 
00030 using namespace rcss::net;
00031 using namespace oxygen;
00032 using namespace zeitgeist;
00033 using namespace boost;
00034 using namespace std;
00035 
00036 NetControl::NetControl() : SimControlNode()
00037 {
00038     mBufferSize = 64 * 1024;
00039     mBuffer     = shared_array<char>(new char[mBufferSize]);
00040     mSocketType = ST_TCP;
00041     mLocalAddr  = Addr(INADDR_ANY, INADDR_ANY);
00042     mClientId   = 1;
00043 }
00044 
00045 NetControl::~NetControl()
00046 {
00047 }
00048 
00049 void NetControl::SetServerPort(Addr::PortType port)
00050 {
00051     mLocalAddr.setPort(port);
00052 }
00053 
00054 rcss::net::Addr::PortType NetControl::GetServerPort()
00055 {
00056     return mLocalAddr.getPort();
00057 }
00058 
00059 void NetControl::SetServerType(ESocketType type)
00060 {
00061     mSocketType = type;
00062 }
00063 
00064 NetControl::ESocketType NetControl::GetServerType()
00065 {
00066     return mSocketType;
00067 }
00068 
00069 boost::shared_ptr<Socket> NetControl::CreateSocket(ESocketType type)
00070 {
00071     shared_ptr<Socket> socket;
00072 
00073     try
00074         {
00075             switch (type)
00076                 {
00077                 case ST_UDP:
00078                     socket = shared_ptr<Socket>(new UDPSocket());
00079                     break;
00080 
00081                 case ST_TCP:
00082                     socket = shared_ptr<Socket>(new TCPSocket());
00083                     break;
00084 
00085                 default:
00086                     cerr << "(NetControl) ERROR: unknown socket type "
00087                          << type << "\n";
00088                     break;
00089                 }
00090         }
00091 
00092     catch (OpenErr error)
00093         {
00094             cerr << "(NetControl) failed to create socket with '"
00095                  << error.what()
00096                  << endl;
00097         }
00098 
00099     return socket;
00100 }
00101 
00102 string NetControl::DescribeSocketType()
00103 {
00104     stringstream ss;
00105 
00106     switch (mSocketType)
00107         {
00108         case ST_UDP:
00109             ss << "UDP";
00110             break;
00111 
00112         case ST_TCP:
00113             ss << "TCP";
00114             break;
00115 
00116         default:
00117             ss << "(unknown socket type)";
00118             break;
00119         }
00120 
00121     ss << ":" << mLocalAddr.getPort();
00122 
00123     return ss.str();
00124 }
00125 
00126 void NetControl::InitSimulation()
00127 {
00128     // assert that the local port has been set
00129     if (mLocalAddr.getPort() == INADDR_ANY)
00130         {
00131             GetLog()->Error()
00132                 << "(NetControl) ERROR: local port has no been set in '"
00133                 << GetClass()->GetName() << "'\n";
00134             return;
00135         }
00136 
00137     GetLog()->Normal() << "(NetControl) '" << GetName()
00138                        << "' setting up a server on " << DescribeSocketType() << std::endl;
00139 
00140     mSocket = CreateSocket(mSocketType);
00141 
00142     if (mSocket.get() == 0)
00143         {
00144             return;
00145         }
00146 
00147   int ret = mSocket->setNonBlocking(true);
00148 
00149   if (ret < 0)
00150       {
00151           GetLog()->Error()
00152               << "(NetControl) failed to set server socket to non "
00153               << "blocking mode with '"
00154               << strerror(errno) << "'\n";
00155           mSocket->close();
00156           return;
00157       }
00158 
00159   try
00160       {
00161           mSocket->bind(mLocalAddr);
00162       }
00163 
00164   catch (BindErr error)
00165       {
00166           GetLog()->Error() << "(NetControl) failed to bind socket with '"
00167                             << error.what() << "'"
00168                             << endl;
00169 
00170           mSocket->close();
00171           return;
00172       }
00173 
00174   try
00175       {
00176           if (mSocketType == ST_TCP)
00177               {
00178 #ifdef SOMAXCONN
00179                   mSocket->listen(SOMAXCONN);
00180 #else
00181                   mSocket->listen(50);
00182 #endif
00183               }
00184       }
00185 
00186   catch (ListenErr error)
00187       {
00188           GetLog()->Error() << "(NetControl) failed to listen on socket with '"
00189                             << error.what() << "'"
00190                             << endl;
00191 
00192           mSocket->close();
00193           return;
00194       }
00195 
00196   // assure that a NetMessage object is registered
00197   mNetMessage = FindChildSupportingClass<NetMessage>();
00198 
00199   if (mNetMessage.get() == 0)
00200       {
00201           mNetMessage = shared_ptr<NetMessage>(new NetMessage());
00202       }
00203 }
00204 
00205 void NetControl::DoneSimulation()
00206 {
00207     // reset the cached NetMessage reference
00208     mNetMessage.reset();
00209 
00210     // close all client connections
00211     for (
00212          TAddrMap::iterator iter = mClients.begin();
00213          iter != mClients.end();
00214          ++iter
00215          )
00216         {
00217             RemoveClient((*iter).second->addr);
00218         }
00219 
00220     // shutdown the server socket
00221     mSocket->close();
00222     GetLog()->Normal() << "(NetControl) '" << GetName()
00223                        << "' closed server socket "
00224                        << DescribeSocketType() << std::endl;
00225     mSocket.reset();
00226 
00227     mClients.clear();
00228 }
00229 
00230 void NetControl::AddClient(const Addr& from, shared_ptr<Socket> socket)
00231 {
00232     shared_ptr<Client> client(new Client(mClientId,from,socket));
00233     mClients[from] = client;
00234 
00235     GetLog()->Normal()
00236         << "(NetControl) '" << GetName() << "' accepted a "
00237         << ((socket.get() != 0) ? "TCP" : "UDP")
00238         << " connection from '"
00239         << from.getHostStr() << ":" << from.getPort()
00240         << "' id " << mClientId
00241         << endl;
00242 
00243     mClientId++;
00244     ClientConnect(client);
00245 }
00246 
00247 void NetControl::RemoveClient(const Addr& from)
00248 {
00249     TAddrMap::iterator mapIter = mClients.find(from);
00250 
00251     if (mapIter == mClients.end())
00252         {
00253             GetLog()->Warning()
00254                 << "(NetControl) '" << GetName()
00255                 << "' RemoveClient called with an unknown client address\n";
00256             return;
00257         }
00258 
00259     shared_ptr<Client> client = (*mapIter).second;
00260     ClientDisconnect(client);
00261 
00262     shared_ptr<Socket> socket = client->socket;
00263 
00264     GetLog()->Normal()
00265         << "(NetControl) '" << GetName() << "' closing a "
00266         << ((socket.get() != 0) ? "TCP" : "UDP")
00267         << " connection from '"
00268         << from.getHostStr() << ":" << from.getPort()
00269         << "' id " << client->id << endl;
00270 
00271     if (socket.get() != 0)
00272         {
00273             socket->close();
00274         }
00275 
00276     mClients.erase(mapIter);
00277 }
00278 
00279 void NetControl::ClientConnect(shared_ptr<Client> /*client*/)
00280 {
00281     // empty callback, implemented in derived classes
00282 }
00283 
00284 void NetControl::ClientDisconnect(shared_ptr<Client> /*client*/)
00285 {
00286     // empty callback, implemented in derived classes
00287 }
00288 
00289 void NetControl::SendMessage(shared_ptr<Client> client, const string& msg)
00290 {
00291     if (client.get() == 0)
00292         {
00293             return;
00294         }
00295 
00296     int rval = 0;
00297     shared_ptr<Socket> socket = client->socket;
00298 
00299     if (socket.get() == 0)
00300         {
00301             // udp client
00302             if (mSocket.get() != 0)
00303                 {
00304                     rval = mSocket->send(msg.data(), msg.size(), client->addr);
00305                 }
00306         } else
00307             {
00308                 // tcp client
00309                 rval = socket->send(msg.data(), msg.size());
00310             }
00311 
00312     if (rval < 0)
00313         {
00314             GetLog()->Error()
00315                 << "(NetControl::SendMessage) ERROR: '" << GetName()
00316                 << "' send returned error '"
00317                 << strerror(errno) << "' " << endl;
00318         }
00319 }
00320 
00321 void NetControl::SendMessage(const Addr& addr, const string& msg)
00322 {
00323     TAddrMap::iterator iter = mClients.find(addr);
00324 
00325     if (iter == mClients.end())
00326         {
00327             GetLog()->Error()
00328                 << "(NetControl::SendMessage) ERROR: unknown client address '"
00329                 << addr.getHostStr() << ":" << addr.getPort() << "'\n";
00330             return;
00331         }
00332 
00333     SendMessage((*iter).second,msg);
00334 }
00335 
00336 void NetControl::AcceptTCPConnections()
00337 {
00338     if (
00339         (mSocketType != ST_TCP) ||
00340         (mSocket.get() == 0)
00341         )
00342         {
00343             return;
00344         }
00345 
00346     int fd = mSocket->getFD();
00347 
00348     fd_set readfds;
00349     FD_ZERO(&readfds);
00350     FD_SET(fd,&readfds);
00351 
00352     timeval time;
00353     time.tv_sec = 0;
00354     time.tv_usec = 0;
00355 
00356     for(;;)
00357         {
00358             int ret = select(fd+1, &readfds, 0, 0, &time);
00359 
00360             if (ret == 0)
00361                 {
00362                     // no more connections pending
00363                     break;
00364                 }
00365 
00366             if (ret < 0)
00367                 {
00368                     GetLog()->Error()
00369                         << "(NetControl) ERROR: '" << GetName()
00370                         << "' select returned error on server socket "
00371                         << DescribeSocketType()
00372                         << ' ' << strerror(errno) << "\n"
00373                         << "(NetControl) ERROR: closing server socket"
00374                         << endl;
00375 
00376                     mSocket->close();
00377                     mSocket.reset();
00378                     break;
00379                 }
00380 
00381             try
00382                 {
00383                     Addr addr;
00384                     shared_ptr<Socket> socket(mSocket->accept(addr));
00385 
00386                     int ret = socket->setNonBlocking(true);
00387 
00388                     if (ret < 0)
00389                         {
00390                             GetLog()->Error()
00391                                 << "(NetControl) failed to set client socket to"
00392                                 << " non blocking mode with '"
00393                                 << strerror(errno)
00394                                 << "'. closing connection\n";
00395 
00396                             socket->close();
00397                         } else
00398                             {
00399                                 AddClient(addr,socket);
00400                             }
00401                 }
00402 
00403             catch (AcceptErr error)
00404                 {
00405                     GetLog()->Error()
00406                         << "(NetControl) '" << GetName()
00407                         << "' failed to accept TCP connection with '"
00408                         << error.what() << endl;
00409                     break;
00410                 }
00411         }
00412 }
00413 
00414 void NetControl::CloseDeadConnections()
00415 {
00416     while (! mCloseClients.empty())
00417         {
00418             RemoveClient(mCloseClients.front());
00419             mCloseClients.pop_front();
00420         }
00421 }
00422 
00423 void NetControl::StartCycle()
00424 {
00425     // read any pending messages, for UDP new source addresses are
00426     // registered as new clients
00427     ReadMessages();
00428 
00429     // if we manage a TCP server socket accept new client connections
00430     AcceptTCPConnections();
00431 }
00432 
00433 void NetControl::EndCycle()
00434 {
00435     // close connections marked as dead during this cycle
00436     CloseDeadConnections();
00437 }
00438 
00439 void NetControl::ReadMessages()
00440 {
00441     switch (mSocketType)
00442         {
00443         case ST_TCP:
00444             ReadTCPMessages();
00445             break;
00446 
00447         case ST_UDP:
00448             ReadUDPMessages();
00449             break;
00450 
00451         default:
00452             break;
00453         }
00454 }
00455 
00456 void NetControl::StoreFragment(const Addr& addr, int size)
00457 {
00458     TBufferMap::iterator msgIter = mBuffers.find(addr);
00459     if (msgIter == mBuffers.end())
00460         {
00461             // allocate a new NetBuffer for the client
00462             mBuffers[addr] =
00463                 (shared_ptr<NetBuffer>
00464                  (new NetBuffer(addr,string(mBuffer.get(),size)))
00465                  );
00466         } else
00467             {
00468                 // append to an existing NetBuffer
00469                 (*msgIter).second->AddFragment(string(mBuffer.get(),size));
00470             }
00471 }
00472 
00473 void NetControl::ReadUDPMessages()
00474 {
00475     if (mSocket.get() == 0)
00476         {
00477             return;
00478         }
00479 
00480     int fd = mSocket->getFD();
00481 
00482     fd_set readfds;
00483     FD_ZERO(&readfds);
00484     FD_SET(fd,&readfds);
00485 
00486     timeval time;
00487     time.tv_sec = 0;
00488     time.tv_usec = 0;
00489 
00490     for(;;)
00491         {
00492             int ret = select(fd+1, &readfds, 0, 0, &time);
00493 
00494             if (ret == 0)
00495                 {
00496                     // no data available
00497                     break;
00498                 }
00499 
00500             if (ret < 0)
00501                 {
00502                     GetLog()->Error()
00503                         << "(NetControl) ERROR: ReadUDPSocket '" << GetName()
00504                         << "' select returned error on server socket "
00505                         << DescribeSocketType()
00506                         << ' ' << strerror(errno) << endl;
00507                     break;
00508                 }
00509 
00510             // read fragment
00511             Addr from;
00512             int rval = mSocket->recv(mBuffer.get(), mBufferSize, from);
00513 
00514             if (rval < 0)
00515                 {
00516                     GetLog()->Error()
00517                         << "(NetControl) ERROR: ReadUDPSocket '" << GetName()
00518                         << "' recv returned error '"
00519                         << strerror(errno) << "' " << endl;
00520                     continue;
00521                 }
00522 
00523             TAddrMap::iterator iter =  mClients.find(from);
00524             if (iter == mClients.end())
00525                 {
00526                     // a new client connected
00527                     AddClient(from);
00528                 }
00529 
00530             StoreFragment(from,rval);
00531         }
00532 }
00533 
00534 void NetControl::ReadTCPMessages()
00535 {
00536     // generate a set of client socket fds
00537     fd_set client_fds;
00538     FD_ZERO(&client_fds);
00539 
00540     int maxFd = 0;
00541 
00542     for (
00543          TAddrMap::iterator iter=mClients.begin();
00544          iter != mClients.end();
00545          ++iter
00546          )
00547         {
00548             const int fd = (*iter).second->socket->getFD();
00549             maxFd = std::max<int>(fd,maxFd);
00550             FD_SET(fd,&client_fds);
00551         }
00552 
00553     // test for pending fragments
00554     for(;;)
00555         {
00556             timeval time;
00557             time.tv_sec = 0;
00558             time.tv_usec = 0;
00559 
00560             fd_set test_fds = client_fds;
00561             int ret = select(maxFd+1, &test_fds, 0, 0, &time);
00562 
00563             if (ret == 0)
00564                 {
00565                     // no data available
00566                     break;
00567                 }
00568 
00569             if (ret < 0)
00570                 {
00571                     GetLog()->Error()
00572                         << "(NetControl) ERROR: '" << GetName()
00573                         << "' select returned error on client sockets '"
00574                         << strerror(errno) << "' " << endl;
00575 
00576                     break;
00577                 }
00578 
00579             // read fragments
00580             for (
00581                  TAddrMap::iterator iter=mClients.begin();
00582                  iter != mClients.end();
00583                  ++iter
00584                  )
00585                 {
00586                     const int fd = (*iter).second->socket->getFD();
00587                     if (! FD_ISSET(fd, &test_fds))
00588                         {
00589                             continue;
00590                         }
00591 
00592                     // read a fragment
00593                     shared_ptr<Client>& client = (*iter).second;
00594                     int rval = client->socket->recv(mBuffer.get(),mBufferSize);
00595 
00596                     if (rval > 0)
00597                         {
00598                             StoreFragment(client->addr,rval);
00599                         } else
00600                             {
00601                                 if (rval < 0)
00602                                     {
00603                                         GetLog()->Error()
00604                                             << "(NetControl) ERROR: '" << GetName()
00605                                             << "' recv returned error on a client socket '"
00606                                             << strerror(errno) << "' " << endl;
00607                                         continue;
00608                                     }
00609 
00610                                 // (rval==0) indicates a close() on
00611                                 // the client side
00612 
00613                                 // mark the client connection to be
00614                                 // closed and exclude it from further
00615                                 // select() calls
00616                                 FD_CLR(fd,&client_fds);
00617                                 mCloseClients.push_back(client->addr);
00618                             }
00619                 }
00620         }
00621 }
00622 

Generated on Thu Apr 6 15:25:39 2006 for rcssserver3d by  doxygen 1.4.4