# 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