Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

/Go4Socket/TGo4Socket.cxx

Go to the documentation of this file.
00001 //---------------------------------------------------------------
00002 //        Go4 Release Package v2.10-5 (build 21005) 
00003 //                      03-Nov-2005
00004 //---------------------------------------------------------------
00005 //       The GSI Online Offline Object Oriented (Go4) Project
00006 //       Experiment Data Processing at DVEE department, GSI
00007 //---------------------------------------------------------------
00008 //
00009 //Copyright (C) 2000- Gesellschaft f. Schwerionenforschung, GSI
00010 //                    Planckstr. 1, 64291 Darmstadt, Germany
00011 //Contact:            http://go4.gsi.de
00012 //----------------------------------------------------------------
00013 //This software can be used under the license agreements as stated
00014 //in Go4License.txt file which is part of the distribution.
00015 //----------------------------------------------------------------
00016 #include "TGo4Socket.h"
00017 
00018 #include <iostream.h>
00019 
00020 #include "TMutex.h"
00021 #include "TMessage.h"
00022 #include "TSystem.h"
00023 #include "TSocket.h"
00024 #include "TServerSocket.h"
00025 
00026 #include "Go4Log/TGo4Log.h"
00027 #include "Go4LockGuard/TGo4LockGuard.h"
00028 #include "TGo4SocketSignalHandler.h"
00029 
00030 const Int_t TGo4Socket::fguOPENWAIT=200;
00031 const Int_t TGo4Socket::fgiOPENCYCLES=6;
00032 const Int_t TGo4Socket::fgiBUFLENGTH=256;
00033 const Int_t TGo4Socket::fgiBUFINITSIZE=65536;
00034 const Int_t TGo4Socket::fgiBUFEXTRASPACE=8;
00035 const Text_t TGo4Socket::fgcGOON[]="-I- go on";
00036 
00037 // note: ownwership bit changed for newer root versions!!
00038 #if __GO4ROOTVERSION__ > 40302
00039    const Int_t TGo4Socket::fgiISOWNER=TBuffer::kIsOwner;
00040 #else
00041    const Int_t TGo4Socket::fgiISOWNER=BIT(14);
00042    // have to emulate the protected owner flag of the TBuffer class, needed for reallocation!
00043 #endif
00044 
00045 
00046 
00047 TGo4Socket::TGo4Socket(Bool_t IsClient)
00048    : fbClientMode(IsClient), fbOpen(kFALSE),
00049        fxSocket(0), fxServerSocket(0), fiPort(0)
00050 {
00051    TRACE((14,"TGo4Socket::TGo4Socket(Bool_t)", __LINE__, __FILE__));
00052 
00053    fxBuffer= new TBuffer(TBuffer::kRead, TGo4Socket::fgiBUFINITSIZE);
00054    fxSignalHandler= new TGo4SocketSignalHandler(SIGWINCH);
00055    fxLocalBuffer = new Text_t [TGo4Socket::fgiBUFLENGTH];
00056    if(fbClientMode)
00057       {
00058          TGo4Log::Debug(" Created new Go4Socket in client mode ");
00059       }
00060    else
00061       {
00062          TGo4Log::Debug(" Created new Go4Socket in server mode ");
00063       }
00064 }
00065 
00066 TGo4Socket::~TGo4Socket()
00067 {
00068    TRACE((14,"TGo4Socket::~TGo4Socket()", __LINE__, __FILE__));
00069    delete [] fxLocalBuffer;
00070    if(fxSocket)
00071       {
00072          delete fxSocket;
00073       }
00074 
00075    if(fxServerSocket)
00076       {
00077          delete fxServerSocket;
00078       }
00079    delete fxSignalHandler;
00080 }
00081 
00082 Int_t TGo4Socket::Open(const char* host, Int_t port, Bool_t keepservsock)
00083 {
00084   TRACE((12,"TGo4Socket::Open(Text_t *host, Int_t port)", __LINE__, __FILE__));
00085 
00086   Int_t rev=0;
00087   if(!fbOpen)
00088     {
00089       if(fbClientMode)
00090          {
00091             // client socket
00092             fxSocket = new TSocket(host, port);
00093             Int_t maxcounter=0;
00094             while(!fxSocket->IsValid())
00095                {
00096                   if(++maxcounter> TGo4Socket::fgiOPENCYCLES)
00097                      {
00098                         TGo4Log::Debug(" Socket: Open timeout!!");
00099                         break;
00100                      }
00101                   else
00102                      {
00103                         TGo4Log::Debug(" Socket: Open retry %d ", maxcounter);
00104                         delete fxSocket;
00105                         gSystem->Sleep(TGo4Socket::fguOPENWAIT);
00106                         fxSocket = new TSocket(host, port);
00107                      }
00108                } // while()
00109             if(!fxSocket->IsValid())
00110                {
00111                    TGo4Log::Debug(" Socket: Open(Text_t *host, Int_t port ) as Client failed ");
00112                    fiPort=0;
00113                    return -8;
00114                }
00115             else
00116                {
00117                   fiPort=fxSocket->GetLocalPort(); // success, get real port number
00118                }
00119             char str[32];
00120             fxSocket->Recv(str, 32);
00121             if(!strcmp(str,TGo4Socket::fgcGOON))
00122                {
00123                   //cout << "-I- We are told to go on !\n";
00124                   fbOpen = kTRUE;
00125                   rev=0;
00126                   TGo4Log::Debug(" Socket: Connection Established ");
00127                }
00128             else
00129                {
00130                   TGo4Log::Debug(" Socket: !!! Received unknown string !!! ");
00131                }
00132          }
00133       else // if(fbClientMode)
00134          {
00135             // server socket:
00136          if(!fxServerSocket)
00137             {
00138                fxServerSocket = new TServerSocket(port, kFALSE); // for portscan
00139                fxServerSocket->SetOption(kNoBlock,1);
00140             }
00141          else
00142             {
00143                // do nothing, we poll existing server socket
00144             }
00145          if(!fxServerSocket->IsValid())
00146             {
00147                TGo4Log::Debug(" Socket: Open(Text_t *host,  Int_t port) as Server failed ");
00148                fiPort=0;
00149                return -8;
00150             }
00151          else
00152            {
00153              fiPort=fxServerSocket->GetLocalPort(); // success, get real port number
00154              //cout << " ---- Go4 Socket got local port "<< fiPort  << endl;
00155            }
00156          fxSocket = 0;
00157          while(1)
00158             {
00159                if(!fxSocket)
00160                  {
00161                      fxSocket = fxServerSocket->Accept();
00162                      if(!fxSocket || fxSocket==(TSocket*) (-1) )
00163                         {
00164                            fxSocket=0;
00165                            rev=-1;
00166                            break;
00167                               // no connection request, leave loop
00168                         }
00169                      else
00170                         {
00171                            fxSocket->Send(TGo4Socket::fgcGOON);
00172                            if(!keepservsock)
00173                               {
00174                                  fxServerSocket->Close();
00175                                  delete fxServerSocket;
00176                                  fxServerSocket = 0;
00177                               }
00178                            else
00179                               {
00180                                  // do not delete serversocket in "keep" mode
00181                                  // more performant for servers that should be
00182                                  // idle quickly for repeated client requests
00183                               }// if(!keepservsock)
00184                            fbOpen = kTRUE;
00185                            rev=0;
00186                            break;
00187                         } // if(!fxSocket || fxSocket==(TSocket*) (-1) )
00188                   }
00189                else
00190                   {
00191                      rev=-2; // TSocket already existing
00192                      break;
00193                   } // if(!fxSocket)
00194             } // while(1)
00195          } // end if(fbClientMode)
00196       } // if(!fbOpen)
00197    else
00198       {
00199          rev=1; // TGo4Socket already open
00200       }  // end if(!fbOpen)
00201    return rev;
00202 }
00203 
00204 
00205 Int_t TGo4Socket::Close()
00206 {
00207    TRACE((12,"TGo4Socket::Close()", __LINE__, __FILE__));
00208    Int_t rev=0;
00209    if(fbOpen)
00210       {
00211          fxSocket->Close();
00212          fbOpen = kFALSE;
00213          rev = 0;
00214       }
00215    else
00216       {
00217          rev = 1;
00218       }
00219    return rev;
00220 }
00221 
00222 Int_t TGo4Socket::SendBuffer(TBuffer* buf)
00223 {
00224    TRACE((12,"TGo4Socket::SendBuffer(TBuffer*)", __LINE__, __FILE__));
00225 
00226    Int_t rev=0;
00227    if(buf)
00228       {
00229       UInt_t len=buf->Length();
00230 //      cout << "))))))))) socket send: buffer length "<< len << endl;
00231       char* field=buf->Buffer();
00232       if(IsOpen())
00233          {
00234             if(fxSocket)
00235                {
00236                   if(field)
00237                      {
00238                         char* temp = field;
00239                         tobuf(temp, (UInt_t)(len - sizeof(UInt_t))); // tobuf changes pointer!
00240                               //set length into first word of buffer (see TMessage)
00242 //                        cout << "))))))))) socket send: buffer length in buffer ";
00243 //                        UInt_t dummy=0;
00244 //                        temp=field;
00245 //                        frombuf(temp,&dummy);
00246 //                        cout << dummy << endl;
00248                         rev=fxSocket->SendRaw(field,len);
00249                            // raw send complete buffer
00250                         if(rev<= 0)
00251                            {
00252                               // error on send
00253                               TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR # %d !!! ",rev);
00254                               return rev;
00255                            }
00256                         else
00257                            {
00258                               rev=0;
00259                            }
00260                      } // if(field)
00261                   else
00262                      {
00263                         TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : no data field !!! ");
00264                         rev=-5;
00265                       }
00266                 } // if(fxSocket)
00267             else
00268                {
00269                   TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : no TSocket !!! ");
00270                   rev=-5;
00271                }  // end if(fxSocket)
00272          }
00273       else // if(IsOpen())
00274          {
00275             TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : socket not open  !!! ");
00276             rev=-1;
00277          }
00278       } // if(buf)
00279    else
00280       {
00281          TGo4Log::Debug(" !!! Socket: SendBuffer() ERROR : no buffer  !!! ");
00282             rev=-2;
00283       }
00284    return rev;
00285 }
00286 
00287 Int_t TGo4Socket::ReceiveBuffer()
00288 {
00289    TRACE((12,"TGo4Socket::ReceiveBuffer()", __LINE__, __FILE__));
00290 
00291    Int_t rev=0;
00292    UInt_t len=0;
00293    if(IsOpen())
00294       {
00295          if(fxSocket)
00296             {
00297                // first receive length of following buffer
00298                rev=fxSocket->RecvRaw(&len, sizeof(UInt_t));
00299                if(rev<= 0)
00300                   {
00301                      // error on receive
00302                      //TGo4Log::Debug(" !!! Socket: ReceiveBuffer() -- receive length ERROR # %d !!! ",rev);
00303                      // no output here, we will redirect cout client runnable (command) 
00304                      return -55;
00305                   }
00306                else
00307                   {
00308                   }
00309                // check if length exceeds receive buffer
00310                len = net2host(len);  //from network to host byte order
00311                Int_t messlen = len + sizeof(UInt_t); // compatible with root TMessage protocol
00312 //               cout << "))))))))) socket receive: buffer length "<< len << endl;
00313 //               cout << "))))))))) socket receive: messlen "<< messlen << endl;
00314                Int_t oldsize = fxBuffer->BufferSize();
00315                Int_t newsize = messlen;
00316                if(newsize>oldsize)
00317                   {
00318                      ReallocBuffer(fxBuffer, oldsize, newsize);
00319                   }
00320               else if(newsize<oldsize && oldsize>TGo4Socket::fgiBUFINITSIZE)
00321                   {
00322                       //cout << "))))))))) socket receive shorter messlen "<< messlen << endl;
00323                       if(newsize< TGo4Socket::fgiBUFINITSIZE)
00324                             newsize= TGo4Socket::fgiBUFINITSIZE;
00325                       ReallocBuffer(fxBuffer, oldsize, newsize);
00326                   }
00327                else { }
00328                // read object buffer into receive buffer:
00329                char* buf=fxBuffer->Buffer() +sizeof(UInt_t);
00330                            // skip first word, see TMessage transport
00331                rev=fxSocket->RecvRaw((void*) buf, len);
00332                if(rev<= 0)
00333                   {
00334                      // error on receive
00335                      TGo4Log::Debug(" !!! Socket: ReceiveBuffer() ERROR # %d !!! ",rev);
00336                      return -56;
00337                   }
00338                else
00339                   {
00340 //                     cout << "socket: received raw "<< rev << " bytes" << endl;
00341                      // set root byte count for correct object reconstruction:
00342                      fxBuffer->SetBufferOffset(messlen);
00343                      fxBuffer->SetByteCount(0);
00344                      rev=0;
00345                   } // if(rev< 0)
00346              } // if(fxSocket)
00347          else
00348             {
00349                TGo4Log::Debug(" !!! Socket: ReceiveBuffer() ERROR : no TSocket !!! ");
00350                rev=-10;
00351             }  // end if(fxSocket)
00352       }
00353    else // if(IsOpen())
00354       {
00355          TGo4Log::Debug(" !!! Socket: ReceiveBuffer() ERROR : not open  !!! ");
00356          rev=-11;
00357       }
00358    return rev;
00359 }
00360 
00361 Int_t TGo4Socket::Send(TObject *obj)
00362 {
00363    TRACE((12,"TGo4Socket::Send(TObject *obj)", __LINE__, __FILE__));
00364 
00365    Int_t rev=0;
00366    if(IsOpen())
00367       {
00368          {
00369             TGo4LockGuard init; // initialize main mutex
00370          }
00371          TGo4LockGuard::fgxMainMutex->Lock();
00372             TMessage mess(kMESS_OBJECT);
00373             mess.WriteObject(obj);
00374          TGo4LockGuard::fgxMainMutex->UnLock();
00375          if(fxSocket)
00376             {
00377                rev = fxSocket->Send(mess);
00378             }
00379          else
00380             {
00381                rev=-16;
00382             } // end if(fxSocket)
00383       }    // if(IsOpen())
00384    else
00385       {
00386          // do not send on closed socket
00387          rev=-32;
00388       } // end   if(IsOpen() && IsActive())
00389 
00390    if(rev < 0)
00391       {
00392          TGo4Log::Debug(" !!! Socket: Send(TObject*) ERROR # %d !!! ",rev);
00393       }
00394    return rev;
00395 }
00396 
00397 Int_t TGo4Socket::Send(const char* name)
00398 {
00399    TRACE((12,"TGo4Socket::Send(const char* name)", __LINE__, __FILE__));
00400 
00401    Int_t rev=0;
00402    if(IsOpen())
00403       {
00404          if(fxSocket)
00405             {
00406                snprintf(fxLocalBuffer,TGo4Socket::fgiBUFLENGTH-1, "%s", name);
00407                rev = fxSocket->SendRaw(fxLocalBuffer,TGo4Socket::fgiBUFLENGTH);
00408             }
00409          else
00410             {
00411                rev=-16;
00412             } // end if(fxSocket)
00413       }    // if(IsOpen())
00414    else
00415       {
00416          // do not send on closed socket
00417          rev=-32;
00418       } // end   if(IsOpen())
00419 
00420    if(rev < 0)
00421       {
00422          TGo4Log::Debug(" !!! Socket: Send(const char*) ERROR # %d !!! ",rev);
00423       }
00424    return rev;
00425 }
00426 
00427 Text_t* TGo4Socket::RecvRaw(const char* name)
00428 {
00429 // note: optional parameter Text_t *name is left for compatibility, has no effect!
00430    TRACE((12,"TGo4Socket::RecvRaw(Text_t *name)", __LINE__, __FILE__));
00431 
00432    Text_t* revchar;
00433    if(IsOpen())
00434       {
00435          if(fxSocket)
00436             {
00437                Int_t rev=fxSocket->RecvRaw(fxLocalBuffer, TGo4Socket::fgiBUFLENGTH);
00438                if(rev<= 0)
00439                   {
00440                      // error on receive
00441                      TGo4Log::Debug(" !!! Socket: Recv(Text_t*) ERROR # %d !!! ",rev);
00442                      revchar=0;
00443                   }
00444                else
00445                   {
00446                      revchar=fxLocalBuffer;
00447                   }
00448              } // if(fxSocket)
00449          else
00450             {
00451                TGo4Log::Debug(" !!! Socket: Recv(const char*) ERROR : no TSocket !!! ");
00452                revchar=0;
00453             }  // end if(fxSocket)
00454       }
00455    else // if(IsOpen())
00456       {
00457          TGo4Log::Debug(" !!! Socket: Recv(const char*) ERROR : not open or not active !!! ");
00458          revchar=0;
00459       }
00460    return revchar;
00461 }
00462 
00463 
00464 
00465 TObject* TGo4Socket::Recv(const char* name)
00466 {
00467 // note: optional parameter Text_t *name is left for compatibility, has no effect!
00468    TRACE((12,"TGo4Socket::Recv(const char* name)", __LINE__, __FILE__));
00469 
00470    TObject* obj=0;
00471    Int_t rev=0;
00472    if(IsOpen())
00473       {
00474          TMessage *mess;
00475          if(fxSocket)
00476             {
00477             rev=fxSocket->Recv(mess);
00478             if(mess == 0)
00479                   {
00480                      //cout << "TGo4SocketTransportImp: zero mess" << endl;
00481                      obj=0;
00482                   }
00483             else
00484                {
00485                TGo4LockGuard socker;
00486                   if(mess->What() == kMESS_OBJECT)
00487                       {
00488                            obj = mess->ReadObject(mess->GetClass());
00489                       }
00490                   delete mess;
00491                } // end if(mess == NULL)
00492 
00493             } // if (fxSocket)
00494          else
00495             {
00496                TGo4Log::Debug(" !!! Socket: Recv(TMessage*) ERROR : no TSocket! ");
00497             } // end if (fxSocket)
00498       }
00499    else // if(IsOpen())
00500       {
00501          TGo4Log::Debug(" !!! Socket: Recv(TMessage*) ERROR : not open or not active! ");
00502       }
00503    return obj;
00504 }
00505 
00506 
00507 void TGo4Socket::ReallocBuffer(TBuffer* buffer, Int_t oldsize, Int_t newsize)
00508 {
00509 if(buffer==0) return;
00510 TGo4LockGuard mainguard;
00511    char* memfield=buffer->Buffer();
00512    //buffer->Expand(newsize); // is protected! we make it by hand...
00513    //Int_t current = buffer->Length(); // cursor position
00514    Int_t extraspace=TGo4Socket::fgiBUFEXTRASPACE; // =8, constant within TBuffer
00515 //   memfield = (char *) TStorage::ReAlloc(memfield,
00516 //                                           (newsize + extraspace) * sizeof(char),
00517 //                                           (oldsize+ extraspace) * sizeof(char));
00518    // this works only for ROOT versions > 3.02/04:
00519    memfield = TStorage::ReAllocChar(memfield,
00520                                            (newsize+extraspace),
00521                                            (oldsize+extraspace));
00522    //cout << "Socket reallocating char receive buffer from "<<oldsize<< " to " << newsize<< endl;
00523    buffer->ResetBit(fgiISOWNER);
00524    buffer->SetBuffer(memfield, newsize);
00525    buffer->SetBit(fgiISOWNER);
00526    // <- here we avoid the ownership of TBuffer for the internal buffer
00527    // (new feature of ROOT versions > 3.02/04)
00528    // problem: SetBuffer will delete previous buffer in adopt mode (isowner=true)
00529    // which might be at the same location as the new buffer after ReAlloc
00530    // ergo SetBuffer would set a buffer which it deleted before itself!
00531    buffer->SetBufferOffset(newsize);
00532 }
00533 
00534 //----------------------------END OF GO4 SOURCE FILE ---------------------

Generated on Tue Nov 8 10:56:04 2005 for Go4-v2.10-5 by doxygen1.2.15