void remote_pvd_pwrcli::objectName( co_procom *pcom, char *name, pwr_tOix poix)
{
  rpvd_sMsgObjectName msg;
  rpvd_sMsgObject *rmsg;
  pwr_tStatus sts;

  msg.Type = rpvd_eMsg_ObjectName;
  msg.Id = rpvd_id++;
  strcpy( msg.Name, name);
  msg.POid.vid = rpvd_vid;
  msg.POid.oix = poix;
  
  if ( pvd_cLog) logg( "ObjName", poix, name);

  sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }
  if ( sts == REM__TIMEOUT) {
    pcom->provideStatus( REM__UDPNOCON);
    return;
  }
  while ( rmsg->Id != msg.Id) {
    dispatch( pcom, (rpvd_sMsg *)rmsg);

    sts = udp_Receive( (char **)&rmsg, 1000);
    if ( sts == REM__TIMEOUT) {
      pcom->provideStatus( REM__DISORDER);
      return;
    }
  }
  if ( rmsg->Type != rpvd_eMsg_Object) {
    pcom->provideStatus( REM__DISORDER);
    return;
  }
  if ( EVEN( rmsg->Status)) {
    pcom->provideStatus( rmsg->Status);
    return;
  }

  vector<procom_obj> m_list;
  for ( int i = 0; i < rmsg->OSize; i++) {
    procom_obj item;
      
    item.oix = rmsg->o[i].oix;
    item.fthoix = rmsg->o[i].fthoix;
    item.fchoix = rmsg->o[i].fchoix;
    item.lchoix = rmsg->o[i].lchoix;
    item.fwsoix = rmsg->o[i].fwsoix;
    item.bwsoix = rmsg->o[i].bwsoix;
    item.cid = rmsg->o[i].cid;
    strcpy( item.name, rmsg->o[i].name);
    m_list.push_back(item);
  }
  pcom->provideObjects( GDH__SUCCESS, m_list);
}
void remote_pvd_pwrcli::nodeUp()
{
  rpvd_sMsgAny msg;
  rpvd_sMsgAny *rmsg;
  pwr_tStatus sts;

  msg.Type = rpvd_eMsg_NodeUp;
  msg.Id = rpvd_id++;
  
  sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  if ( EVEN(sts) || sts == REM__TIMEOUT) {
  }
}
void remote_pvd_pwrcli::subDisassociateBuffer( co_procom *pcom, pwr_tSubid subid)
{
  rpvd_sMsgSubRemove msg;
  rpvd_sMsgAny *rmsg;
  pwr_tStatus sts;

  // Remove from local list
  sublist_iterator it = rpvd_sublist.find( subid.rix);
  if ( it != rpvd_sublist.end())
    rpvd_sublist.erase( it);

  // Send message
  msg.Type = rpvd_eMsg_SubRemove;
  msg.Id = rpvd_id++;
  msg.Rix = subid.rix;

  if ( pvd_cLog) logg( "DisoBuff", subid.rix, "(rix)");

  sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }
  if ( sts == REM__TIMEOUT) {
    pcom->provideStatus( REM__UDPNOCON);
    return;
  }
  while ( rmsg->Id != msg.Id) {
    dispatch( pcom, (rpvd_sMsg *)rmsg);

    sts = udp_Receive( (char **)&rmsg, 1000);
    if ( sts == REM__TIMEOUT) {
      pcom->provideStatus( REM__DISORDER);
      return;
    }
  }
  if ( rmsg->Type != rpvd_eMsg_Status) {
    pcom->provideStatus( REM__DISORDER);
    return;
  }
  pcom->provideStatus( rmsg->Status);
}
void remote_pvd_pwrcli::subRestore()
{
  rpvd_sMsgSubAdd msg;
  rpvd_sMsgAny *rmsg;
  pwr_tStatus sts;

  for ( sublist_iterator it = rpvd_sublist.begin(); it != rpvd_sublist.end(); it++) {
    
    msg.Type = rpvd_eMsg_SubAdd;
    msg.Id = rpvd_id++;

    msg.Oid = it->second.m_oid;
    strcpy( msg.Attribute, it->second.m_attr);
    msg.Rix = it->first;
    msg.Size = it->second.m_size;

    sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  }

}
int main(int argc, char *argv[])
{
  pwr_tStatus sts;
  char remote_address[40];
  char remote_host_name[40];
  rpvd_sMsg *msg;
  rpvd_sMsgAny umsg;
  rpvd_sMsgAny *rmsg;
  int udp_port;

  /* Read arguments */
  if ( argc < 3) {
    usage();
    exit(0);
  }
  strcpy( remote_address, argv[1]);
  strcpy( remote_host_name, argv[2]);

  if ( argc >= 4) {
    sts = sscanf( argv[3], "%d", &udp_port);
    if ( sts != 1) {
      usage();
      exit(0);
    } 
  }
  else
    udp_port = 3051;

  sts = udp_Init( remote_address, remote_host_name, udp_port);
  if ( EVEN(sts)) {
    exit(0);
  }

  sts = gdh_Init( "remote_pvd_pwrsrv");
  if ( EVEN(sts)) return sts;

  umsg.Type = rpvd_eMsg_NodeUp;
  umsg.Id = 0;
  sts = udp_Request( (char *)&umsg, sizeof(umsg), (char **)&rmsg);
  if ( ODD(sts) && sts != REM__TIMEOUT && ODD(rmsg->Status))
    printf( "Link up\n");
  
  for (;;) {
    sts = udp_Receive( (char **)&msg, 5000);
    if ( sts == REM__TIMEOUT) {
      printf( "Alive\n");
    }
    else if ( ODD(sts)) {
      switch ( msg->Any.Type) {
      case rpvd_eMsg_Oid:
	pwrsrv_Oid( &msg->Oid);
	break;
      case rpvd_eMsg_ObjectName:
	pwrsrv_ObjectName( &msg->ObjectName);
	break;
      case rpvd_eMsg_ReadAttribute:
	pwrsrv_ReadAttribute( &msg->ReadAttribute);
	break;
      case rpvd_eMsg_WriteAttribute:
	pwrsrv_WriteAttribute( &msg->WriteAttribute);
	break;
      case rpvd_eMsg_SubAdd:
	pwrsrv_SubAdd( &msg->SubAdd);
	break;
      case rpvd_eMsg_SubRemove:
	pwrsrv_SubRemove( &msg->SubRemove);
	break;
      case rpvd_eMsg_SubRequest:
	pwrsrv_SubSend( &msg->Any);
	break;
      case rpvd_eMsg_NodeUp:
	pwrsrv_NodeUp( &msg->Any);
	break;
      }
    }
  }
}
void remote_pvd_pwrcli::subAssociateBuffer( co_procom *pcom, void **buff, int oix,
					    int offset, int size, pwr_tSubid subid)
{
  rpvd_sMsgSubAdd msg;
  rpvd_sMsgAny *rmsg;
  pwr_tStatus sts;
  pwr_tAttrRef aref;
  pwr_tOName aname;
  pwr_tCid cid;
  pwr_tUInt32 osize;

  msg.Type = rpvd_eMsg_SubAdd;
  msg.Id = rpvd_id++;
  msg.Oid.oix = oix;
  msg.Oid.vid = rpvd_vid;
  
  sts = gdh_GetObjectSize( msg.Oid, &osize);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }

  memset( &aref, 0, sizeof(aref));
  aref.Objid = msg.Oid;
  aref.Offset = offset;
  aref.Size = size;
  if ( (int) osize == size)
    aref.Flags.b.Object = 1;

  sts = gdh_GetObjectClass( msg.Oid, &cid);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }

  if ( aref.Flags.b.Object)
    strcpy( aname, "");
  else {
    sts = gdh_ClassAttrrefToAttr( cid, &aref, aname, sizeof(aname));
    if ( EVEN(sts)) {
      pcom->provideStatus( sts);
      return;
    }
  }
  strcpy( msg.Attribute, aname);
  msg.Rix = subid.rix;
  msg.Size = size;


  if ( pvd_cLog) logg( "AssoBuff", msg.Oid.oix, aname);

  sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }
  if ( sts == REM__TIMEOUT) {
    pcom->provideStatus( REM__UDPNOCON);
    return;
  }
  while ( rmsg->Id != msg.Id) {
    dispatch( pcom, (rpvd_sMsg *)rmsg);

    sts = udp_Receive( (char **)&rmsg, 1000);
    if ( sts == REM__TIMEOUT) {
      pcom->provideStatus( REM__DISORDER);
      return;
    }
  }
  if ( rmsg->Type != rpvd_eMsg_Status) {
    pcom->provideStatus( REM__DISORDER);
    return;
  }
  if ( EVEN( rmsg->Status)) {
    pcom->provideStatus( rmsg->Status);
    return;
  }

  pcom->provideStatus( rmsg->Status);
  if ( ODD(rmsg->Status)) {
    // Add to local list
    subitem s(size, cid, offset, msg.Attribute, msg.Oid);
    rpvd_sublist[subid.rix] = s;
    *buff = rpvd_sublist[subid.rix].m_p;
  }
}
void remote_pvd_pwrcli::readAttribute( co_procom *pcom, pwr_tOix oix, 
				       unsigned int offset, unsigned int size)
{
  rpvd_sMsgReadAttribute msg;
  rpvd_sMsgAttribute *rmsg;
  pwr_tStatus sts;
  pwr_tAttrRef aref;
  pwr_tOName aname;
  pwr_tCid cid;

  msg.Type = rpvd_eMsg_ReadAttribute;
  msg.Id = rpvd_id++;
  msg.Oid.oix = oix;
  msg.Oid.vid = rpvd_vid;
  
  memset( &aref, 0, sizeof(aref));
  aref.Objid = msg.Oid;
  aref.Offset = offset;
  aref.Size = size;

  sts = gdh_GetObjectClass( msg.Oid, &cid);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }

  sts = gdh_ClassAttrrefToAttr( cid, &aref, aname, sizeof(aname));
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }

  strcpy( msg.Attribute, aname);

  if ( pvd_cLog) logg( "Read", aref.Objid.oix, aname);

  sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  if ( pvd_cLog) logg( "Reply", sts, "");
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }
  if ( sts == REM__TIMEOUT) {
    pcom->provideStatus( REM__UDPNOCON);
    return;
  }
  while ( rmsg->Id != msg.Id) {
    dispatch( pcom, (rpvd_sMsg *)rmsg);

    sts = udp_Receive( (char **)&rmsg, 1000);
    if ( sts == REM__TIMEOUT) {
      pcom->provideStatus( REM__DISORDER);
      return;
    }
  }
  if ( rmsg->Type != rpvd_eMsg_Attribute) {
    pcom->provideStatus( REM__DISORDER);
    return;
  }
  if ( EVEN( rmsg->Status)) {
    pcom->provideStatus( rmsg->Status);
    return;
  }

  // TODO Float conversion !!!
  if ( rpvd_opsys == 0 || rpvd_opsys == gdbroot->my_node->os) {
    void *p = &rmsg->Value;
    pcom->provideAttr( GDH__SUCCESS, oix, rmsg->Size, p);
  }
  else {
    gdb_sNode 		n;
    gdb_sClass		*cp;
    void		*p = NULL;

    memset( &n, 0, sizeof(n));
    n.os = (co_eOS) rpvd_opsys;

    p = malloc( max(rmsg->Size, (int)aref.Size));
    size = aref.Size;
    cp = (gdb_sClass *) hash_Search(&sts, gdbroot->cid_ht, &cid);
    if (cp != NULL) {
      rndc_ConvertData(&sts, &n, cp, p, &rmsg->Value, (pwr_tUInt32 *)&size,
		      ndc_eOp_encode, aref.Offset, 0);
      pcom->provideAttr( GDH__SUCCESS, oix, rmsg->Size, p);
    }
    else {
      pcom->provideStatus( GDH__NOSUCHCLASS);
    }
  }

}
void remote_pvd_pwrcli::writeAttribute( co_procom *pcom, pwr_tOix oix, 
					unsigned int offset,
					unsigned int size, char *buffer)
{
  rpvd_sMsgWriteAttribute msg;
  rpvd_sMsgAny *rmsg;
  pwr_tStatus sts;
  pwr_tAttrRef aref;
  pwr_tOName aname;
  pwr_tCid cid;

  msg.Type = rpvd_eMsg_WriteAttribute;
  msg.Id = rpvd_id++;
  msg.Oid.oix = oix;
  msg.Oid.vid = rpvd_vid;
  msg.Size = size;
  
  memset( &aref, 0, sizeof(aref));
  aref.Objid = msg.Oid;
  aref.Offset = offset;
  aref.Size = size;

  sts = gdh_GetObjectClass( msg.Oid, &cid);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }

  sts = gdh_ClassAttrrefToAttr( cid, &aref, aname, sizeof(aname));
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }

  strcpy( msg.Attribute, aname);
  // TODO Float conversion
  if ( rpvd_opsys == 0 || rpvd_opsys == gdbroot->my_node->os)
    memcpy( &msg.Value, buffer, size);
  else {
    gdb_sNode 		n;
    gdb_sClass		*cp;
    int			rsize;

    memset( &n, 0, sizeof(n));
    n.os = (co_eOS) rpvd_opsys;

    rsize = aref.Size;
    cp = (gdb_sClass *) hash_Search(&sts, gdbroot->cid_ht, &cid);
    if (cp != NULL) {
      rndc_ConvertData(&sts, &n, cp, &msg.Value, buffer, (pwr_tUInt32 *)&rsize,
		      ndc_eOp_decode, aref.Offset, 0);
    }
  }

  if ( pvd_cLog) logg( "Write", aref.Objid.oix, aname);

  sts = udp_Request( (char *)&msg, sizeof(msg), (char **)&rmsg);
  if ( EVEN(sts)) {
    pcom->provideStatus( sts);
    return;
  }
  if ( sts == REM__TIMEOUT) {
    pcom->provideStatus( REM__UDPNOCON);
    return;
  }
  
  while ( rmsg->Id != msg.Id) {
    dispatch( pcom, (rpvd_sMsg *)rmsg);

    sts = udp_Receive( (char **)&rmsg, 1000);
    if ( sts == REM__TIMEOUT) {
      pcom->provideStatus( REM__DISORDER);
      return;
    }
  }
  if ( rmsg->Type != rpvd_eMsg_Status) {
    pcom->provideStatus( REM__DISORDER);
    return;
  }
  pcom->provideStatus( rmsg->Status);
}