content: /*
   * Copyright (c) 2001 Boulder Real Time Technologies, Inc.
   * All rights reserved
   *
   * This software may be used freely in any way as long as
   * the copyright statement above is not removed.
   *
   * com.brtt.antelope.Orb.java
   *
   * Created on February 9, 2001, 6:30 PM
   */
  
  package com.brtt.antelope;
  
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import java.lang.*;
  import javax.swing.table.*;
  
  /**
   * This class represents a client connection to an Antelope orbserver.
   *
   * @author  Danny Harvey, BRTT
   * @version 1.0
   */
  public class Orb extends java.lang.Object {
  
      static private final String sync = "orbm";
      static private byte syncBuf[] = sync.getBytes ();
      static private final int defaultPort = 6510;
      static private final int defaultTimeout = 60000;
      static private final int ORBMAGIC = 0x6d62726f;
  
      /** The following are orb commands */
  
      static private final int ORBPUT = 1;
      static private final int ORBGET = 2;
      static private final int ORBREAP = 3;
      static private final int ORBSTAT = 4;
      static private final int ORBCLIENTS = 5;
      static private final int ORBSOURCES = 6;
      static private final int ORBSEEK = 7;
      static private final int ORBTELL = 8;
      static private final int ORBSELECT = 9;
      static private final int ORBREJECT = 10;
      static private final int ORBCLOSE = 11;
      static private final int ORBAFTER = 12;
      static private final int ORBBEFORE = 13;
      static private final int ORBPING = 14;
      static private final int ORBHDR = 15;
      static private final int ORBSETPRI = 16;
      static private final int ORBHALT = 17;
      static private final int ORBSETLOGGING = 18;
      static private final int ORBERROR = 19;
      static private final int ORBOPEN = 20;
      static private final int ORBKILL = 21;
      static private final int ORBID = 23;
      static private final int ORBRUP = 24;
      static private final int ORBPUTL = 25;
      static private final int ORBGETL = 26;
      static private final int ORBREAPL = 27;
      static private final int ORB_ENDREAP = -32;
      static private final int ORBHOST_SIZE = 128;
      static private final int ORBWHO_SIZE = 24;
      static private final int ORBWHAT_SIZE = 128;
      static private final int ORBVERSION_SIZE = 128;
      static private final int ORBSRCNAME_SIZE = 64;
      static private final int SELECT_MAX = 96;
  
      /** The following are valid values for the "whickpkt" argument to
       *  Orb.select and Orb.get. FIXME: I don't think these values are
       *  being transmitted correctly.  Bug in signed/unsigned handling?
       */
  
      static public final int ORBCURRENT    =	-10;
      static public final int ORBNEXT       =	-11;
      static public final int ORBPREV	  =    -12;
      static public final int ORBOLDEST     =	-13;
      static public final int ORBNEWEST     =	-14;
      static public final int ORBNEXT_WAIT  =	-15;
      static public final int ORBNEXTT	  =    -16;
      static public final int ORBPREVT	  =    -17;
      static public final int ORBSTASH	  =    -18;
      static public final int ORBPREVSTASH  =    -19;
  
      private byte syncIn[] = new byte[4];
      private Socket socket;
      private String host;
      private int port = defaultPort;
      private int socketTimeout = defaultTimeout;
      private int reconnect = 0;
      private String permission;
      private String name;
      private String who;
      private String what;
      private OutputStream out;
      private InputStream in;
      private DataOutputStream outBuf;
      private DataInputStream inBuf;
      private double lastPkttime = 0.0;
      private double serverStart = 0.0;
      private double orbStart = 0.0;
      private double openTime = 0.0;
      private int reaped = 0;
      private int once = 0;
      private int error = 0;
      private int nonblocking = 0;
      private int lastPktid = -1;
      private int firstNdFailure = 0;
      private Request request = new Request();
      private Response reply = new Response();
  
      /** Constructors */
  
      /**
       * Creates a new client connection to an Antelope orbserver.
       * The ORB constructor without arguments will attempt to open a
       * connection to localhost:default_orbserver_port.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.net.UnknownHostException
       *              localhost not found.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public Orb() throws OrbErrorException, UnknownHostException, IOException {
          setupOpen ("", "r&");
      }
  
      /**
       * Creates a new client connection to an Antelope orbserver.
       * @param name The orbserver name, of the form hostname:portno. If
       *              hostname is omitted, then localhost is used. If
       *              :portno is ommited, then the default orbserver port
       *              number is used.
       * @param perm Permission string. Must be one of "r", for read, "r&amp;",
       *              for read with automatic reconnect, "w", for write, or
       *              "w&amp;", for write with automatic reconnect.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.net.UnknownHostException
       *              hostname not found.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public Orb(String name, String perm) throws OrbErrorException,
  	UnknownHostException, IOException {
          setupOpen (name, perm);
      }
  
      /** Public class methods */
  
      /**
       * Sends a packet to the Antelope orbserver.  If the packet object's "time"
       * field is nonzero, it is used as the time stamp for the packet sent to
       * the orb; otherwise the current time is used.
       *
       * @param packet An instance of OrbPacket representing the (stuffed)
       *               packet to be sent.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       * @author Tobin Fricke, University of California
       *
       * Written Thu Jun 17 11:11:32 PDT 2004
       */
  
      public void put(OrbRawPacket packet) throws OrbErrorException,
  	IOException {
  	request.what = ORBPUT;
  	request.pkg = packet;
  	request.time = packet.time == 0 ?
  	    Epoch.fromString("now").epoch : packet.time;
  	orbClient(request,null);
      }
  
      /**
       * Closes a client connection to an Antelope orbserver.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public void close () throws OrbErrorException, IOException {
          request.what = ORBCLOSE;
          orbClient (request, reply);
          socket.close();
          in.close();
          out.close();
      }
  
      /**
       * Sends a packet select string to an Antelope orbserver.
       * @param expression Select string. This must be a regular UNIX
       *              expression that is matched against each packet
       *              srcname by the orbserver. Only packets whose srcnames
       *              match this expression will be transmitted by the orbserver.
       * @return The number of srcnames that currently match the expression.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public int select (String expression) throws OrbErrorException,
  	IOException {
          request.what = ORBSELECT;
          request.select = expression;
          orbClient (request, reply);
          return (reply.nSelections);
      }
  
      /**
       * Sends a packet reject string to an Antelope orbserver.
       * @param expression Reject string. This must be a regular UNIX
       *              expression that is matched against each packet
       *              srcname by the orbserver. Only packets whose srcnames
       *              do not match this expression will be transmitted by the
       *              orbserver.
       * @return The number of srcnames that do not currently match the
       *              expression.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public int reject (String expression) throws OrbErrorException,
  	IOException {
          request.what = ORBREJECT;
          request.reject = expression;
          orbClient (request, reply);
          return (reply.nSelections);
      }
  
      /**
       * Sets an Antelope orbserver read pointer to a requested pktid.
       * @param whence The requested pktid of the orbserver read pointer.
       * @return The set pktid of the orbserver read pointer.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public int seek (int whence) throws OrbErrorException, IOException {
          request.what = ORBSEEK;
          request.pktCode = whence;
          orbClient (request, reply);
          return (reply.pktid);
      }
  
      /**
       * Sets an Antelope orbserver read pointer to the next packet after
       * a requested time.
       * @param time The requested time for setting the orbserver read pointer.
       * @return The set pktid of the orbserver read pointer.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public int after (double time) throws OrbErrorException, IOException {
          request.what = ORBAFTER;
          request.time = time;
          orbClient (request, reply);
          return (reply.pktid);
      }
  
      /**
       * Gets the current Antelope orbserver read pointer.
       * @return The current pktid of the orbserver read pointer.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public int tell () throws OrbErrorException, IOException {
          request.what = ORBTELL;
          orbClient (request, reply);
          return (reply.pktid);
      }
  
      /**
       * Gets the current Antelope orbserver status.
       * @return The current status of the orbserver.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public OrbStat stat () throws OrbErrorException, IOException {
          request.what = ORBSTAT;
          orbClient (request, reply);
          return (reply.orbStat);
      }
  
      /**
       * Gets the current Antelope orbserver status for all sources.
       * @return The current status of the orbserver sources.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public OrbSource[] sources () throws OrbErrorException, IOException {
          request.what = ORBSOURCES;
          orbClient (request, reply);
          return (reply.source);
      }
  
      /**
       * Gets the current Antelope orbserver status for all client connections.
       * @return The current status of the orbserver client connections.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
      public OrbClient[] clients () throws OrbErrorException, IOException {
          request.what = ORBCLIENTS;
          orbClient (request, reply);
          return (reply.client);
      }
  
      /**
       * Reaps selected packets from an Antelope orbserver.
       * @return The Antelope OrbPacket.  If unstuff is true, then this function
       *  will attempt to unstuff the packet; otherwise an OrbRawPacket is
       *  returned.
       * @exception com.brtt.antelope.OrbErrorException
       *              An error was generated by the orbserver.
       * @exception java.io.IOException
       *              IO error during communication with orbserver.
       */
  
      public OrbPacket reap(boolean unstuff)
  	throws OrbErrorException, IOException {
  
          if (reaped == 0) {
              startReap (0.0, -1, -1);
              reaped = 1;
          }
  
          reapPacket ();
  
  	if (unstuff) {
  
  	    /* Call OrbPacket's general unstuffer, which dispatches to the
  	       more specialized unstuffers. */
  
  	    return OrbPacket.unstuff(reply.pkg);
  
  	}
  
  	/* If the caller didn't want unstuffing, we'll return the packet
  	   we collected from the Orb, and then we'll make a new packet obj
  	   into which the next packet can be reaped.  Note that one
  	   possibly undesired behavior here is that the buffer in the
  	   returned OrbRawPacket can be larger than the actual packet
  	   data, potentially much larger, if the user mixes unstuffed
  	   reap requests with stuffed reap requests. */
  
  	OrbRawPacket thePacket = reply.pkg;
  	reply.pkg = new OrbRawPacket();
  	return thePacket;
      }
  
      /** Protected class methods */
  
      protected void finalize () throws Throwable {
          close();
      }
  
      /** Private Class Methods */
  
      private void setupOpen (String name, String perm)
  	throws OrbErrorException, UnknownHostException, IOException {
  
  	int i = name.indexOf(':');
          if (i < 0) {
              if (name.length() == 0) {
                  this.host = "localhost";
                  this.port = defaultPort;
              } else {
                  this.host = name;
                  this.port = defaultPort;
              }
          } else if (i == 0) {
              this.host = "localhost";
              String namePort = name.substring(1);
              if (namePort.length() == 0) {
                  this.port = defaultPort;
              } else {
                  this.port = Integer.parseInt(namePort);
              }
          } else {
              this.host = name.substring(0, i);
              String namePort = name.substring(i+1);
              if (namePort.length() == 0) {
                  this.port = defaultPort;
              } else {
                  this.port = Integer.parseInt(namePort);
              }
          }
  
          String permission = perm.substring(0, 1);
          if (perm.length() == 2) {
              if (perm.substring(1, 2) == "&") this.reconnect = 1;
          }
  
          this.permission = permission;
          this.name = name;
          String what = "java"; // FIXME
          try {
              String who = System.getProperty ( "user.name", "none");
          }
          catch (Throwable e) { who = "unknown"; }
          if (who == null) who = "unknown";
          this.request.hello = new Openstring ( permission, what, who ) ;
  
  
          this.socket = new Socket ( this.host, this.port );
          this.socket.setSoTimeout(this.socketTimeout);
          this.socket.setKeepAlive(true);
          this.socket.setTcpNoDelay(true);
          this.out = this.socket.getOutputStream();
          this.in = this.socket.getInputStream();
          this.outBuf = new DataOutputStream(this.out);
          this.inBuf = new DataInputStream(this.in);
  
          this.request.what = ORBOPEN;
          orbClient (this.request, this.reply);
  
      }
  
      private void orbClient (Request req, Response rsp)
  	throws OrbErrorException, IOException, EOFException {
  
  	int done = 0;
          int donerecv = 0;
  
          while (done == 0) {
  
              if (this.error != 0) {
                  if (this.reconnect != 0) {
                      orbReopen();
                      continue;
                  }
              }
  
              if (req != null) {
                  this.reaped = 0;
                  try {
                      sendOrbrequest (req);
                  }
                  catch (IOException exc) {
                      throw new IOException (exc.getMessage());
                  }
              }
  
              if (rsp != null) {
                  donerecv = 0;
                  while (donerecv == 0) {
                      try {
                          recvOrbresponse (rsp);
                      }
                      catch (EOFException exc) {
                          donerecv = 0;
                          throw new EOFException ("EOF on connection to Orb");
                      }
                      catch (IOException exc) {
                          donerecv = 0;
                          throw new IOException (exc.getMessage());
                      }
                      catch (OrbErrorException exc) {
                          donerecv = 0;
                          throw exc;
                      }
                      if (rsp.what == request.what
                              || rsp.what == ORBREAPL && request.what == ORBREAP
                              || rsp.what == ORBGETL && request.what == ORBGET) {
                          donerecv = 1;
                          done = 1;
                      }
                  }
              } else {
                  done = 1;
              }
          }
      }
  
      private void orbReopen () throws UnknownHostException, IOException {
      }
  
      private void sendOrbrequest (Request req) throws IOException {
          byte b[];
          int size;
  
          if (req == null) return;
          outBuf.write ( syncBuf, 0, 4 );
          outBuf.writeInt ( req.what );
          switch (req.what) {
              case ORBOPEN:
                  outBuf.writeInt ( req.hello.handshake );
                  outBuf.write ( req.hello.whoBuf, 0, req.hello.whoBuf.length);
                  outBuf.write ( req.hello.whatBuf, 0, req.hello.whatBuf.length);
                  outBuf.writeInt ( req.hello.pid );
                  outBuf.write ( req.hello.permissionBuf,
  			       0, req.hello.permissionBuf.length );
                  break;
              case ORBHALT:
              case ORBCLOSE:
              case ORBSTAT:
              case ORBSOURCES:
              case ORBCLIENTS:
  //	    case ORBTELL:
  //	    case ORBPING:
  //	    case ORBID:
                  break;
              case ORBSELECT:
                  b = req.select.getBytes();
                  size = b.length;
                  outBuf.writeInt ( size+1 ) ;
                  outBuf.write ( b, 0, size ) ;
                  outBuf.writeByte ( 0 ) ;
                  break;
              case ORBREJECT:
                  b = req.reject.getBytes();
                  size = b.length;
                  outBuf.writeInt ( size+1 ) ;
                  outBuf.write ( b, 0, size ) ;
                  outBuf.writeByte ( 0 ) ;
                  break;
              case ORBSEEK:
              case ORBGET:
                  outBuf.writeInt ( req.pktCode ) ;
                  break;
              case ORBAFTER:
  	    case ORBBEFORE:
                  outBuf.writeDouble (req.time ) ;
                  break;
              case ORBREAP:
                  outBuf.writeDouble ( req.reapMaxtime ) ;
                  outBuf.writeInt ( req.reapMaxbytes ) ;
                  outBuf.writeInt ( req.reapMaxpkts ) ;
                  break;
  	    case ORBPUT:
  		// FixMe: check that packet length < 65538 and srcname.length < 64.
  		outBuf.writeInt(-1);
  		outBuf.writeShort(req.pkg.packet.length);
  		outBuf.writeShort(req.pkg.srcname.toString().length() + 1);
  		outBuf.writeDouble(req.time);
                  outBuf.write(req.pkg.srcname.toString().getBytes("US-ASCII"), 0, req.pkg.srcname.toString().length());
  		outBuf.writeByte(0); // null termination
  		outBuf.write(req.pkg.packet, 0, req.pkg.packet.length);
  		break;
              default:
                  throw new IllegalArgumentException ("Illegal request value");
          }
      }
  
      private void recvOrbresponse (Response rsp)
  	throws OrbErrorException, IOException, EOFException {
  
  	int i, size;
  
          if (rsp == null) return;
          sync (inBuf);
          rsp.what = inBuf.readInt ();
          rsp.result = inBuf.readInt ();
          switch (rsp.result) {
              case 0:
                  switch (rsp.what) {
                      case ORBOPEN:
                          rsp.orbStart    = inBuf.readDouble ();
                          rsp.serverStart = inBuf.readDouble ();
                          rsp.latestPktid = inBuf.readInt ();
                          break;
                      case ORBCLOSE:
                      case ORBSETLOGGING:
                      case ORBHALT:
                      case ORBSETPRI:
                      case ORBKILL:
                          break;
                      case ORBSELECT:
                      case ORBREJECT:
                          rsp.nSelections = inBuf.readInt ();
                          break;
                      case ORBSEEK:
                      case ORBAFTER:
  		    case ORBBEFORE:
                      case ORBTELL:
                          rsp.pktid = inBuf.readInt () ;
                          break;
                      case ORBSTAT:
                          rsp.orbStat.maxdataBytes    = inBuf.readInt () ;
                          rsp.orbStat.maxPkts         = inBuf.readInt () ;
                          rsp.orbStat.maxSources      = inBuf.readInt () ;
                          rsp.orbStat.nClients        = inBuf.readInt () ;
                          rsp.orbStat.nSources        = inBuf.readInt () ;
                          rsp.orbStat.orbstartedTime  = inBuf.readDouble () ;
                          rsp.orbStat.whenTime        = inBuf.readDouble () ;
                          rsp.orbStat.pid             = inBuf.readInt () ;
                          rsp.orbStat.address[0]      = inBuf.readByte () ;
                          rsp.orbStat.address[1]      = inBuf.readByte () ;
                          rsp.orbStat.address[2]      = inBuf.readByte () ;
                          rsp.orbStat.address[3]      = inBuf.readByte () ;
                          rsp.orbStat.port            = inBuf.readInt () ;
                          rsp.orbStat.opens           = inBuf.readInt () ;
                          rsp.orbStat.closes          = inBuf.readInt () ;
                          rsp.orbStat.rejected        = inBuf.readInt () ;
                          rsp.orbStat.errors          = inBuf.readInt () ;
                          rsp.orbStat.host            = inbuf2str (ORBHOST_SIZE) ;
                          rsp.orbStat.who             = inbuf2str (ORBWHO_SIZE) ;
                          rsp.orbStat.version         = inbuf2str (ORBVERSION_SIZE) ;
                          rsp.orbStat.orbinitializedTime = inBuf.readDouble () ;
                          rsp.orbStat.messages        = inBuf.readInt () ;
                          rsp.orbStat.connections     = inBuf.readInt () ;
                          break;
                      case ORBSOURCES:
                          rsp.sourceWhen              = inBuf.readDouble () ;
                          size                        = inBuf.readInt () ;
                          rsp.source                  = new OrbSource[size];
                          for (i=0; i<size; i++) {
                              rsp.source[i]               = new OrbSource ();
                              rsp.source[i].whenTime      = rsp.sourceWhen;
                              rsp.source[i].srcname       = inbuf2str (ORBSRCNAME_SIZE) ;
                              rsp.source[i].active        = inBuf.readInt () ;
                              rsp.source[i].oldestPktid   = inBuf.readInt () ;
                              rsp.source[i].latestPktid   = inBuf.readInt () ;
                              rsp.source[i].npktsOrb      = inBuf.readInt () ;
                              rsp.source[i].nbytesOrb     = inBuf.readInt () ;
                              rsp.source[i].oldestTime    = inBuf.readDouble () ;
                              rsp.source[i].latestTime    = inBuf.readDouble () ;
                          }
                          break;
                      case ORBCLIENTS:
                          rsp.clientWhen              = inBuf.readDouble () ;
                          size                        = inBuf.readInt () ;
                          rsp.client                  = new OrbClient[size];
                          for (i=0; i<size; i++) {
                              rsp.client[i]               = new OrbClient ();
                              rsp.client[i].whenTime      = rsp.clientWhen;
                              rsp.client[i].started       = inBuf.readDouble () ;
                              rsp.client[i].lastpktTime   = inBuf.readDouble () ;
                              rsp.client[i].currentPktid  = inBuf.readInt () ;
                              rsp.client[i].packetsTransferred  = inBuf.readInt () ;
                              rsp.client[i].bytesTransferred  = inBuf.readInt () ;
                              rsp.client[i].bytesRead     = inBuf.readInt () ;
                              rsp.client[i].bytesWritten  = inBuf.readInt () ;
                              rsp.client[i].nreads        = inBuf.readInt () ;
                              rsp.client[i].nwrites       = inBuf.readInt () ;
                              rsp.client[i].nrequests     = inBuf.readInt () ;
                              rsp.client[i].messages      = inBuf.readInt () ;
                              rsp.client[i].lastRequest   = inBuf.readInt () ;
                              rsp.client[i].priority      = inBuf.readInt () ;
                              rsp.client[i].errors        = inBuf.readInt () ;
                              rsp.client[i].select        = inbuf2strn (SELECT_MAX);
                              rsp.client[i].reject        = inbuf2strn (SELECT_MAX);
                              rsp.client[i].fd            = inBuf.readInt () ;
                              rsp.client[i].thread        = inBuf.readInt () ;
                              rsp.client[i].address[0]    = inBuf.readByte () ;
                              rsp.client[i].address[1]    = inBuf.readByte () ;
                              rsp.client[i].address[2]    = inBuf.readByte () ;
                              rsp.client[i].address[3]    = inBuf.readByte () ;
                              rsp.client[i].port          = inBuf.readInt () ;
                              rsp.client[i].who           = inbuf2str (ORBWHO_SIZE) ;
                              rsp.client[i].host          = inbuf2str (ORBHOST_SIZE) ;
                              rsp.client[i].what          = inbuf2str (ORBWHAT_SIZE) ;
                              rsp.client[i].pid           = inBuf.readInt () ;
                              rsp.client[i].permission    = inbuf2str (1) ;
                          }
                          break;
                      case ORBREAP:
                          rsp.pkg.pktid = inBuf.readInt () ;
                          rsp.pkg.pktsize = inBuf.readUnsignedShort () ;
                          int srcsize = inBuf.readUnsignedShort () ;
                          if (srcsize > ORBSRCNAME_SIZE) srcsize = ORBSRCNAME_SIZE;
                          rsp.pkg.time = inBuf.readDouble () ;
                          rsp.pkg.srcname = new SourceName(inbuf2str(srcsize));
                          if (rsp.pkg.pktsize > 0) {
                              if (rsp.pkg.packet == null || rsp.pkg.packet.length < rsp.pkg.pktsize) {
                                  // FixMe: remove debug statement
  				System.out.println ("Resizing to " + rsp.pkg.pktsize + " bytes");
                                  rsp.pkg.packet = new byte[rsp.pkg.pktsize];
                              }
                              inBuf.readFully (rsp.pkg.packet, 0, rsp.pkg.pktsize) ;
                          }
                          break;
                      default:
                          throw new IllegalArgumentException ("Illegal response value");
                  }
                  break;
              default:
                  rsp.errMsg = inbuf2strn (512);
                  throw new OrbErrorException (rsp.errMsg);
          }
      }
  
      private void startReap (double reap_maxtime, int reap_maxbytes, int reap_maxpkts) throws OrbErrorException, IOException, EOFException {
          request.what = ORBREAP;
          request.reapMaxtime = reap_maxtime;
          request.reapMaxbytes = reap_maxbytes;
          request.reapMaxpkts = reap_maxpkts;
          orbClient (request, null);
      }
  
      private void reapPacket () throws OrbErrorException, IOException, EOFException {
          request.what = ORBREAP;
          orbClient (null, reply);
          if (reply.pkg.pktid == ORB_ENDREAP) reaped = 0;
      }
  
      private static void sync (DataInputStream in) throws IOException, EOFException {
          int i = 0;
          byte sync_in[] = new byte[4];
  
          while (i < 4) {
              in.readFully (sync_in, 0, 1) ;
              if (sync_in[0] == syncBuf[i]) {
                  i++;
              } else {
                  i = 0;
              }
          }
      }
  
      private static void str2buf (String string, byte bytes[]) {
          byte b[] = string.getBytes () ;
          int size = b.length ;
          if (size > bytes.length) size = bytes.length;
          System.arraycopy (b, 0, bytes, 0, size);
      }
  
      private String inbuf2str (int l) throws IOException {
          int i;
  
          if (l < 1) {
              return (new String(""));
          }
          byte ibuf[] = new byte[l];
          inBuf.readFully (ibuf);
          for (i=0; i<l; i++) if (ibuf[i] == 0) break;
          return (new String (ibuf, 0, i));
      }
  
      private String inbuf2strn (int l) throws IOException {
          int i, n;
  
          n = inBuf.readInt ();
          if (n < 1) {
              return (new String(""));
          }
          if (n > l) n = l;
          byte ibuf[] = new byte[n];
          inBuf.readFully (ibuf);
          for (i=0; i<n; i++) if (ibuf[i] == 0) break;
          return (new String (ibuf, 0, i));
      }
  
      /** Member Clases */
  
      private class Openstring extends java.lang.Object {
          public int pid = -1;
          public int handshake = ORBMAGIC;
          public String permission;
          public String what;
          public String who;
          public byte whatBuf[] = new byte[128];
          public byte whoBuf[] = new byte[24];
          public byte permissionBuf[] = new byte[1];
  
          /* Constructor */
  
          public Openstring (String permission, String what, String who) {
              this.permission = permission;
              this.what = what;
              this.who = who;
              str2buf (what, whatBuf);
              str2buf (who, whoBuf);
              str2buf (permission, permissionBuf);
          }
      }
  
      private class Request extends java.lang.Object {
          public double time;
          public double reapMaxtime;
          public String select;
          public String reject;
          public OrbRawPacket pkg = new OrbRawPacket();
          public Openstring hello;
          public int thread;
          public int newPri;
          public int logFlag;
          public int pktCode;
          public int reapMaxpkts;
          public int reapMaxbytes;
          public int athread;
          public int what;
      }
  
      private class Response extends java.lang.Object {
          public double sourceWhen;
          public double clientWhen;
          public double serverStart;
          public double orbStart;
          public OrbClient client[] = null;
          public OrbSource source[] = null;
          public OrbRawPacket pkg = new OrbRawPacket();
          public OrbStat orbStat = new OrbStat();
          public int pktid;
          public int nSelections;
          public int version;
          public int thread;
          public int latestPktid;
          public int active;
          public int result;
          public int what;
          public String errMsg;
      }
  
  }
  