SocketUDP.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CERTI - HLA RunTime Infrastructure
00003 // Copyright (C) 2002-2005  ONERA
00004 //
00005 // This program is free software ; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation ; either version 2 of
00008 // the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful, but
00011 // WITHOUT ANY WARRANTY ; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this program ; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018 // ----------------------------------------------------------------------------
00019 
00020 
00021 
00022 #include "certi.hh"
00023 #include "SocketUDP.hh"
00024 #include "PrettyDebug.hh"
00025 #include <cstdlib>
00026 #include <cstring>
00027 
00028 #ifndef MAXHOSTNAMELEN
00029 #define MAXHOSTNAMELEN 4096
00030 #endif
00031 
00032 #ifdef _WIN32
00033 #include "SocketTCP.hh"
00034 #else
00035 #include <iostream>
00036 #include <sstream>
00037 #include <unistd.h>
00038 #include <strings.h>
00039 #endif
00040 #include <assert.h>
00041 #include <errno.h>
00042 
00043 using std::cout ;
00044 using std::endl ;
00045 
00046 namespace certi {
00047 
00048 static pdCDebug D("SOCKUDP", "(SocketUDP) - ");
00049 
00050 // ----------------------------------------------------------------------------
00051 void
00052 SocketUDP::attach(int socket_ouvert, unsigned long Adresse, unsigned int port)
00053     throw (NetworkError,
00054            NetworkSignal)
00055 {
00056     assert(!_est_init_udp);
00057 
00058     PhysicalLink = false ;
00059 
00060     _socket_udp = socket_ouvert ;
00061     // Building Distant Address
00062     memset((struct sockaddr_in *) &sock_distant, 0, sizeof(struct sockaddr_in));
00063 
00064     sock_distant.sin_addr.s_addr = htonl(Adresse);
00065     sock_distant.sin_family = AF_INET ;
00066     sock_distant.sin_port = port ;
00067 
00068     _est_init_udp = true ;
00069 
00070     D.Out(pdDebug, "Attaching the federate to his address and to his peer...");
00071 }
00072 
00073 // ----------------------------------------------------------------------------
00074 int
00075 SocketUDP::bind()
00076 {
00077     assert(!_est_init_udp);
00078 
00079     long result = ::bind(_socket_udp, (sockaddr *)&sock_local,
00080                          sizeof(struct sockaddr_in));
00081 
00082     return ((result == 0) ? 1 : 0);
00083 }
00084 
00085 // ----------------------------------------------------------------------------
00087 void
00088 SocketUDP::createConnection(const char *server_name, unsigned int port)
00089     throw (NetworkError)
00090 {
00091 // unsigned long addr = 0 ;
00092 struct sockaddr_in sock_temp ;
00093 char localhost[4096] ;
00094 std::stringstream msg;
00095 struct hostent * hp_local;
00096 
00097 #ifdef _WIN32                               //netDot
00098     int taille = sizeof(struct sockaddr_in);
00099 #else
00100     socklen_t taille = sizeof(struct sockaddr_in);
00101 #endif
00102 
00103 assert(!_est_init_udp);
00104 
00105 // Building Local Address
00106 memset(&sock_local, 0, sizeof(struct sockaddr_in));
00107 hp_local = NULL;
00108 
00109 gethostname(localhost, 4096);
00110 
00111 if ((hp_local = gethostbyname(localhost)) == NULL)
00112     {
00113         msg << "gethostbyname gave NULL answer for hostname <"
00114             << localhost 
00115             << "> with error <"
00116             << strerror(errno) 
00117             << ">";
00118        throw NetworkError(msg.str().c_str());
00119     }
00120 
00121 #ifdef _WIN32
00122     memcpy((char*)&sock_local.sin_addr,(char *)hp_local->h_addr,    hp_local->h_length);
00123 #else
00124     bcopy((char*)hp_local->h_addr, (char *) &sock_local.sin_addr,hp_local->h_length);
00125 #endif
00126 
00127 // lors du BIND, le systeme alloue un port libre au socket _sock_udp
00128 sock_local.sin_family = AF_INET;
00129 sock_local.sin_port = 0 ;
00130 
00131 if (!open())
00132     {
00133     msg << "Cannot Open Socket open gave error < "
00134         <<  strerror(errno) 
00135         << ">"; 
00136     throw NetworkError(msg.str().c_str());
00137     }
00138     
00139 if (!bind())
00140     {
00141     msg << "Cannot Bind Socket bind gave error < "
00142             <<  strerror(errno) 
00143             << ">"; 
00144     throw NetworkError(msg.str().c_str());
00145     }
00146 
00147 // recuperation du port lie au socket _socket_udp
00148 getsockname(_socket_udp, (sockaddr *)&sock_temp, &taille);
00149 //HPUX: getsockname(_socket_udp, (sockaddr *)&sock_temp, (int*)&taille);
00150 sock_local.sin_port = sock_temp.sin_port ;
00151 _est_init_udp = true ;
00152 }
00153 
00154 // ----------------------------------------------------------------------------
00156 void
00157 SocketUDP::createUDPServer(unsigned int port)
00158     throw (NetworkError, NetworkSignal)
00159 {
00160   assert(!_est_init_udp);
00161   
00162   char localhost[MAXHOSTNAMELEN+1] ;
00163   std::stringstream msg;
00164   struct hostent * hp_local=NULL;
00165 
00166   // Building Local Address
00167   memset((struct sockaddr_in *) &sock_local, 0, sizeof(struct sockaddr_in));
00168 
00169   gethostname(localhost, MAXHOSTNAMELEN);
00170 
00171   hp_local = (struct hostent *) gethostbyname(localhost);
00172   if (NULL == hp_local) 
00173     {
00174      msg << "gethostbyname gave NULL answer for hostname <"
00175                 << localhost 
00176                 << "> with error <"
00177                 << strerror(errno) 
00178                 << ">";
00179             //perror("SocketUDP: gethostbyname");
00180            throw NetworkError(msg.str().c_str());       
00181     }
00182 
00183    memcpy((char *) &sock_local.sin_addr,(char *)hp_local->h_addr, hp_local->h_length);
00184    sock_local.sin_family = hp_local->h_addrtype ;
00185    sock_local.sin_port   = htons((u_short)port);
00186 
00187 if (!open()) 
00188     {
00189     perror("SocketUDP: Open");
00190     throw NetworkError("Cannot open UDP Socket");
00191     }
00192 
00193 if (!bind()) 
00194     {
00195     perror("SocketUDP: Bind");
00196     throw NetworkError("Cannot bind UDP Socket");
00197     }
00198 
00199 _est_init_udp = true ;
00200 }
00201 
00202 // ----------------------------------------------------------------------------
00203 SocketUDP::SocketUDP()
00204 {
00205 _est_init_udp = false ;
00206     _socket_udp = 0;
00207 
00208 hp_distant = NULL ;
00209 PhysicalLink = true ;
00210 
00211 BufferSize = 0 ;
00212 SentBytesCount = 0 ;
00213 RcvdBytesCount = 0 ;
00214 
00215 #ifdef _WIN32                               //netDot
00216     SocketTCP::winsockStartup();
00217 #endif
00218 }
00219 
00220 // ----------------------------------------------------------------------------
00221 SocketUDP::~SocketUDP()
00222 {
00223 // Fermeture
00224 if (_est_init_udp)
00225     close();
00226 
00227 #ifdef _WIN32                               //netDot
00228     SocketTCP::winsockShutdown();
00229 #endif
00230 
00231 #ifdef RTI_PRINTS_STATISTICS
00232     cout << " UDP Socket " ;
00233     cout.width(2);
00234     cout << _socket_udp << " : total = " ;
00235     cout.width(9);
00236     cout << SentBytesCount << "b sent " << endl ;
00237     cout << " UDP Socket " ;
00238     cout.width(2);
00239     cout << _socket_udp << " : total = " ;
00240     cout.width(9);
00241     cout << RcvdBytesCount << "b received" << endl ;
00242 #endif
00243 }
00244 
00245 // ----------------------------------------------------------------------------
00246 void
00247 SocketUDP::send(const unsigned char * Message, size_t Size)
00248     throw (NetworkError, NetworkSignal)
00249 {
00250     
00251 D.Out(pdDebug, "Beginning to send UDP message... Size = %ld", Size);
00252 assert(_est_init_udp);
00253 
00254 int sent = sendto(_socket_udp, (char*)Message, Size, 0,
00255       (struct sockaddr *)&sock_distant, sizeof(sock_distant));
00256 if (sent < 0) 
00257     {
00258     perror("Sendto");
00259     throw NetworkError("cannot sendto");
00260     };
00261 D.Out(pdDebug, "Sent UDP message.");
00262 SentBytesCount += sent ;
00263 }
00264 
00265 // ----------------------------------------------------------------------------
00266 void
00267 SocketUDP::close()
00268 {
00269 if (_est_init_udp) 
00270     {
00271     D.Out(pdDebug, "Closing UDP object...");
00272     _est_init_udp = false ;
00273     if (PhysicalLink) 
00274         {
00275         D.Out(pdDebug, "Closing physical UDP link...");
00276         #ifdef _WIN32                               //netDot
00277               ::closesocket(_socket_udp);
00278         #else
00279 			  ::close(_socket_udp);
00280         #endif
00281         }
00282     }
00283 }
00284 
00285 // ----------------------------------------------------------------------------
00286 unsigned long
00287 SocketUDP::getAddr() const
00288 {
00289 D.Out(pdDebug, "Hostname is %ul...", sock_local.sin_addr.s_addr);
00290 return(sock_local.sin_addr.s_addr);
00291 }
00292 
00293 // ----------------------------------------------------------------------------
00294 unsigned int
00295 SocketUDP::getPort() const
00296 {
00297 D.Out(pdDebug, "UDP port is %ud...", sock_local.sin_port);
00298 return sock_local.sin_port ;
00299 }
00300 
00301 // ----------------------------------------------------------------------------
00305 bool
00306 SocketUDP::isDataReady() const
00307 {
00308  return BufferSize > 0 ;
00309 }
00310 
00311 // ----------------------------------------------------------------------------
00312 int SocketUDP::open()
00313 {
00314 #ifdef _WIN32                               //netDot
00315     assert(SocketTCP::winsockInitialized());
00316 #endif
00317 
00318  _socket_udp = socket(AF_INET, SOCK_DGRAM, 0);
00319  return _socket_udp >= 0 ;
00320 }
00321 
00322 // ----------------------------------------------------------------------------
00323 void
00324 SocketUDP::receive(void * Message, unsigned long Size)
00325     throw (NetworkError, NetworkSignal)
00326 {
00327 #ifdef _WIN32                               //netDot
00328     int taille = sizeof(struct sockaddr_in);
00329 #else
00330     socklen_t taille = sizeof(struct sockaddr_in);
00331 #endif
00332 
00333 int CR ;
00334 
00335 assert(_est_init_udp);
00336 
00337 D.Out(pdDebug, "Beginning to receive UDP message...");
00338 if (BufferSize == 0) 
00339     {
00340     CR = recvfrom(_socket_udp,
00341     Buffer, BUFFER_MAXSIZE, 0,
00342     (struct sockaddr *)&sock_source, &taille);
00343     //HPUX:(struct sockaddr *)&sock_source, (int*) &taille);
00344     if (CR <= 0) 
00345         {
00346         perror("Recvfrom");
00347         throw NetworkError("cannot recvfrom");
00348         }
00349     else 
00350         {
00351         RcvdBytesCount += CR ;
00352         BufferSize += CR ;
00353         }
00354     }
00355 
00356 if (BufferSize < Size) 
00357     {
00358     perror("Taille du Buffer inferieure a celle demandee");
00359     throw NetworkError("");
00360     }
00361 else 
00362     {
00363     BufferSize -= Size ;
00364     memcpy(Message, (void *)Buffer, Size);
00365     memmove((void *) Buffer, (void *)(Buffer + Size), BufferSize);
00366     }
00367 }
00368 
00369 // ----------------------------------------------------------------------------
00370 unsigned long
00371 SocketUDP::returnAdress() const
00372 {
00373 D.Out(pdDebug, "Retourner Adresse Machine locale...");
00374 return getAddr();
00375 }
00376 
00377 // ----------------------------------------------------------------------------
00378 #ifdef _WIN32
00379     SOCKET  SocketUDP::returnSocket()
00380 #else
00381     int     SocketUDP::returnSocket()
00382 #endif
00383 {
00384 D.Out(pdDebug, "Retourner Socket UDP...");
00385 return _socket_udp ;
00386 }
00387 
00388 // ----------------------------------------------------------------------------
00389 void
00390 SocketUDP::setPort(unsigned int port)
00391 {
00392 D.Out(pdDebug, "Affectation du Port UDP...");
00393 sock_local.sin_port=port ;
00394 }
00395 
00396 } // namespace certi

Generated on Thu Apr 30 15:53:50 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5