Listing 4 Transaction management functions

/* Open a network client (master)
  Sets up the global masterid as the client name id. Note only
  one client per machine */
open_net_client(char *name)
{  struct Ncb command_ncb ;
   int dgstat = -1 ;

   if (chk_net_bios())
     { printf("%s", errmes1) ;
       exit(1) ;
     }
   if (masterid == -1)
    { NetDelName(name, command_ncb) ; // Precaution against a lost name
      strcpy(mastername, name) ;
      if ((dgstat = NetAddName(mastername,command_ncb)) == 0)
        masterid = command_ncb.NCB_num ;
    }
   return(dgstat) ;
}

/* ***********************  */
/* Close the network client */
close_net_client(void)
{ struct Ncb command_ncb ;
  int dgstat ;

  dgstat = NetDelName(mastername, command_ncb) ;
  masterid = -1 ;
  return(dgstat) ;
}

/* ****************************************************************** */
/* Install a datagram server on a given local name. Slave will call post
  function given when a transaction occurs. Slave will return 0 to master
  if post function was successful or error code if not.
  The Net name descriptor is entered in a linked list.
  Return pointer to descriptor if successful                        */
struct netrpcserver *install_rpcserver(char *name, void *(*rpc)(void *),
                               int replysize)
{  struct netrpcserver *ep ;
  int dgstat = 0 ;
  void netslavepost(struct Ncb far *) ;

/* Check for Net Bios first */
  if (chk_net_bios())
    { printf("%s", errmes1) ;
      exit(1) ;
    }

/* Malloc descriptor space */
   if ((ep = (struct netrpcserver *)malloc(sizeof(struct netrpcserver))) == NULL)
     return(NULL) ;
   if ((ep->name = strdup(name)) == NULL)
     { free(ep) ;
       return(NULL) ;
     }
/* Clear error count and last_dgstat */
  ep->errcnt = 0 ;
  ep->errcnt = 0 ;
/* Set up Remote procedure call and replysize */
   ep->rpc = rpc ;
   if (replysize < DGRAMSIZE)
     ep->replysize = replysize ;
   else
     ep->replysize = DGRAMSIZE ;
/* Malloc space for Ncb's */
   if ((ep->receivencbptr = (struct Ncb *)calloc(2,sizeof(struct Ncb))) == NULL)
     { free(ep->name) ;
       free(ep) ;
       return(NULL) ;
     }
   ep->sendncbptr = ep->receivencbptr + 1 ;
/* Malloc space for Datagram buffer */
   if ((ep->dgbufin = (char *)malloc(DGRAMSIZE)) == NULL)
     { free(ep->name) ;
       free(ep) ;
       return(NULL) ;
     }
/* Install name */
   NetDelName_p(name, ep->receivencbptr) ;
   if ((dgstat = net_name_command(NCBADDNAME,name,NULL,ep->receivencbptr)) != 0)
     { free(ep->dgbufin) ;
       free(ep->receivencbptr) ;
       free(ep->name) ;
       free(ep) ;
       return(NULL) ;
     }
/* Set up name id */
  ep->id = ep->receivencbptr->NCB_num ;
/* and link in */
  if (netrpcserverlist == NULL)
    { netrpcserverlist = ep ;
      ep->prev = NULL ;
    }
  else
    { ep->prev = netrpcserverlist ;
      netrpcserverlist = ep;
    }

/* Now set up receive */
  if ( dgstat |= net_dgram_command(NCBRECEIVEDATAGRAM | NCBNO_WAIT,ep->id,NULL,
                             ep->dgbufin,sizeof(struct dgbufsize),
                             NULL,ep->receivencbptr))
    { net_name_command(NCBDELETENAME,name,NULL,ep->receivencbptr) ;
      free(ep->dgbufin) ;
      free(ep->receivencbptr) ;
      free(ep->name) ;
      free(ep) ;
      return(NULL) ;
    }
  else
    return(ep) ;
}

