00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "TGo4Socket.h"
00015
00016 #include <string.h>
00017
00018 #ifndef WIN32
00019 #include <sys/types.h>
00020 #include <sys/socket.h>
00021 #endif
00022
00023 #include "TMutex.h"
00024 #include "TMessage.h"
00025 #include "TSystem.h"
00026 #include "TSocket.h"
00027 #include "TServerSocket.h"
00028 #include "RVersion.h"
00029
00030 #include "TGo4Log.h"
00031 #include "TGo4LockGuard.h"
00032 #include "TGo4Buffer.h"
00033 #include "TGo4SocketSignalHandler.h"
00034
00035 const Int_t TGo4Socket::fguOPENWAIT=200;
00036 const Int_t TGo4Socket::fgiOPENCYCLES=6;
00037 const Int_t TGo4Socket::fgiBUFLENGTH=256;
00038 const Int_t TGo4Socket::fgiBUFINITSIZE=65536;
00039 const Int_t TGo4Socket::fgiBUFEXTRASPACE=8;
00040 const char* TGo4Socket::fgcGOON = "-I- go on";
00041
00042
00043 #if ROOT_VERSION_CODE > ROOT_VERSION(4,3,2)
00044
00045 const Int_t TGo4Socket::fgiISOWNER = TBuffer::kIsOwner;
00046 #else
00047 const Int_t TGo4Socket::fgiISOWNER = BIT(14);
00048
00049 #endif
00050
00051
00052
00053 TGo4Socket::TGo4Socket(Bool_t IsClient) :
00054 fbClientMode(IsClient),
00055 fbOpen(kFALSE),
00056 fxSocket(0),
00057 fxServerSocket(0),
00058 fiPort(0),
00059 fxLocalBuffer(0),
00060 fxBuffer(0)
00061 {
00062 GO4TRACE((14,"TGo4Socket::TGo4Socket(Bool_t)", __LINE__, __FILE__));
00063
00064 fxBuffer = new TGo4Buffer(TBuffer::kRead, TGo4Socket::fgiBUFINITSIZE);
00065
00066
00067 TGo4SocketSignalHandler::SetSigWINCH();
00068
00069
00070 TGo4SocketSignalHandler::DisableSigPipe();
00071
00072 fxLocalBuffer = new char [TGo4Socket::fgiBUFLENGTH];
00073 if(fbClientMode)
00074 TGo4Log::Debug(" Created new Go4Socket in client mode ");
00075 else
00076 TGo4Log::Debug(" Created new Go4Socket in server mode ");
00077 }
00078
00079 TGo4Socket::~TGo4Socket()
00080 {
00081 GO4TRACE((14,"TGo4Socket::~TGo4Socket()", __LINE__, __FILE__));
00082
00083 if (fxBuffer!=0) {
00084
00085 delete fxBuffer;
00086 fxBuffer = 0;
00087 }
00088
00089 if (fxLocalBuffer) {
00090 delete [] fxLocalBuffer;
00091 fxLocalBuffer = 0;
00092 }
00093
00094 if(fxSocket) {
00095 fxSocket->Close();
00096 delete fxSocket;
00097 fxSocket = 0;
00098 }
00099
00100 if(fxServerSocket) {
00101 fxServerSocket->Close();
00102 delete fxServerSocket;
00103 fxServerSocket = 0;
00104 }
00105 }
00106
00107 Int_t TGo4Socket::Open(const char* host, Int_t port, Bool_t keepservsock)
00108 {
00109 GO4TRACE((12,"TGo4Socket::Open(const char* host, Int_t port)", __LINE__, __FILE__));
00110
00111 if(fbOpen) return 1;
00112
00113 Int_t rev=0;
00114
00115 if(fbClientMode) {
00116
00117 fxSocket = new TSocket(host, port);
00118 Int_t maxcounter=0;
00119 while(!fxSocket->IsValid())
00120 {
00121 if(++maxcounter> TGo4Socket::fgiOPENCYCLES)
00122 {
00123 TGo4Log::Debug(" Socket: Open timeout!!");
00124 break;
00125 }
00126 else
00127 {
00128 TGo4Log::Debug(" Socket: Open retry %d ", maxcounter);
00129 delete fxSocket;
00130 gSystem->Sleep(TGo4Socket::fguOPENWAIT);
00131 fxSocket = new TSocket(host, port);
00132 }
00133 }
00134 if(!fxSocket->IsValid())
00135 {
00136 TGo4Log::Debug(" Socket: Open(const char* host, Int_t port ) as Client failed ");
00137 fiPort=0;
00138 return -8;
00139 }
00140 else
00141 {
00142 fxSocket->SetOption(kNoBlock,0);
00143 fiPort=fxSocket->GetLocalPort();
00144 }
00145 char str[32];
00146 fxSocket->Recv(str, 32);
00147 if(!strcmp(str,TGo4Socket::fgcGOON))
00148 {
00149
00150 fbOpen = kTRUE;
00151 rev=0;
00152 TGo4Log::Debug(" Socket: Connection Established ");
00153 }
00154 else
00155 {
00156 TGo4Log::Debug(" Socket: !!! Received unknown string !!! ");
00157 }
00158 }
00159 else
00160 {
00161
00162 if(!fxServerSocket)
00163 {
00164 fxServerSocket = new TServerSocket(port, kFALSE);
00165 fxServerSocket->SetOption(kNoBlock,1);
00166 }
00167 else
00168 {
00169
00170 }
00171 if(!fxServerSocket->IsValid())
00172 {
00173 TGo4Log::Debug(" Socket: Open(const char* host, Int_t port) as Server failed ");
00174 fiPort = 0;
00175 return -8;
00176 }
00177 else
00178 {
00179 fiPort = fxServerSocket->GetLocalPort();
00180
00181 }
00182 fxSocket = 0;
00183 while(1)
00184 {
00185 if(!fxSocket)
00186 {
00187 fxSocket = fxServerSocket->Accept();
00188 if(!fxSocket || fxSocket==(TSocket*) (-1) )
00189 {
00190 fxSocket=0;
00191 rev=-1;
00192 break;
00193
00194 }
00195 else
00196 {
00197 fxSocket->SetOption(kNoBlock,0);
00198 fxSocket->Send(TGo4Socket::fgcGOON);
00199 if(!keepservsock)
00200 {
00201 fxServerSocket->Close();
00202 delete fxServerSocket;
00203 fxServerSocket = 0;
00204 }
00205 else
00206 {
00207
00208
00209
00210 }
00211 fbOpen = kTRUE;
00212 rev=0;
00213 break;
00214 }
00215 }
00216 else
00217 {
00218 rev=-2;
00219 break;
00220 }
00221 }
00222 }
00223 return rev;
00224 }
00225
00226
00227 Int_t TGo4Socket::Close(Option_t *opt)
00228 {
00229 GO4TRACE((12,"TGo4Socket::Close()", __LINE__, __FILE__));
00230 if(!fbOpen) return 1;
00231
00232 fxSocket->Close(opt);
00233 fbOpen = kFALSE;
00234 return 0;
00235 }
00236
00237 Int_t TGo4Socket::SendBuffer(TBuffer* buf)
00238 {
00239 GO4TRACE((12,"TGo4Socket::SendBuffer(TBuffer*)", __LINE__, __FILE__));
00240
00241 if(!buf) {
00242 TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : no buffer !!! ");
00243 return -2;
00244 }
00245
00246 if(!IsOpen()) {
00247 TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : socket not open !!! ");
00248 return -1;
00249 }
00250
00251 if(!fxSocket) {
00252 TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : no TSocket !!! ");
00253 return -5;
00254 }
00255
00256
00257 UInt_t len = buf->Length();
00258 char* field = buf->Buffer();
00259
00260 if(field==0) {
00261 TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : no data field !!! ");
00262 return -5;
00263 }
00264
00265 char* temp = field;
00266 tobuf(temp, (UInt_t)(len - sizeof(UInt_t)));
00267
00269
00270
00271
00272
00273
00275
00276 #ifdef WIN32
00277
00278 Int_t rev = fxSocket->SendRaw(field, len);
00279
00280 #else
00281
00282 Int_t rev = gSystem->SendRaw(fxSocket->GetDescriptor(), field, len, MSG_NOSIGNAL);
00283
00284 #endif
00285
00286 if(rev>0) return 0;
00287
00288
00289 TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR # %d !!! ",rev);
00290 return rev;
00291 }
00292
00293 Int_t TGo4Socket::ReceiveBuffer()
00294 {
00295 GO4TRACE((12,"TGo4Socket::ReceiveBuffer()", __LINE__, __FILE__));
00296
00297 if(!IsOpen()) {
00298 TGo4Log::Debug(" !!! Socket: ReceiveBuffer() ERROR : not open !!! ");
00299 return -11;
00300 }
00301
00302 if(!fxSocket) {
00303 TGo4Log::Debug(" !!! Socket: ReceiveBuffer() ERROR : no TSocket !!! ");
00304 return -10;
00305 }
00306
00307 UInt_t len = 0;
00308
00309 #ifdef WIN32
00310 Int_t rev = fxSocket->RecvRaw(&len, sizeof(UInt_t));
00311 #else
00312 Int_t rev = gSystem->RecvRaw(fxSocket->GetDescriptor(), &len, sizeof(UInt_t), MSG_NOSIGNAL);
00313 #endif
00314 if(rev <= 0) {
00315
00316
00317
00318 return -55;
00319 }
00320
00321 len = net2host(len);
00322 Int_t messlen = len + sizeof(UInt_t);
00323
00324
00325 Int_t oldsize = fxBuffer->BufferSize();
00326 Int_t newsize = messlen;
00327 if(newsize>oldsize) {
00328 ReallocBuffer(fxBuffer, oldsize, newsize);
00329 } else
00330 if(newsize<oldsize && oldsize>TGo4Socket::fgiBUFINITSIZE) {
00331
00332 if(newsize < TGo4Socket::fgiBUFINITSIZE)
00333 newsize = TGo4Socket::fgiBUFINITSIZE;
00334 ReallocBuffer(fxBuffer, oldsize, newsize);
00335 }
00336
00337 char* buf = fxBuffer->Buffer()+sizeof(UInt_t);
00338
00339 #ifdef WIN32
00340 rev = fxSocket->RecvRaw((void*) buf, len);
00341 #else
00342 rev = gSystem->RecvRaw(fxSocket->GetDescriptor(), buf, len, MSG_NOSIGNAL);
00343 #endif
00344 if(rev <= 0) {
00345
00346 TGo4Log::Debug(" !!! Socket: ReceiveBuffer() ERROR # %d !!! ",rev);
00347 return -56;
00348 }
00349
00350
00351 fxBuffer->SetBufferOffset(messlen);
00352 fxBuffer->SetByteCount(0);
00353 return 0;
00354 }
00355
00356 Int_t TGo4Socket::Send(TObject *obj)
00357 {
00358 GO4TRACE((12,"TGo4Socket::Send(TObject *obj)", __LINE__, __FILE__));
00359
00360 Int_t rev=0;
00361 if(IsOpen())
00362 {
00363 {
00364 TGo4LockGuard init;
00365 }
00366 TGo4LockGuard::LockMainMutex();
00367 TMessage mess(kMESS_OBJECT);
00368 mess.WriteObject(obj);
00369 TGo4LockGuard::UnLockMainMutex();
00370 if(fxSocket)
00371 {
00372 rev = fxSocket->Send(mess);
00373 }
00374 else
00375 {
00376 rev=-16;
00377 }
00378 }
00379 else {
00380
00381 rev=-32;
00382 }
00383
00384 if(rev < 0)
00385 TGo4Log::Debug(" !!! Socket: Send(TObject*) ERROR # %d !!! ",rev);
00386
00387 return rev;
00388 }
00389
00390 Int_t TGo4Socket::Send(const char* name)
00391 {
00392 GO4TRACE((12,"TGo4Socket::Send(const char* name)", __LINE__, __FILE__));
00393
00394 Int_t rev=0;
00395 if(IsOpen())
00396 {
00397 if(fxSocket)
00398 {
00399 strncpy(fxLocalBuffer,name, TGo4Socket::fgiBUFLENGTH-1);
00400
00401 #ifdef WIN32
00402 rev = fxSocket->SendRaw(fxLocalBuffer,TGo4Socket::fgiBUFLENGTH);
00403 #else
00404 rev = gSystem->SendRaw(fxSocket->GetDescriptor(), fxLocalBuffer,TGo4Socket::fgiBUFLENGTH, MSG_NOSIGNAL);
00405 #endif
00406 }
00407 else
00408 {
00409 rev=-16;
00410 }
00411 }
00412 else
00413 {
00414
00415 rev=-32;
00416 }
00417
00418 if(rev < 0)
00419 {
00420 TGo4Log::Debug(" !!! Socket: Send(const char*) ERROR # %d !!! ",rev);
00421 }
00422 return rev;
00423 }
00424
00425 char* TGo4Socket::RecvRaw(const char* name)
00426 {
00427
00428 GO4TRACE((12,"TGo4Socket::RecvRaw(const char* name)", __LINE__, __FILE__));
00429
00430 if(!IsOpen()) {
00431 TGo4Log::Debug(" !!! Socket: Recv(const char*) ERROR : not open or not active !!! ");
00432 return 0;
00433 }
00434
00435 if (!fxSocket) {
00436 TGo4Log::Debug(" !!! Socket: Recv(const char*) ERROR : no TSocket !!! ");
00437 return 0;
00438 }
00439 #ifdef WIN32
00440 Int_t rev = fxSocket->RecvRaw(fxLocalBuffer, TGo4Socket::fgiBUFLENGTH);
00441 #else
00442 Int_t rev = gSystem->RecvRaw(fxSocket->GetDescriptor(), fxLocalBuffer, TGo4Socket::fgiBUFLENGTH, MSG_NOSIGNAL);
00443 #endif
00444
00445 if(rev<=0) {
00446
00447 TGo4Log::Debug(" !!! Socket: RecvRaw(const char*) ERROR # %d !!! ",rev);
00448 return 0;
00449 }
00450
00451 return fxLocalBuffer;
00452 }
00453
00454
00455
00456 TObject* TGo4Socket::Recv(const char* name)
00457 {
00458
00459 GO4TRACE((12,"TGo4Socket::Recv(const char* name)", __LINE__, __FILE__));
00460
00461 TObject* obj=0;
00462 if(IsOpen())
00463 {
00464 if(fxSocket)
00465 {
00466 TMessage *mess = 0;
00467 fxSocket->Recv(mess);
00468
00469 if(mess == 0)
00470 {
00471
00472 obj=0;
00473 }
00474 else
00475 {
00476 TGo4LockGuard socker;
00477 if(mess->What() == kMESS_OBJECT)
00478 {
00479 obj = mess->ReadObject(mess->GetClass());
00480 }
00481 delete mess;
00482 }
00483
00484 }
00485 else
00486 {
00487 TGo4Log::Debug(" !!! Socket: Recv(TMessage*) ERROR : no TSocket! ");
00488 }
00489 }
00490 else
00491 {
00492 TGo4Log::Debug(" !!! Socket: Recv(TMessage*) ERROR : not open or not active! ");
00493 }
00494 return obj;
00495 }
00496
00497
00498 void TGo4Socket::ReallocBuffer(TBuffer* buffer, Int_t oldsize, Int_t newsize)
00499 {
00500 if(buffer==0) return;
00501 TGo4LockGuard mainguard;
00502 char* memfield = buffer->Buffer();
00503
00504
00505 Int_t extraspace = TGo4Socket::fgiBUFEXTRASPACE;
00506
00507
00508
00509
00510 memfield = TStorage::ReAllocChar(memfield,
00511 (newsize+extraspace),
00512 (oldsize+extraspace));
00513
00514 buffer->ResetBit(fgiISOWNER);
00515
00516
00517
00518 buffer->SetBuffer(memfield, newsize);
00519
00520 buffer->SetBit(fgiISOWNER);
00521
00522
00523
00524
00525
00526 buffer->SetBufferOffset(newsize);
00527 }