/* This set of utility routines shows how to use the netclb routines. The conbk0() routine shows one way to fill in a connect block. This example assumes some familiarity with network and "C" programming. It does work, atleast for us, and provides enough flexiblity to allow real time, ast driven routines. The normal sequence for use is: snet_ast(&net_rcv_function); snet_msg(&net_msg_function); init_net(); connect(node, task) -or wait for connect from other task - */ #include #include #include #include #define NDQLUN 8 /* lun for network data que */ #define LINKLUN 7 /* lun for network link */ #define NETEFN 2 /* network function efn */ #define RECEFN 3 /* recnt efn */ #define SNDEFN 4 /* sndnt efn */ #define IS_SUC 1 /* sucess return */ #define IE_ABO 0361 /* abort during rcv */ #define IE_ALN 0366 /* LUN already established */ #define IE_NLN 0333 /* no link established on LUN */ #define IE_NDA -78 /* no data */ /* c_conblk is part of a_conblk starting at n_snd in a_conblk. the functions that build a connect block for the network connt function must set a structure pointer to point to the right spot in a_conblk. */ static struct c_conblk { /* connt connect block */ byte n_rnd[6]; byte n_rfm; byte n_rot; word n_rdec; byte n_rde[16]; word n_ridc; byte n_rid[16]; word n_rpsc; byte n_rps[8]; word n_racc; byte n_rac[16]; } ; static struct a_conblk { /* accnt connect block */ word n_ctl; word n_segz; byte n_dfm; byte n_dot; word n_ddec; byte n_dde[16]; /* beginnning of c_conblk */ byte n_snd[6]; byte n_sfm; byte n_sot; word n_sdec; byte n_sde[16]; word n_cidc; byte n_cid[16]; word n_cpsc; byte n_cps[8]; word n_cacc; byte n_cac[16]; /* end of c_conblk */ word n_cdev; byte n_cuni; byte n_xxx; word n_cuic; byte n_xxz[40]; word n_cdac; byte n_cda[16]; } conbuf; int $niosb[2]; /* io status block */ static int $netcnct; /* 1 when connection established */ static int (*netfcn)() = -1; /* receive ast handler function */ static int (*netmsg)() = -1; /* network ast handler function */ static int netbuf[512]; snet_ast(nfp) /* set function to call with network packet */ int (*nfp)(); { netfcn = nfp; } snet_msg(nfp) /* set function to call with network message */ int (*nfp)(); { netmsg = nfp; } /* put a buffer to the receiving task - returns chars sent or error code */ putnet(buf, len) char *buf; /* pointer to buffer */ int len; /* length in bytes */ { int status; if (!$netcnct) return(IE_NLN); status = sndwnt(LINKLUN, SNDEFN, $niosb, 0, buf, len); if (status < 0) return(status); return($niosb[0]); } clsnet() /* close network, exit if failure */ { word iosb[2]; word status; dsar(); status = clswnt(NDQLUN, NETEFN, iosb, 0); dirtst(status, iosb, "clsw failed"); return(1); } init_net() /* initialize network, exit if failure */ { word status; word iosb[2]; extern word cmpast(); extern word netast(); status = alunx(NDQLUN, "NS", 0); dirtst(status, 0, "alun 1 failed"); status = alunx(LINKLUN, "NS", 0); dirtst(status, 0, "alun 2 failed"); status = opnwnt(NDQLUN, NETEFN, iosb, 0, 0, 0); dirtst(status, iosb, "opnw failed"); status = spawnt(NDQLUN, NETEFN, iosb, &cmpast, &netast); dirtst(status, iosb, "spaw failed"); return(1); } con_net(dest_node, dest_task) /* connect to remote, retrun status */ char *dest_node, *dest_task; { int status; struct c_conblk *conp; if ($netcnct) return(IE_ALN); /* check if already connected */ conp = conbuf.n_snd; /* point to connect part */ conb0(conp, dest_node, dest_task); /* fill con req block */ status = conwnt(LINKLUN, NETEFN, $niosb, 0, conp, (sizeof (struct c_conblk)), 0, 0, 0, 0); if (status < 0) return(status); status = $niosb[0]; /* save status for return */ if ($niosb[0] == 1) { if (netfcn != -1) net_read(); /* start net read */ $netcnct = 1; } return(status); } /************************************************************** internal functions from here on **************************************************************/ static int net_read() { int status; int net_ast(); status = recnt(LINKLUN, RECEFN, $niosb, &net_ast, netbuf, sizeof netbuf); if (status != 1) { printf("/%6.6s/ recnt dsw err %o\n", conbuf.n_dde, status); return(-1); } return(1); } static int net_ast() { astset(); /* set up the ast parameter*/ if ($niosb[0] == IS_SUC) { /* if it worked, process it */ if (netfcn != -1) (*netfcn)(netbuf, $niosb[1]); net_read(); astx(1); } else if ($niosb[0] == IE_ABO) { /* aborted receive not fatal */ astx(1); } fprintf(stderr, "rcvnet err %o %o\n", $niosb[0], $niosb[1]); astx(1); } static word cmpast() { byte *piosb; /* pointer to iosb */ astset(); piosb = gtdp(0); /* point to iosb */ dirtst(1, piosb, "spaw failed"); piosb += 2; /* move 1 word */ if (*piosb < 0) get_msg(*piosb); astx(1); } static word netast() { astset(); get_msg(1); astx(0); } static int get_msg(msgcnt) int msgcnt; { char *cp; word iosb[2]; byte *bp; word status; cp = &conbuf; bp = iosb; while (msgcnt-- > 0) { status = gndwnt(NDQLUN, NETEFN, iosb, 0, &conbuf, (sizeof conbuf)); if (status == IE_NDA) return(1); /* no data waiting */ dirtst(status, iosb, "gndw failed"); switch (*(bp+1)) { case NT_CON: { status = accwnt(LINKLUN, NETEFN, iosb, 0, &conbuf, (sizeof conbuf), 0, 0); dirtst(status, iosb, "accw failed"); $netcnct= 1; if (netmsg != -1) (*netmsg)(NT_CON, cp); if (netfcn != -1) net_read(); /* start net read */ break; } case NT_INT: { *(cp + iosb[1]) = 0; /* make a string */ if (netmsg != -1) (*netmsg)(NT_INT, cp); break; } case NT_DSC: { if (netmsg != -1) (*netmsg)(NT_DSC, -1); $netcnct= 0; break; } case NT_ABT: { if (netmsg != -1) (*netmsg)(NT_ABT, -1); $netcnct= 0; break; } case NT_ABO: { if (netmsg != -1) (*netmsg)(NT_ABO, -1); $netcnct = 0; break; } default: { fprintf(stderr, "unexpected msg %d %d\n", status, iosb[0]); $netcnct = 0; } } } return(1); } static int r_conast() { astset(); $netcnct = 1; astx(1); } static int conb0(conp, node, task) struct c_conblk *conp; char *node, *task; { int i, len; zero(conp, (sizeof (struct c_conblk))); fill(conp->n_rnd, 040, 6); /* put spaces in node name */ fill(conp->n_rde, 040, 16); /* and destination task */ len = strlen(node); copy(conp->n_rnd, node, (len > 6 ? 6 : len)); for (i = 0; i < 6; i++) conp->n_rnd[i] = toupper(conp->n_rnd[i]); conp->n_rdec = ((len = strlen(task)) > 16) ? 16 : len; copy(conp->n_rde, task, conp->n_rdec); for (i = 0; i < 16; i++) conp->n_rde[i] = toupper(conp->n_rde[i]); conp->n_rfm = 1; /* type 1 descriptor */ conp->n_rot = 0; /* object type 0 */ return(1); } static int dirtst(dstat, pio, msg) int dstat; char *pio, *msg; { if ((dstat >= 0) && ((pio == 0) || (*pio == 1))) return(0); fatal(msg, dstat, pio); } static int fatal(msg, dsw, fiosb) char *msg; word dsw, fiosb[2]; { printf("FATAL:%s: \ndsw:%o, fiosb:%o:%o\n", msg, dsw, fiosb[0], fiosb[1]); exit(4); }