📄 ckcfn3.c
字号:
/* C K C F N 3 -- Packet buffer management for C-Kermit *//* (plus assorted functions tacked on at the end) *//* Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use this software as long as it is not sold for profit. This copyright notice must be retained. This software may not be included in commercial products without written permission of Columbia University.*/#include "ckcdeb.h"#include "ckcasc.h"#include "ckcker.h"#include "ckcxla.h"extern int unkcs, wmax, wcur, discard, bctu, bctl, local, fdispla;extern CHAR *data;extern char filnam[];#ifndef NOFRILLSextern int rprintf, rmailf; /* REMOTE MAIL, PRINT */extern char optbuf[]; /* Options buffer for mail, print */#endif /* NOFRILLS */extern int wslots;extern int fblksiz, frecl, forg, frecfm, fncact, fcctrl, lf_opts;#ifdef DYNAMIC extern CHAR *srvcmd;#else extern CHAR srvcmd[];#endifextern int binary, spsiz;extern int pktnum, cxseen, czseen, bsave, bsavef, nfils, stdinf;extern int memstr, stdouf, keep, sndsrc, hcflg;extern int server, en_cwd;extern int atenci, atenco, atdati, atdato, atleni, atleno, atblki, atblko, attypi, attypo, atsidi, atsido, atsysi, atsyso, atdisi, atdiso; #ifdef datageneralextern int quiet;#endif /* datageneral */extern long fsize, filcnt, ffc, tfc;#ifndef NOCSETSextern int tcharset, fcharset;extern int ntcsets;extern struct csinfo tcsinfo[], fcsinfo[];/* Pointers to translation functions */#ifdef CK_ANSICextern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */extern CHAR (*rx)(CHAR); /* Pointer to input character translation function */extern CHAR (*sx)(CHAR); /* Pointer to output character translation function */#elseextern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */extern CHAR (*rx)(); /* Pointer to input character translation function */extern CHAR (*sx)(); /* Pointer to output character translation function */#endif /* CK_ANSIC */#endif /* NOCSETS *//* Variables global to Kermit that are defined in this module */int winlo; /* packet number at low window edge */int sbufnum; /* number of free buffers */int dum001 = 1234; /* protection... */int sbufuse[MAXWS]; /* buffer in-use flag */int dum003 = 1111;int rbufnum; /* number of free buffers */int dum002 = 4321; /* more protection */int rbufuse[MAXWS]; /* buffer in-use flag */int sseqtbl[64]; /* sequence # to buffer # table */int rseqtbl[64]; /* sequence # to buffer # table */int sacktbl[64]; /* sequence # ack table */#ifdef DYNAMICstruct pktinfo *s_pkt = NULL; /* array of pktinfo structures */struct pktinfo *r_pkt = NULL; /* array of pktinfo structures */#elsestruct pktinfo s_pkt[MAXWS]; /* array of pktinfo structures */struct pktinfo r_pkt[MAXWS]; /* array of pktinfo structures */#endif /* DYNAMIC */#ifdef DEBUGchar xbuf[200]; /* For debug logging */#endif /* DEBUG */#ifdef DYNAMICCHAR *bigsbuf = NULL, *bigrbuf = NULL;#elsechar bigsbt[8]; /* Protection (shouldn't need this). */ /* BUT DON'T REMOVE IT! */CHAR bigsbuf[SBSIZ + 5]; /* Send-packet buffer area */char bigrbt[8]; /* Safety padding */CHAR bigrbuf[RBSIZ + 5]; /* Receive-packet area */#endifint bigsbsiz = SBSIZ; /* Sizes of big send & rcv buffers. */int bigrbsiz = RBSIZ;/* FUNCTIONS *//* For sanity, use "i" for buffer slots, "n" for packet numbers. *//* I N I B U F S *//* Allocates the big send and receive buffers. Call with size for big send buffer (s) and receive buffer (r). These sizes can be different. Attempts to allocate buffers of the requested size, but if it can't, it will allocate smaller ones. Sets global variables bigsbsiz and bigrbsiz to the actual sizes, and bigsbuf and bigrbuf pointing to the actual buffers. Designed to be called more than once. Returns 0 on success, -1 on failure.*/CHAR *bigbufp = NULL;intinibufs(s,r) int s, r; {#ifdef DYNAMIC int size, x; long z; if (s < 80 || r < 80) return(-1); /* Validate arguments. */ if (!s_pkt) { /* Allocate packet info structures */ if (!(s_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS))) fatal("ini_pkts: no memory for s_pkt"); } for (x = 0; x < MAXWS; x++) s_pkt[x].pk_adr = NULL; /* Initialize addresses */ if (!r_pkt) { if (!(r_pkt = (struct pktinfo *) malloc(sizeof(struct pktinfo)*MAXWS))) fatal("ini_pkts: no memory for s_pkt"); } for (x = 0; x < MAXWS; x++) r_pkt[x].pk_adr = NULL; /* Initialize addresses */ if (!srvcmd) { /* Allocate srvcmd buffer */ srvcmd = (CHAR *) malloc(r + 100); if (!srvcmd) return(-1); } if (bigbufp) { /* Free previous buffers, if any. */ free(bigbufp); bigbufp = NULL; } size = s + r + 40; /* Combined requested size + padding */ /* Try to get the space. If malloc fails, try to get a little less. */ /* (Obviously, this algorithm can be refined.) */ while (!(bigbufp = (CHAR *) malloc(size))) { size = (size * 3) / 2; /* Failed, cut size by 1/3. */ if (size < 200) /* Try again until too small. */ return(-1); } debug(F101,"inibufs size","",size); /* OK, we got some space. *//* Now divide the allocated space between the send and receive buffers in the requested proportion. The natural formula would be (s / (s + r)) * size (for the send buffer), but that doesn't work with integer arithmetic and we can't use floating point because some machines don't have it. This can be rearranged as (s * size) / (s + r). But (s * size) can be VERY large, too large for 32 bits. So let's do it this way. This arithmetic works for buffer sizes up to about 5,000,000.*/#define FACTOR 20L z = ( (long) s * FACTOR ) / ( (long) s + (long) r ); x = ( z * ( (long) size / FACTOR ) ); if (x < 0) return(-1); /* Catch overflow */ bigsbsiz = x - 5; /* Size of send buffer */ bigsbuf = bigbufp; /* Address of send buffer */ debug(F101,"inibufs bigsbsiz","",bigsbsiz); bigrbsiz = size - x - 5; /* Size of receive buffer */ bigrbuf = bigbufp + x; /* Addresss of receive buffer */ debug(F101,"inibufs bigrbsiz","",bigrbsiz); return(0); /* Success */#else /* No dynamic allocation */ bigsbsiz = SBSIZ; /* Just use the symbols */ bigrbsiz = RBSIZ; /* ... */ return(0); /* Success. */#endif /* DYNAMIC */}/* M A K E B U F -- Makes and clears a new buffers. *//* Call with: *//* slots: number of buffer slots to make, 1 to 31 *//* bufsiz: size of the big buffer *//* buf: address of the big buffer *//* xx: pointer to array of pktinfo structures for these buffers *//* Subdivides the big buffer into "slots" buffers. *//* Returns: *//* -1 if too many or too few slots requested, *//* -2 if slots would be too small. *//* n (positive) on success = size of one buffer. *//* with pktinfo structure initialized for this set of buffers. */intmakebuf(slots,bufsiz,buf,xx)/* makebuf */ int slots, bufsiz; CHAR buf[]; struct pktinfo *xx; { CHAR *a; int i, size; debug(F101,"makebuf","",slots); debug(F101,"makebuf bufsiz","",bufsiz); debug(F101,"makebuf MAXWS","",MAXWS); if (slots > MAXWS || slots < 1) return(-1); if (bufsiz < slots * 10 ) return(-2); size = bufsiz / slots; /* Divide up the big buffer. */ a = buf; /* Address of first piece. */ for (i = 0; i < slots; i++) { struct pktinfo *x = &xx[i]; x->bf_adr = a; /* Address of this buffer */ x->bf_len = size; /* Length of this buffer */ x->pk_len = 0; /* Length of data field */ x->pk_typ = ' '; /* packet type */ x->pk_seq = -1; /* packet sequence number */ x->pk_flg = 0; /* ack'd bit */ x->pk_rtr = 0; /* retransmissions */ *a = '\0'; /* Clear the buffer */ a += size; /* Position to next buffer slot */ } return(size);}/* M A K S B U F -- Makes the send-packet buffer */intmksbuf(slots) int slots; { int i, x; sbufnum = 0; if ((x = makebuf(slots,bigsbsiz,bigsbuf,s_pkt)) < 0) { debug(F101,"mksbuf makebuf return","",x); return(x); } debug(F101,"mksbuf makebuf return","",x); for (i = 0; i < 64; i++) { /* Initialize sequence-number- */ sseqtbl[i] = -1; /* to-buffer-number table. */ sacktbl[i] = 0; } for (i = 0; i < MAXWS; i++) sbufuse[i] = 0; /* Mark each buffer as free */ sbufnum = slots; return(x);}/* M A K R B U F -- Makes the receive-packet buffer */intmkrbuf(slots) int slots; { int i, x; rbufnum = 0; if ((x = makebuf(slots,bigrbsiz,bigrbuf,r_pkt)) < 0) { debug(F101,"mkrbuf makebuf return","",x); return(x); } debug(F101,"mkrbuf makebuf return","",x); for (i = 0; i < 64; i++) { /* Initialize sequence-number- */ rseqtbl[i] = -1; /* to-buffer-number table. */ } for (i = 0; i < MAXWS; i++) rbufuse[i] = 0; /* Mark each buffer as free */ rbufnum = slots; return(x);}/* W I N D O W -- Resize the window to n */intwindow(n) int n; { debug(F101,"window","",n); if (n < 1 || n > 31) return(-1); if (mksbuf(n) < 0) return(-1); if (mkrbuf(n) < 0) return(-1); wslots = n;#ifdef DEBUG if (deblog) dumpsbuf(); if (deblog) dumprbuf();#endif /* DEBUG */ return(0);}/* G E T S B U F -- Allocate a send-buffer. *//* Call with packet sequence number to allocate buffer for. *//* Returns: *//* -4 if argument is invalid (negative, or greater than 63) *//* -3 if buffers were thought to be available but really weren't (bug!) *//* -2 if the number of free buffers is negative (bug!) *//* -1 if no free buffers. *//* 0 or positive, packet sequence number, with buffer allocated for it. */intgetsbuf(n) int n; { /* Allocate a send-buffer */ int i; if (n < 0 || n > 63) { debug(F101,"getsbuf bad arg","",n); return(-4); /* Bad argument */ } debug(F101,"getsbuf, packet","",n); debug(F101,"getsbuf, sbufnum","",sbufnum); if (sbufnum == 0) return(-1); /* No free buffers. */ if (sbufnum < 0) return(-2); /* Shouldn't happen. */ for (i = 0; i < wslots; i++) /* Find the first one not in use. */ if (sbufuse[i] == 0) { /* Got one? */ sbufuse[i] = 1; /* Mark it as in use. */ sbufnum--; /* One less free buffer. */ *s_pkt[i].bf_adr = '\0'; /* Zero the buffer data field */ s_pkt[i].pk_seq = n; /* Put in the sequence number */ sseqtbl[n] = i; /* Back pointer from sequence number */ sacktbl[n] = 0; /* ACK flag */ s_pkt[i].pk_len = 0; /* Data field length now zero. */ s_pkt[i].pk_typ = ' '; /* Blank the packet type too. */ s_pkt[i].pk_flg = 0; /* Zero the flags */ s_pkt[i].pk_rtr = 0; /* Zero the retransmission count */ data = s_pkt[i].bf_adr + 7; /* Set global "data" address. */ wcur = wslots - sbufnum; /* Current number of window slots */ if (i+1 > wmax) wmax = i+1; /* For statistics. */ return(n); /* Return its index. */ } sbufnum = 0; /* Didn't find one. */ return(-3); /* Shouldn't happen! */}intgetrbuf() { /* Allocate a receive buffer */ int i; debug(F101,"getrbuf rbufnum","",rbufnum); debug(F101,"getrbuf wslots","",wslots); debug(F101,"getrbuf dum002","",dum002); debug(F101,"getrbuf dum003","",dum003); if (rbufnum == 0) return(-1); /* No free buffers. */ if (rbufnum < 0) return(-2); /* Shouldn't happen. */ for (i = 0; i < wslots; i++) /* Find the first one not in use. */ if (rbufuse[i] == 0) { /* Got one? */ rbufuse[i] = 1; /* Mark it as in use. */ *r_pkt[i].bf_adr = '\0'; /* Zero the buffer data field */ rbufnum--; /* One less free buffer. */ debug(F101,"getrbuf new rbufnum","",rbufnum);#ifdef COMMENT wcur = wslots - rbufnum; /* Current number of window slots */#endif /* COMMENT */ if (i+1 > wmax) wmax = i+1; /* For statistics. */ return(i); /* Return its index. */ } debug(F101,"getrbuf foulup","",i); rbufnum = 0; /* Didn't find one. */ return(-3); /* Shouldn't happen! */}/* F R E E S B U F -- Free send-buffer for given packet sequence number *//* Returns: *//* 1 upon success *//* -1 if specified buffer does not exist */intfreesbuf(n) int n; { /* Release send-buffer for packet n. */ int i; debug(F101,"freesbuf","",n); if (n < 0 || n > 63) /* No such packet. */ return(-1); i = sseqtbl[n]; /* Get the window slot number. */ if (i > -1 && i <= wslots) { sseqtbl[n] = -1; /* If valid, remove from seqtbl */ sbufnum++; /* and count one more free buffer */ sbufuse[i] = 0; /* and mark it as free, */ } else { debug(F101," sseqtbl[n]","",sseqtbl[n]); return(-1); }/* The following is done only so dumped buffers will look right. */ if (1) { *s_pkt[i].bf_adr = '\0'; /* Zero the buffer data field */ s_pkt[i].pk_seq = -1; /* Invalidate the sequence number */ s_pkt[i].pk_len = 0; /* Data field length now zero. */ s_pkt[i].pk_typ = ' '; /* Blank the packet type too. */ s_pkt[i].pk_flg = 0; /* And zero the flag */ s_pkt[i].pk_rtr = 0; /* And the retries field. */ } return(1);}intfreerbuf(i) int i; { /* Release receive-buffer slot "i". */ int n;/* NOTE !! Currently, this function frees the indicated buffer, but *//* does NOT erase the data. The program counts on this. Will find a *//* better way later.... */ debug(F101,"freerbuf, slot","",i); if (i < 0 || i >= wslots) { /* No such slot. */ debug(F101,"freerbuf no such slot","",i); return(-1); } n = r_pkt[i].pk_seq; /* Get the packet sequence number */ debug(F101,"freerbuf, packet","",n); if (n > -1 && n < 64) /* If valid, remove from seqtbl */ rseqtbl[n] = -1; if (rbufuse[i] != 0) { /* If really allocated, */ rbufuse[i] = 0; /* mark it as free, */ rbufnum++; /* and count one more free buffer. */ debug(F101,"freerbuf, new rbufnum","",rbufnum); }/* The following is done only so dumped buffers will look right. */ if (1) { /* *r_pkt[i].bf_adr = '\0'; */ /* Zero the buffer data field */ r_pkt[i].pk_seq = -1; /* And from packet list */ r_pkt[i].pk_len = 0; /* Data field length now zero. */ r_pkt[i].pk_typ = ' '; /* Blank the packet type too. */ r_pkt[i].pk_flg = 0; /* And zero the flag */ r_pkt[i].pk_rtr = 0; /* And the retries field. */ } return(1);}/* This is like freerbuf, except it's called with a packet sequence number *//* rather than a packet buffer index. */VOIDfreerpkt(seq) int seq; { int k; debug(F101,"freerpkt seq","",seq); k = rseqtbl[seq]; debug(F101,"freerpkt k","",k); if (k > -1) { k = freerbuf(k); debug(F101,"freerpkt freerbuf","",k); }}/* C H K W I N -- Check if packet n is in window. *//* Returns: *//* 0 if it is in the current window, *//* +1 if it would have been in previous window (e.g. if ack was lost), *//* -1 if it is outside any window (protocol error), *//* -2 if either of the argument packet numbers is out of range. *//* Call with packet number to check (n), lowest packet number in window *//* (bottom), and number of slots in window (slots). */intchkwin(n,bottom,slots) int n, bottom, slots; { int top, prev; debug(F101,"chkwin packet","",n); debug(F101,"chkwin winlo","",bottom); debug(F101,"chkwin slots","",slots);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -