// @(#)root/net:$Id$
// Author: Fons Rademakers   19/1/2001

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPServerSocket                                                       //
//                                                                      //
// This class implements parallel server sockets. A parallel server     //
// socket waits for requests to come in over the network. It performs   //
// some operation based on that request and then possibly returns a     //
// full duplex parallel socket to the requester. The actual work is     //
// done via the TSystem class (either TUnixSystem or TWinNTSystem).     //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TPServerSocket.h"
#include "TPSocket.h"
#include "TROOT.h"
#include "TVirtualMutex.h"

ClassImp(TPServerSocket)

//______________________________________________________________________________
TPServerSocket::TPServerSocket(Int_t port, Bool_t reuse, Int_t backlog,
                               Int_t tcpwindowsize) :
   TServerSocket(port, reuse, backlog, tcpwindowsize)
{
   // Create a parallel server socket object on a specified port. Set reuse
   // to true to force reuse of the server socket (i.e. do not wait for the
   // time out to pass). Using backlog one can set the desirable queue length
   // for pending connections.
   // Use tcpwindowsize to specify the size of the receive buffer, it has
   // to be specified here to make sure the window scale option is set (for
   // tcpwindowsize > 65KB and for platforms supporting window scaling).
   // Use IsValid() to check the validity of the
   // server socket. In case server socket is not valid use GetErrorCode()
   // to obtain the specific error value. These values are:
   //  0 = no error (socket is valid)
   // -1 = low level socket() call failed
   // -2 = low level bind() call failed
   // -3 = low level listen() call failed
   // Every valid server socket is added to the TROOT sockets list which
   // will make sure that any open sockets are properly closed on
   // program termination.

   fTcpWindowSize = tcpwindowsize;
   SetName("PServerSocket");
}

//______________________________________________________________________________
TPServerSocket::TPServerSocket(const char *service, Bool_t reuse, Int_t backlog,
                               Int_t tcpwindowsize) :
   TServerSocket(service, reuse, backlog, tcpwindowsize)
{
   // Create a parallel server socket object for a named service. Set reuse
   // to true to force reuse of the server socket (i.e. do not wait for the
   // time out to pass). Using backlog one can set the desirable queue length
   // for pending connections.
   // Use tcpwindowsize to specify the size of the receive buffer, it has
   // to be specified here to make sure the window scale option is set (for
   // tcpwindowsize > 65KB and for platforms supporting window scaling).
   // Use IsValid() to check the validity of the
   // server socket. In case server socket is not valid use GetErrorCode()
   // to obtain the specific error value. These values are:
   //  0 = no error (socket is valid)
   // -1 = low level socket() call failed
   // -2 = low level bind() call failed
   // -3 = low level listen() call failed
   // Every valid server socket is added to the TROOT sockets list which
   // will make sure that any open sockets are properly closed on
   // program termination.

   fTcpWindowSize = tcpwindowsize;
   SetName("PServerSocket");
}

