/* * PACKET.C */ #include "dnet.h" void BuildPacket(); #define Ascize(foo) (((foo) & 0x3F) | 0x40) ubyte RxTmp[MAXPACKET]; void BuildDataPacket(pkt, win, dbuf, actlen) PKT *pkt; ubyte win; ubyte *dbuf; uword actlen; { ubyte *ptr; ubyte *pend; ubyte range = 0; static ubyte BadCtl[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; ptr = dbuf; pend= dbuf + actlen; while (ptr < pend) { if (*ptr < 0x20 && BadCtl[*ptr]) range |= 1; if (*ptr >= 0x80) range |= 2; ++ptr; } if (Mode7 && range) { uword buflen = Expand6(dbuf, pkt->data, actlen); BuildPacket(pkt, PKCMD_WRITE6, win, pkt->data, actlen, buflen); } else { if (Mode7 || (range & 2)) { BuildPacket(pkt, PKCMD_WRITE, win, dbuf, actlen, actlen); } else { uword buflen = Compress7(dbuf, pkt->data, actlen); BuildPacket(pkt, PKCMD_WRITE7, win, pkt->data, actlen, buflen); } } } PKT * BuildRestartAckPacket(dbuf, bytes) ubyte *dbuf; ubyte bytes; { static PKT pkt; BuildPacket(&pkt, PKCMD_ACKRSTART, 0, dbuf, bytes, bytes); return(&pkt); } void BuildPacket(pkt, ctl, win, dbuf, actlen, buflen) PKT *pkt; ubyte ctl; ubyte *dbuf; uword actlen; uword buflen; { pkt->buflen = buflen; pkt->sync = SYNC; pkt->ctl = ctl | win; pkt->cchk = Ascize((pkt->sync << 1) ^ pkt->ctl); if (actlen) { uword chk = chkbuf(dbuf, buflen); ubyte dchkh = chk >> 8; ubyte dchkl = chk; pkt->lenh = Ascize(actlen >> 6); pkt->lenl = Ascize(actlen); pkt->dchkh= Ascize(dchkh); pkt->dchkl= Ascize(dchkl); if (dbuf != pkt->data) bcopy(dbuf, pkt->data, buflen); } } void WritePacket(pkt) PKT *pkt; { if (DDebug) printf("SEND-PACKET %02x %d\n", pkt->ctl, pkt->buflen); if (pkt->buflen) NetWrite(&pkt->sync, 7 + pkt->buflen); else NetWrite(&pkt->sync, 3); switch(pkt->ctl) { case PKCMD_WRITE: case PKCMD_WRITE6: case PKCMD_WRITE7: case PKCMD_RESTART: WTimeout(WTIME); } } void WriteCtlPacket(ctl, win) { static CTLPKT pkt; NetWrite(NULL, 0); BuildPacket(&pkt, ctl, win, NULL, 0, 0); WritePacket(&pkt); } void WriteNak(win) { WriteCtlPacket(PKCMD_NAK, win); } void WriteAck(win) { WriteCtlPacket(PKCMD_ACK, win); } void WriteChk(win) { WriteCtlPacket(PKCMD_CHECK, win); } void WriteRestart() { WriteCtlPacket(PKCMD_RESTART, 0); } /* * RECEIVE A PACKET */ int RecvPacket(ptr, len) ubyte *ptr; long len; { static uword ActLen; /* actual # bytes after decoding */ static uword BufLen; /* length of input data buffer */ static uword DBLen; /* # bytes already in i.d.buf */ static ubyte RState; static PKT Pkt; ubyte *dptr; short expect; if (ptr == NULL) { RState = 0; return(3); } while (len) { switch(RState) { case 0: --len; Pkt.sync = *ptr++; if (Pkt.sync == SYNC) ++RState; break; case 1: /* CTL */ --len; Pkt.ctl = *ptr++; if (Pkt.ctl < 0x20 || Pkt.ctl > 0x7F) { RState = 0; break; } ++RState; break; case 2: /* CCHK */ --len; Pkt.cchk = *ptr++; if (Ascize((SYNC<<1) ^ Pkt.ctl) != Pkt.cchk) { RState = 0; break; } switch(Pkt.ctl & PKF_MASK) { case PKCMD_ACKRSTART: case PKCMD_WRITE: case PKCMD_WRITE6: case PKCMD_WRITE7: if (DDebug) printf("Recv Header %02x\n", Pkt.ctl & PKF_MASK); ++RState; break; default: if (DDebug) printf("Recv Control %02x\n", Pkt.ctl & PKF_MASK); do_cmd(Pkt.ctl, NULL, 0); RState = 0; break; } break; case 3: /* LENH */ --len; Pkt.lenh = *ptr++; ++RState; if (Pkt.lenh < 0x20 || Pkt.lenh > 0x7F) RState = 0; break; case 4: /* LENL */ --len; Pkt.lenl = *ptr++; if (Pkt.lenl < 0x20 || Pkt.lenl > 0x7F) { RState = 0; break; } ++RState; ActLen = ((Pkt.lenh & 0x3F) << 6) | (Pkt.lenl & 0x3F); DBLen = 0; switch(Pkt.ctl & PKF_MASK) { case PKCMD_ACKRSTART: case PKCMD_WRITE: BufLen = ActLen; break; case PKCMD_WRITE6: BufLen = (ActLen * 8 + 5) / 6; break; case PKCMD_WRITE7: BufLen = (ActLen * 7 + 7) / 8; break; default: puts("BaD"); break; } if (ActLen > MAXPKT || BufLen > MAXPACKET) { if (DDebug || DDebug) printf("Packet Length Error %d %d\n", ActLen, BufLen); RState = 0; } break; case 5: /* DChkH */ --len; Pkt.dchkh = *ptr++; ++RState; if (Pkt.dchkh < 0x20 || Pkt.dchkh > 0x7F) RState = 0; break; case 6: /* DCHKL */ --len; Pkt.dchkl = *ptr++; ++RState; if (Pkt.dchkl < 0x20 || Pkt.dchkl > 0x7F) RState = 0; break; case 7: /* -DATA- */ if (DBLen + len < BufLen) { /* not enough */ bcopy(ptr, Pkt.data + DBLen, len); DBLen += len; len = 0; break; } /* * Enough data, check chk */ bcopy(ptr, Pkt.data + DBLen, BufLen - DBLen); len -= BufLen - DBLen; ptr += BufLen - DBLen; { uword chk; ubyte chkh; ubyte chkl; chk = chkbuf(Pkt.data, BufLen); chkh = Ascize(chk >> 8); chkl = Ascize(chk); if (Pkt.dchkh != chkh || Pkt.dchkl != chkl) { printf("Chksum failure %02x %02x %02x %02x\n", Pkt.dchkh, chkh, Pkt.dchkl, chkl ); RState = 0; break; } } switch(Pkt.ctl & PKF_MASK) { case PKCMD_ACKRSTART: dptr = Pkt.data; break; case PKCMD_WRITE: dptr = Pkt.data; break; case PKCMD_WRITE6: UnExpand6(Pkt.data, RxTmp, ActLen); dptr = RxTmp; break; case PKCMD_WRITE7: UnCompress7(Pkt.data, RxTmp, ActLen); dptr = RxTmp; break; default: puts("BaD2"); dptr = Pkt.data; break; } if (DDebug) printf("Recv Body %02x %ld bytes\n", Pkt.ctl, ActLen); do_cmd(Pkt.ctl, dptr, ActLen); RState = 0; break; } } { static short ExpAry[] = { 3, 2, 1, 4, 3, 2, 1, 0 }; expect = ExpAry[RState]; if (RState == 7) expect = BufLen - DBLen; } #ifdef NOTDEF if (Rto_act) { AbortIO((IOR *)&Rto); WaitIO((IOR *)&Rto); Rto_act = 0; } if (RState == 7) { Rto.tr_time.tv_secs = 8; Rto.tr_time.tv_micro= 0; SendIO((IOR *)&Rto); Rto_act = 1; } #endif do_cmd((uword)-1, NULL, 0); return((int)expect); }