//=========================================================================
// Summary  : */
// Filename : SharedObjectClient.cc
// Author   : Tom O'Reilly                                                  */
// Project  : */
// Revision : 1
// Created  : 2000/08/19
// Modified : 2000/08/19
//=========================================================================
// Description :
//=========================================================================
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <sys/name.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/proxy.h>
#include "SharedObjectClient.h"
#include "VehicleConfigurator.h"
#include "VehicleConfigurationIF.h"
#include "Syslog.h"
#include "System.h"
#include <sys/vc.h>


SharedObjectClient::SharedObjectClient(const char *name,
				       const char *serverName,
				       int serverConnectTimeout)
  : SharedObject(name)
{
  _serverName = strdup(serverName);
  _serverPid = NoPid;
  _connected = False;

  if (serverConnectTimeout == DoNotConnect)
    return;

  bind(serverConnectTimeout);
}


SharedObjectClient::SharedObjectClient(const char *name)
  : SharedObject(name)
{
  _serverName = 0;
  _serverPid = NoPid;
  _connected = False;
  _serverConnectTimeout = 10;
}


SharedObjectClient::~SharedObjectClient()
{
    // probly should do this with a little more subtlety
  qnx_vc_detach(_serverPid);
  free((void *)_serverName);
}


void SharedObjectClient::bind(int serverConnectTimeout)
{
  findServer(serverConnectTimeout);
}


void SharedObjectClient::bind(const char *serverName,
			      int serverConnectTimeout)
{
  setServerName(serverName);
  findServer(serverConnectTimeout);
}


void SharedObjectClient::setServerName(const char *name)
{
  free((void *)_serverName);
  _serverName = strdup(name);
}


void SharedObjectClient::findServer(int timeoutSecs)
{
	Boolean debug = False;
	char _realName[96];

	int elapsed = 0;

	// We want to do this loop at least once (hence the do... while construct)
	do {
		// So if we're looking for the vehicle configuration server, it
		//  would be silly to try to use a VehicleConfigurator function
		//  to get the name, 'cause this would cause and endless loop.
		if ( stricmp( _serverName, VehicleConfigurationIFServerName ) )
		   VehicleConfigurator::getTaskNameFromIFName(_serverName, _realName);
		else
		   strcpy ( _realName, VehicleConfigurationIFServerName);

		if ((_serverPid = qnx_name_locate(0, _realName, 0, 0)) != -1) {
			// Found it!
			_connected = True;
			return;
		}

		elapsed++;
		// Only do a sleep if we're gonna do another round
		if ( elapsed < timeoutSecs ) { sleep(1); }

	} while ( elapsed < timeoutSecs );

	throw MissingServer(_serverName);
}


void SharedObjectClient::send(Request *request, int nRequestBytes,
			      Reply *reply, int nReplyBytes)
{
  Boolean debug = False;

  if (!connected()) {
    // Not connected to server; try to find it
    findServer();
  }

  dprintf("SharedObjectClient::send()- server=%d, requestBytes=%d, "
	  "replyBytes=%d\n", _serverPid, nRequestBytes, nReplyBytes);

  if (Send(_serverPid, (void *)request, (void *)reply,
	   nRequestBytes, nReplyBytes) == -1) {

    if (errno == ESRCH) {
      // Server pid no longer there
      _connected = False;
      throw MissingServer(_serverName);
    } else if (errno == EINTR ) {
	 // Boy, I hope this won't recurse forever.
	 send( request, nRequestBytes, reply, nReplyBytes );
	 return;
    }
    char errorBuf[256];

    dprintf("SharedObjectClient::send() - errno=%d\n", errno);

    sprintf(errorBuf, "SharedObjectClient::send() failed - %s",
	    strerror(errno));

    dprintf("%s\n", errorBuf);

    throw Error(errorBuf);
  }
  dprintf("SharedObjectClient::send()- done\n");

}