//______________________________________________________________________________
TSocket *TPServerSocket::Accept(UChar_t Opt)
{
   // Accept a connection on a parallel server socket. Returns a full-duplex
   // parallel communication TPSocket object. If no pending connections are
   // present on the queue and nonblocking mode has not been enabled
   // with SetOption(kNoBlock,1) the call blocks until a connection is
   // present. The returned socket must be deleted by the user. The socket
   // is also added to the TROOT sockets list which will make sure that
   // any open sockets are properly closed on program termination.
   // In case of error 0 is returned and in case non-blocking I/O is
   // enabled and no connections are available -1 is returned.

   TSocket  *setupSocket = 0;
   TSocket  **pSockets;
   TPSocket *newPSocket = 0;

   Int_t size, port;

   // wait for the incoming connections to the server and accept them
   setupSocket = TServerSocket::Accept(Opt);

   if (setupSocket == 0) return 0;

   // receive the port number and number of parallel sockets from the
   // client and establish 'n' connections
   if (setupSocket->Recv(port, size) < 0) {
      Error("Accept", "error receiving port number and number of sockets");
      return 0;
   }

   // Check if client is running in single mode
   if (size == 0) {
      pSockets = new TSocket*[1];

      pSockets[0] = setupSocket;

      // create TPSocket object with the original socket
      newPSocket = new TPSocket(pSockets, 1);

   } else {
      pSockets = new TSocket*[size];

      for (int i = 0; i < size; i++) {
         pSockets[i] = new TSocket(setupSocket->GetInetAddress(),
                                           port, fTcpWindowSize);
         R__LOCKGUARD2(gROOTMutex);
         gROOT->GetListOfSockets()->Remove(pSockets[i]);
      }

      // create TPSocket object with all the accepted sockets
      newPSocket = new TPSocket(pSockets, size);

   }

   // Transmit authentication information, if any
   if (setupSocket->IsAuthenticated())
      newPSocket->SetSecContext(setupSocket->GetSecContext());

   // clean up, if needed
   if (size > 0)
      delete setupSocket;

   // return the TSocket object
   return newPSocket;
}

 TPServerSocket.cxx:1
 TPServerSocket.cxx:2
 TPServerSocket.cxx:3
 TPServerSocket.cxx:4
 TPServerSocket.cxx:5
 TPServerSocket.cxx:6
 TPServerSocket.cxx:7
 TPServerSocket.cxx:8
 TPServerSocket.cxx:9
 TPServerSocket.cxx:10
 TPServerSocket.cxx:11
 TPServerSocket.cxx:12
 TPServerSocket.cxx:13
 TPServerSocket.cxx:14
 TPServerSocket.cxx:15
 TPServerSocket.cxx:16
 TPServerSocket.cxx:17
 TPServerSocket.cxx:18
 TPServerSocket.cxx:19
 TPServerSocket.cxx:20
 TPServerSocket.cxx:21
 TPServerSocket.cxx:22
 TPServerSocket.cxx:23
 TPServerSocket.cxx:24
 TPServerSocket.cxx:25
 TPServerSocket.cxx:26
 TPServerSocket.cxx:27
 TPServerSocket.cxx:28
 TPServerSocket.cxx:29
 TPServerSocket.cxx:30
 TPServerSocket.cxx:31
 TPServerSocket.cxx:32
 TPServerSocket.cxx:33
 TPServerSocket.cxx:34
 TPServerSocket.cxx:35
 TPServerSocket.cxx:36
 TPServerSocket.cxx:37
 TPServerSocket.cxx:38
 TPServerSocket.cxx:39
 TPServerSocket.cxx:40
 TPServerSocket.cxx:41
 TPServerSocket.cxx:42
 TPServerSocket.cxx:43
 TPServerSocket.cxx:44
 TPServerSocket.cxx:45
 TPServerSocket.cxx:46
 TPServerSocket.cxx:47
 TPServerSocket.cxx:48
 TPServerSocket.cxx:49
 TPServerSocket.cxx:50
 TPServerSocket.cxx:51
 TPServerSocket.cxx:52
 TPServerSocket.cxx:53
 TPServerSocket.cxx:54
 TPServerSocket.cxx:55
 TPServerSocket.cxx:56
 TPServerSocket.cxx:57
 TPServerSocket.cxx:58
 TPServerSocket.cxx:59
 TPServerSocket.cxx:60
 TPServerSocket.cxx:61
 TPServerSocket.cxx:62
 TPServerSocket.cxx:63
 TPServerSocket.cxx:64
 TPServerSocket.cxx:65
 TPServerSocket.cxx:66
 TPServerSocket.cxx:67
 TPServerSocket.cxx:68
 TPServerSocket.cxx:69
 TPServerSocket.cxx:70
 TPServerSocket.cxx:71
 TPServerSocket.cxx:72
 TPServerSocket.cxx:73
 TPServerSocket.cxx:74
 TPServerSocket.cxx:75
 TPServerSocket.cxx:76
 TPServerSocket.cxx:77
 TPServerSocket.cxx:78
 TPServerSocket.cxx:79
 TPServerSocket.cxx:80
 TPServerSocket.cxx:81
 TPServerSocket.cxx:82
 TPServerSocket.cxx:83
 TPServerSocket.cxx:84
 TPServerSocket.cxx:85
 TPServerSocket.cxx:86
 TPServerSocket.cxx:87
 TPServerSocket.cxx:88
 TPServerSocket.cxx:89
 TPServerSocket.cxx:90
 TPServerSocket.cxx:91
 TPServerSocket.cxx:92
 TPServerSocket.cxx:93
 TPServerSocket.cxx:94
 TPServerSocket.cxx:95
 TPServerSocket.cxx:96
 TPServerSocket.cxx:97
 TPServerSocket.cxx:98
 TPServerSocket.cxx:99
 TPServerSocket.cxx:100
 TPServerSocket.cxx:101
 TPServerSocket.cxx:102
 TPServerSocket.cxx:103
 TPServerSocket.cxx:104
 TPServerSocket.cxx:105
 TPServerSocket.cxx:106
 TPServerSocket.cxx:107
 TPServerSocket.cxx:108
 TPServerSocket.cxx:109
 TPServerSocket.cxx:110
 TPServerSocket.cxx:111
 TPServerSocket.cxx:112
 TPServerSocket.cxx:113
 TPServerSocket.cxx:114
 TPServerSocket.cxx:115
 TPServerSocket.cxx:116
 TPServerSocket.cxx:117
 TPServerSocket.cxx:118
 TPServerSocket.cxx:119
 TPServerSocket.cxx:120
 TPServerSocket.cxx:121
 TPServerSocket.cxx:122
 TPServerSocket.cxx:123
 TPServerSocket.cxx:124
 TPServerSocket.cxx:125
 TPServerSocket.cxx:126
 TPServerSocket.cxx:127
 TPServerSocket.cxx:128
 TPServerSocket.cxx:129
 TPServerSocket.cxx:130
 TPServerSocket.cxx:131
 TPServerSocket.cxx:132
 TPServerSocket.cxx:133
 TPServerSocket.cxx:134
 TPServerSocket.cxx:135
 TPServerSocket.cxx:136
 TPServerSocket.cxx:137
 TPServerSocket.cxx:138
 TPServerSocket.cxx:139
 TPServerSocket.cxx:140
 TPServerSocket.cxx:141
 TPServerSocket.cxx:142
 TPServerSocket.cxx:143
 TPServerSocket.cxx:144
 TPServerSocket.cxx:145
 TPServerSocket.cxx:146
 TPServerSocket.cxx:147
 TPServerSocket.cxx:148
 TPServerSocket.cxx:149
 TPServerSocket.cxx:150
 TPServerSocket.cxx:151