/* rmtfcnrtn */
#ifdef DOCUMENTATION

title	rmtfcnrtn	remote fuction access routines
index	rmtfcnrtn	remote fuction access routines

synopsis

	  _#include <stdio.h>
	  _#include <cx.h>
	  _#include <stdnet.h>

	  extern int $$nerr;

	  NIOV *try_con(node, task)
	  char *node;	/* remote node name */
	  char *task;	/* remote task name */

description

	The is code impliments remote function routine calls
	in cooperation with tasks based on rmtfcn.c.

	Routines like these are very application specific,
	so few general routines are not supplied, with one 
	exception. Try_con() hides most of the details of connecting
	to a remote task.

	Sample send and receive functions are provided in sndfcn()
	and rcvfcn(). They are NOT callable routines, rather they
	are just templates.

	A typical function to impliment remote function calls
	might be structured as follows:

	.s
	.lit

	sample_fcn(data, len)
	char *data;
	int len;
	{
	  NIOV *np;		/* required net link pointer */
	  NIOV *try_con();	/* connect to remote routine */
	  int ret_val;		/* return status value */

	  if ((np = try_con(NODE, TASK)) == NULL {

		/* cant reach remote, handle error */
	  }

	  if (sndfcn(*data, len, np) == NULL) /* check for error */
	  if (rcvfcn(ret_val, sizeof ret_val, np) == NULL) error

	  return(ret_val);
	}

	.elit
	.s

	The above function would send a packet to a remote function
	task and wait for a status return, which would be passed to
	the caller. We assume the remote function task will disconnect
	and exit after replying with the status.

	Note that this type of routine will use one LUN for each
	remote function and possibly a second for connecting to the
	network. The UNITS option may need to be increased.
bugs

#endif

#include <stdio.h>
#include <cx.h>
#include <stdnet.h>

#define IE_NNT	0242	/* no net open done yet */

NIOV *try_con(node, task)
char *node;	/* remote node name */
char *task;	/* remote task name */
{
  NIOV *np;

  if ((np = con_net(node, task))) return(np);

  if ($$nerr != IE_NNT) 	/* only no net open allowed */
    return(NULL);	/* other connect errors just return */

  /* if opn_net succeeds, call ourself again, else die */

  if(opn_net(0)) return(try_con(ndp));	/* try again */

  tmsg('F', "can't open network, err %o\n", $$nerr);
  exits(4);
}

#ifdef SAMPLE

sndrfa(pktp, pktsiz, rfi)
char *pktp;
int pktsiz;
NIOV *np;
{
  if (!put_net(pktp, pktsiz, np)) {
    tmsg('W', "sndfcn err %o iosb %o %o \n", $$nerr, np->iosb[0], 
	np->iosb[1]);
    return(NULL);
  }
  return(pktsiz);
}

getrfa(pktp, pktsiz, np)
char *pktp;
int pktsiz;
NIOV *np;
{
  int glen;

  if (!(glen = get_net(pktp, pktsiz, np))) {
    tmsg('W', "getfcn err %o iosb %o %o \n", $$nerr, np->iosb[0], 
	np->iosb[1]);
    return(NULL);
  }
  return(glen);
}

#endif