/* ****************************************************************** */
/* Remove all net names and pending receives for all datagram servers */
void remove_all_rpcservers(void)
{ char *ptr;
  struct Ncb command_ncb ;

  if (netrpcserverlist != NULL)
    { do
      {
        net_command_cancel(netrpcserverlist->receivencbptr,&command_ncb) ;
        NetDelName(netrpcserverlist->name, command_ncb) ;
        if (netrpcserverlist->errcnt)
         { printf("%d errors occured on rpcserver %s\n", netrpcserverlist->errcnt,
                 netrpcserverlist->name) ;
           printf("Last error was %s\n",
                 get_neterrmess(netrpcserverlist->last_dgstat)) ;
         }
        free(netrpcserverlist->dgbufin) ;
        free(netrpcserverlist->receivencbptr) ;
        free(netrpcserverlist->name) ;

        ptr= (char *) netrpcserverlist ;
        netrpcserverlist = netrpcserverlist->prev ;
        free(ptr) ;
      }
     while (netrpcserverlist != NULL) ;
   }
}

/* ****************************************************************** */
/* Transact a message
   Uses global masterid as sender id. This must have been set up first
   by open_net_client().
   Note : I would advise the implementation of interrupt driven timeout capability
and locking
   against re-entrance for multi-threaded applications.
*/

net_transact(char *name, void *bufin, int bufinlen,
          void *bufout, int bufoutlen)
{
  struct Ncb send_ncb, receive_ncb, command_ncb ;
  char remotename[17]  ;
  int dgstat = 0 ;
  long count = 0 ;

  dgstat |= net_dgram_command(NCBRECEIVEDATAGRAM | NCBNO_WAIT, masterid, NULL,
                        bufin, bufinlen, NULL, &receive_ncb) ;
  dgstat |= net_dgram_command(NCBSENDDATAGRAM, masterid, name, bufout, bufoutlen
,NULL,
                        &send_ncb) ;

  while(receive_ncb.NCB_cmd_cplt == 0xff)
    { count++ ;
      if (count > 100000)
       { dgstat = NETTIMEOUTERR;
         net_command_cancel(&receive_ncb,&command_ncb) ;
         break ;
       }
    }

  return(dgstat) ;
}

/* ****************************************************************** */
/* net_comms(). This is the datagram server function that
   services transaction requests. It must be called regularly to service
   all received transaction requests                                 */
void net_comms()
{ struct netrpcserver *netrpcserverptr ;
  char netmaster[17]  ;
  void *replyptr ;
  int dgstat = 0 ;

/* Track list serving any pending datagrams by calling the server funtion
   with a void pointer to the datagram.
   The server function will return a pointer to its reply message which is
   returned to the transaction master.
*/
  netrpcserverptr = netrpcserverlist ;
  while(netrpcserverptr != NULL)
   { if (netrpcserverptr->receivencbptr->NCB_cmd_cplt != 0xff)
      { dgstat |= netrpcserverptr->receivencbptr->NCB_cmd_cplt ;
        ret_ncb_callname(netmaster, netrpcserverptr->receivencbptr) ;
        replyptr = (*netrpcserverptr->rpc)(netrpcserverptr->dgbufin) ;
        dgstat |= netd_gram_command(NCBRECEIVEDATAGRAM | NCBNO_WAIT,netrpcserverptr->id,
                               NULL,netrpcserverptr->dgbufin,sizeof(struct dgbufsize),
                               NULL,netrpcserverptr->receivencbptr) ;
        dgstat |= net_dgram_command(NCBSENDDATAGRAM,netrpcserverptr->id, netmaster,
                replyptr, netrpcserverptr->replysize, NULL,
                netrpcserverptr->sendncbptr) ;
        if (dgstat)
          { netrpcserverptr->errcnt++;
            netrpcserverptr->last_dgstat = dgstat ;
          }
       }
     netrpcserverptr = netrpcserverptr->prev ;
   }
}
/* End of File */