00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "certi.hh"
00022 #include "SocketUN.hh"
00023
00024 #if defined(RTIA_USE_TCP)
00025 #include "SocketTCP.hh"
00026 #if not defined(_WIN32)
00027 #include <cstring>
00028 #include <cerrno>
00029 #endif
00030 #else
00031 #include <unistd.h>
00032 #include <strings.h>
00033 #include <sstream>
00034 #include <string>
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #include <sys/un.h>
00038 #endif
00039
00040 #include <iostream>
00041 #include <assert.h>
00042
00043 using std::ostringstream ;
00044 using std::string ;
00045 using std::cout ;
00046 using std::endl ;
00047
00048 namespace certi {
00049 static PrettyDebug G("GENDOC",__FILE__);
00050 #define MAX_ATTEMPTS 3
00051
00052
00054 void
00055 SocketUN::acceptUN(int RTIA_port)
00056 {
00057 #if defined(RTIA_USE_TCP)
00058 struct sockaddr_in nom_client, nom_serveur;
00059 int lg_nom;
00060 int result;
00061
00062 #if defined(_WIN32)
00063 assert(SocketTCP::winsockInitialized());
00064 int socklen;
00065 #else
00066 socklen_t socklen;
00067 #endif
00068
00069 if((sock_connect=socket(AF_INET,SOCK_STREAM,0)) < 0)
00070 error("socket");
00071
00072 memset(&nom_serveur, 0, sizeof(nom_serveur));
00073
00074 nom_serveur.sin_family = AF_INET;
00075 nom_serveur.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00076
00077
00078 int tcpport;
00079 if (RTIA_port>0) {
00080 tcpport = RTIA_port;
00081 } else {
00082 tcpport = getpid();
00083 }
00084
00085
00086 if (tcpport > 65535)
00087 throw RTIinternalError("TCP Port too big.");
00088
00089 nom_serveur.sin_port = htons(tcpport);
00090
00091 lg_nom = sizeof(nom_serveur);
00092
00093 result = ::bind(sock_connect,(sockaddr *)&nom_serveur, lg_nom);
00094
00095 if(result <0)
00096 {
00097
00098 error("bind");
00099 }
00100 pD->Out(pdInit, "Server: Bind succeeded, now listening.");
00101 #else
00102
00103 struct sockaddr_un nom_client, nom_serveur ;
00104 socklen_t socklen ;
00105
00106 pD->Out(pdInit, "Opening Server UNIX Socket.");
00107
00108
00109 if ((sock_connect = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
00110 {
00111 pD->Out(pdError, "Cannot open Server UNIX Socket.");
00112 error("socket");
00113 }
00114
00115 pD->Out(pdInit, "Server has got UNIX Socket FpD->");
00116
00117
00118 memset(&nom_serveur, 0, sizeof(nom_serveur));
00119
00120 nom_serveur.sun_family = AF_UNIX ;
00121
00122 if (strlen(NOM_FICHIER_SOCKET) > 90)
00123 throw RTIinternalError("NOM_FICHIER_SOCKET too long.");
00124
00125 char buffer[256] ;
00126 sprintf( buffer, "%s.%d", NOM_FICHIER_SOCKET, getpid() ) ;
00127 name = buffer ;
00128 strcpy( nom_serveur.sun_path, name.c_str() );
00129
00130
00131
00132 if (bind(sock_connect, (struct sockaddr*)&nom_serveur,
00133 sizeof(struct sockaddr_un)) < 0)
00134 error("bind");
00135
00136 pD->Out(pdInit, "Server: Bind succeeded, now listening.");
00137 #endif
00138
00139
00140 if (listen(sock_connect, 10) == -1)
00141 error("listen");
00142
00143 pD->Out(pdInit, "Server: Listen returned, now accepting.");
00144
00145
00146 socklen = sizeof(struct sockaddr_in);
00147 if ((_socket_un = accept(sock_connect,
00148 (struct sockaddr*)&nom_client,
00149 &socklen)) < 0)
00150
00151 error("accept");
00152
00153 pD->Out(pdInit, "Server: Accept OK, server running.");
00154
00155 _est_init_un = true ;
00156 _est_serveur = true ;
00157 }
00158
00159
00161 #ifdef RTIA_USE_TCP
00162 void SocketUN::connectUN(int Server_pid)
00163 #else
00164 int SocketUN::connectUN(pid_t Server_pid)
00165 #endif
00166 {
00167 int Attempt = 0 ;
00168 int Result = 0 ;
00169
00170 #if defined(RTIA_USE_TCP)
00171 struct sockaddr_in nom_serveur;
00172 int lg_nom;
00173 #ifdef _WIN32
00174 struct hostent *hptr = NULL;
00175 assert(SocketTCP::winsockInitialized());
00176 #endif
00177 #else
00178 struct sockaddr_un nom_serveur;
00179 #endif
00180
00181 char buffer[256] ;
00182 sprintf( buffer, "%s.%d", NOM_FICHIER_SOCKET, Server_pid ) ;
00183 name = buffer ;
00184
00185 while (Attempt < MAX_ATTEMPTS)
00186 {
00187 pD->Out(pdInit, "Opening Client UNIX Socket.");
00188
00189
00190 #if defined(RTIA_USE_TCP)
00191 if((_socket_un = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00192 error("socket");
00193
00194 pD->Out(pdInit, "Client has got UNIX Socket FpD->");
00195
00196
00197 memset(&nom_serveur, 0, sizeof(nom_serveur));
00198
00199 nom_serveur.sin_family = AF_INET;
00200 nom_serveur.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00201
00202 if (Server_pid > 65535)
00203 throw RTIinternalError("NOM_FICHIER_SOCKET too long.");
00204 nom_serveur.sin_port= htons(Server_pid);
00205
00206 lg_nom = sizeof(nom_serveur);
00207 Result = ::connect(_socket_un,(sockaddr *)&nom_serveur, lg_nom);
00208
00209
00210 #else
00211 if ((_socket_un = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
00212 error("socket");
00213
00214 pD->Out(pdInit, "Client has got UNIX Socket FpD->");
00215
00216 memset(&nom_serveur, 0, sizeof(nom_serveur));
00217 nom_serveur.sun_family = AF_UNIX ;
00218
00219 if (strlen(NOM_FICHIER_SOCKET) > 90)
00220 throw RTIinternalError("NOM_FICHIER_SOCKET too long.");
00221 strcpy( nom_serveur.sun_path, name.c_str() );
00222 Result = connect(_socket_un,
00223 (struct sockaddr*) &nom_serveur,
00224 sizeof(struct sockaddr_un));
00225 pD->Out(pdInit, "Client: Connect returned %d.", Result);
00226 #endif
00227
00228 if (Result == 0)
00229 break ;
00230
00231
00232 pD->Out(pdError, "SocketUN: Connect, attempt #%d out of %d failed",
00233 Attempt + 1, MAX_ATTEMPTS);
00234 sleep(1);
00235 Attempt ++ ;
00236 }
00237
00238 pD->Out(pdInit, "Client: Done.");
00239
00240 if( Result == 0 )
00241 _est_init_un = true ;
00242
00243 #ifdef _WIN32
00244 return ;
00245 #else
00246 return Result ;
00247 #endif
00248 }
00249
00250
00252 SocketUN::SocketUN(SignalHandlerType theType)
00253 : _socket_un(0), _est_serveur(false), _est_init_un(false),
00254 HandlerType(theType), SentBytesCount(0), RcvdBytesCount(0)
00255 {
00256 #ifdef _WIN32
00257 SocketTCP::winsockStartup();
00258 #endif
00259
00260 #ifdef SOCKUN_BUFFER_LENGTH
00261 RBLength = 0 ;
00262 #endif
00263
00264 pD = new pdCDebug("SOCKUN", "SocketUN");
00265 pD->Out(pdInit, "UNIX Socket created.");
00266 }
00267
00268
00270 SocketUN::~SocketUN()
00271 {
00272 if (_est_init_un)
00273 {
00274 #ifdef _WIN32
00275 closesocket(_socket_un);
00276 if (_est_serveur)
00277 closesocket(sock_connect);
00278 #else
00279 close(_socket_un);
00280 if (_est_serveur)
00281 close(sock_connect);
00282 unlink(name.c_str());
00283 #endif
00284
00285 if (_est_serveur)
00286 pD->Out(pdTerm, "Server: Closed all sockets.");
00287 else
00288 pD->Out(pdTerm, "Client: Closed all sockets.");
00289 }
00290
00291 #ifdef _WIN32
00292 SocketTCP::winsockShutdown();
00293 #endif
00294
00295 pD->Out(pdCom, "Unix Socket %2d : total = %9db sent", _socket_un, SentBytesCount ) ;
00296 pD->Out(pdCom, "Unix Socket %2d : total = %9db received", _socket_un, RcvdBytesCount ) ;
00297
00298 delete pD ;
00299 }
00300
00301
00303
00306 void
00307 SocketUN::send(const unsigned char *buffer, size_t size)
00308 throw (NetworkError, NetworkSignal)
00309 {
00310 long sent = 0 ;
00311 unsigned long total_sent = 0 ;
00312
00313
00314 assert(_est_init_un);
00315
00316 pD->Out(pdTrace, "Beginning to send UN message...");
00317
00318 while (total_sent < size)
00319 {
00320 #ifdef _WIN32
00321 sent = ::send(_socket_un, (char *) buffer + total_sent, size - total_sent, 0);
00322 #else
00323 sent = write(_socket_un, (char *) buffer + total_sent, size - total_sent);
00324 #endif
00325
00326 if (sent > 0)
00327 {
00328 total_sent += sent ;
00329 pD->Out(pdTrace, "Sent %ld bytes out of %ld.", total_sent, size);
00330 }
00331 else
00332 {
00333 if (sent < 0)
00334 {
00335 pD->Out(pdExcept, "Error while sending on UN socket.");
00336
00337 #ifdef _WIN32
00338 if(WSAGetLastError() == WSAEINTR)
00339 #else
00340 if(errno == EINTR)
00341 #endif
00342 {
00343 if (HandlerType == stSignalInterrupt) throw NetworkSignal("");
00344 else pD->Out(pdExcept, "EmettreUN ignoring signal interruption.");
00345 }
00346 else
00347 {
00348 perror("UN Socket(EmettreUN) : ");
00349 throw NetworkError("Error while sending UN message.");
00350 } }
00351
00352 if (sent == 0)
00353 {
00354 pD->Out(pdExcept, "No data could be sent, connection closed?.");
00355 throw NetworkError("Could not send any data on UN socket.");
00356 }
00357 }
00358 }
00359 SentBytesCount += total_sent ;
00360
00361 }
00362
00363
00365 void SocketUN::error(const char *msg) throw (NetworkError)
00366 {
00367 std::stringstream smsg;
00368
00369 smsg << "SocketUN::error <"
00370 << strerror(errno)
00371 << "> msg = <"
00372 << msg <<">";
00373 throw NetworkError(smsg.str().c_str());
00374 }
00375
00376
00380 bool
00381 SocketUN::isDataReady()
00382 {
00383 #ifdef SOCKUN_BUFFER_LENGTH
00384 return RBLength > 0 ;
00385 #else
00386 return false ;
00387 #endif
00388 }
00389
00390
00391 #ifdef _WIN32
00392 SOCKET
00393 #else
00394 int
00395 #endif
00396 SocketUN::returnSocket()
00397 {
00398 return _socket_un;
00399 }
00400
00401
00402 void
00403 SocketUN::receive(const unsigned char *buffer, size_t Size)
00404 throw (NetworkError, NetworkSignal)
00405 {
00406
00407
00408 assert(_est_init_un);
00409
00410 long nReceived = 0 ;
00411
00412 #ifndef SOCKUN_BUFFER_LENGTH
00413 unsigned long RBLength = 0 ;
00414 #endif
00415
00416 pD->Out(pdTrace, "Beginning to receive U/W message...(Size %ld)",Size);
00417
00418 while (RBLength < Size)
00419 {
00420 #ifdef _WIN32
00421 #ifdef SOCKUN_BUFFER_LENGTH
00422 nReceived = recv(_socket_un,
00423 ReadBuffer + RBLength,
00424 SOCKUN_BUFFER_LENGTH - RBLength,
00425 0);
00426 #else
00427 nReceived = recv(_socket_un,
00428 (char *) buffer + RBLength,
00429 Size - RBLength,
00430 0);
00431 #endif
00432 #else
00433 #ifdef SOCKUN_BUFFER_LENGTH
00434 nReceived = read(_socket_un, ReadBuffer + RBLength, SOCKUN_BUFFER_LENGTH - RBLength);
00435 #else
00436 nReceived = read(_socket_un, (char *) buffer + RBLength, Size - RBLength);
00437 #endif
00438 #endif
00439
00440 if (nReceived < 0)
00441 {
00442 pD->Out(pdExcept, "Error while receiving on UN socket.");
00443
00444 #ifdef _WIN32
00445 if(WSAGetLastError() == WSAEINTR)
00446 #else
00447 if(errno == EINTR)
00448 #endif
00449 {
00450 if (HandlerType == stSignalInterrupt)
00451 throw NetworkSignal("");
00452 else
00453 pD->Out(pdExcept, "RecevoirUN ignoring signal interruption.");
00454 }
00455 else
00456 {
00457 perror("UN Socket(RecevoirUN) : ");
00458 throw NetworkError("Error while receiving UN message.");
00459 }
00460 }
00461
00462 if (nReceived == 0)
00463 {
00464 pD->Out(pdExcept, "UN connection has been closed by peer.");
00465 throw NetworkError("Connection closed by client.");
00466 }
00467 else if (nReceived > 0)
00468 {
00469 RBLength += nReceived ;
00470 RcvdBytesCount += nReceived ;
00471 }
00472 }
00473 pD->Out(pdTrace, "Received %ld bytes out of %ld.", RBLength, Size);
00474
00475 #ifdef SOCKUN_BUFFER_LENGTH
00476 memcpy(const_cast<unsigned char *>(buffer), ReadBuffer, Size);
00477 memmove((void *) ReadBuffer,
00478 (void *)(ReadBuffer + Size),
00479 RBLength - Size);
00480 RBLength -= Size ;
00481 #endif
00482
00483 }
00484
00485 }