Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

TGo4Socket.cxx

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

Generated on Fri Nov 28 12:59:28 2008 for Go4-v3.04-1 by  doxygen 1.4.2