#include "sfsrosd.h"
#include "sfsdb.h"
#include "rxx.h"

#ifndef MAINTAINER
enum { dumptrace = 0 };
const int asrvtrace (getenv ("ASRV_TRACE") ? atoi (getenv ("ASRV_TRACE")) : 0);
#else /* MAINTAINER */
const bool dumptrace (getenv ("SFSRO_TRACE"));
enum { asrvtrace = 0 };
#endif /* MAINTAINER */

sfsrodb db;
sfs_connectres cres;
sfs_fsinfo fsinfores;

sfsroclient::sfsroclient (ptr<axprt_stream> _x, const authunix_parms *aup)
  : x (_x), destroyed (New refcounted<bool> (false))
{
  xdrsuio xxx (XDR_ENCODE);

  if ((unixauth = aup))
    uid = aup->aup_uid;

  rosrv = asrv::alloc (x, sfsro_program_1,
			 wrap (this, &sfsroclient::dispatch, destroyed));
  sfssrv = asrv::alloc (x, sfs_program_1,
			wrap (this, &sfsroclient::dispatch, destroyed));
  authid_valid = false;
}


sfsroclient::~sfsroclient()
{
  *destroyed = true;
}
void
sfsroclient::dispatch (ref<bool> d, svccb *sbp)
{
  if (!sbp) {
    if (!*d)
      return;
    delete this;
    return;
  }

  if (sbp->prog () == SFS_PROGRAM) {
    switch (sbp->proc ()) {
    case SFSPROC_NULL:
      sbp->reply (NULL);
      return;
    case SFSPROC_CONNECT:
      {
	if (asrvtrace >= 5) {
	  warnx << "client: handled connect\n";
	}
	sbp->reply (&cres);
	return;
      }
    case SFSPROC_GETFSINFO:
      {
	if (asrvtrace >= 5) {
	  warnx << "client: handled getfsinfo\n";
	}
	sbp->reply(&fsinfores);
	return;
      }
    default:
      warnx << "client: unknown proc\n";
      sbp->reject (PROC_UNAVAIL);
      return;
    }
  }
  else {
    switch (sbp->proc ()) {
    case SFSROPROC_NULL:
      sbp->reply (NULL);
      return;
    case SFSROPROC_GETDATA:
      {
	if (asrvtrace >= 5) {
	  warnx << "client: handling request w/ id" << sbp->xid() << "\n";
	}

	sfs_hash *fh = sbp->template getarg<sfs_hash> ();

	if (dumptrace) {
	  u_char *cp = reinterpret_cast<u_char *> (fh->base ());
	  u_char *lim = cp + fh->size ();
	  printf ("  { 0x%02x", *cp);
	  while (++cp < lim)
	    printf (", 0x%02x", *cp);
	  printf (" },\n");
	}
	
	if (asrvtrace >= 5) {
	  warnx << "calling getdata w fh=" << hexdump(fh->base(), fh->size()) 
		<< "\n";
	}
	sfsro_datares *res = New sfsro_datares();
        db.getdata(fh, res, wrap (this, &sfsroclient::getdata_cb, sbp, res, 
				 destroyed));
        return;
      }
    default:
      warnx << "rejected unavailable proc " << sbp->proc () << "\n";
      sbp->reject (PROC_UNAVAIL);
      break;
    }
  }
}

void
sfsroclient::getdata_cb(svccb *sbp, sfsro_datares *res, ref<bool> d) {
  if (*d)
    return;
  sbp->reply(res);
  delete (res);
  return;
}
