xdr_rec.c revision 8870
11902Swollman/* 21902Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 31902Swollman * unrestricted use provided that this legend is included on all tape 41902Swollman * media and as a part of the software program in whole or part. Users 51902Swollman * may copy or modify Sun RPC without charge, but are not authorized 61902Swollman * to license or distribute it to anyone else except as part of a product or 71902Swollman * program developed by the user. 88870Srgrimes * 91902Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 101902Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 111902Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 128870Srgrimes * 131902Swollman * Sun RPC is provided with no support and without any obligation on the 141902Swollman * part of Sun Microsystems, Inc. to assist in its use, correction, 151902Swollman * modification or enhancement. 168870Srgrimes * 171902Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 181902Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 191902Swollman * OR ANY PART THEREOF. 208870Srgrimes * 211902Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 221902Swollman * or profits or other special, indirect and consequential damages, even if 231902Swollman * Sun has been advised of the possibility of such damages. 248870Srgrimes * 251902Swollman * Sun Microsystems, Inc. 261902Swollman * 2550 Garcia Avenue 271902Swollman * Mountain View, California 94043 281902Swollman */ 298870Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 301902Swollman/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ 311902Swollman/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/ 328870Srgrimesstatic char *rcsid = "$Id: xdr_rec.c,v 1.2 1994/08/07 22:21:14 wollman Exp $"; 331902Swollman#endif 341902Swollman 351902Swollman/* 361902Swollman * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" 371902Swollman * layer above tcp (for rpc's use). 381902Swollman * 391902Swollman * Copyright (C) 1984, Sun Microsystems, Inc. 401902Swollman * 411902Swollman * These routines interface XDRSTREAMS to a tcp/ip connection. 421902Swollman * There is a record marking layer between the xdr stream 431902Swollman * and the tcp transport level. A record is composed on one or more 441902Swollman * record fragments. A record fragment is a thirty-two bit header followed 451902Swollman * by n bytes of data, where n is contained in the header. The header 461902Swollman * is represented as a htonl(u_long). Thegh order bit encodes 471902Swollman * whether or not the fragment is the last fragment of the record 488870Srgrimes * (1 => fragment is last, 0 => more fragments to follow. 491902Swollman * The other 31 bits encode the byte length of the fragment. 501902Swollman */ 511902Swollman 521902Swollman#include <stdio.h> 531902Swollman#include <stdlib.h> 541902Swollman#include <rpc/types.h> 551902Swollman#include <rpc/xdr.h> 561902Swollman#include <netinet/in.h> 571902Swollman 581902Swollmanstatic u_int fix_buf_size(); 591902Swollmanstatic bool_t flush_out(); 601902Swollmanstatic bool_t get_input_bytes(); 611902Swollmanstatic bool_t set_input_fragment(); 621902Swollmanstatic bool_t skip_input_bytes(); 631902Swollman 641902Swollmanstatic bool_t xdrrec_getlong(); 651902Swollmanstatic bool_t xdrrec_putlong(); 661902Swollmanstatic bool_t xdrrec_getbytes(); 671902Swollmanstatic bool_t xdrrec_putbytes(); 681902Swollmanstatic u_int xdrrec_getpos(); 691902Swollmanstatic bool_t xdrrec_setpos(); 701902Swollmanstatic long * xdrrec_inline(); 711902Swollmanstatic void xdrrec_destroy(); 721902Swollman 731902Swollmanstatic struct xdr_ops xdrrec_ops = { 741902Swollman xdrrec_getlong, 751902Swollman xdrrec_putlong, 761902Swollman xdrrec_getbytes, 771902Swollman xdrrec_putbytes, 781902Swollman xdrrec_getpos, 791902Swollman xdrrec_setpos, 801902Swollman xdrrec_inline, 811902Swollman xdrrec_destroy 821902Swollman}; 831902Swollman 841902Swollman/* 851902Swollman * A record is composed of one or more record fragments. 861902Swollman * A record fragment is a two-byte header followed by zero to 871902Swollman * 2**32-1 bytes. The header is treated as a long unsigned and is 881902Swollman * encode/decoded to the network via htonl/ntohl. The low order 31 bits 891902Swollman * are a byte count of the fragment. The highest order bit is a boolean: 901902Swollman * 1 => this fragment is the last fragment of the record, 911902Swollman * 0 => this fragment is followed by more fragment(s). 921902Swollman * 931902Swollman * The fragment/record machinery is not general; it is constructed to 941902Swollman * meet the needs of xdr and rpc based on tcp. 951902Swollman */ 961902Swollman 971902Swollman#define LAST_FRAG ((u_long)(1 << 31)) 981902Swollman 991902Swollmantypedef struct rec_strm { 1001902Swollman caddr_t tcp_handle; 1011902Swollman caddr_t the_buffer; 1021902Swollman /* 1031902Swollman * out-goung bits 1041902Swollman */ 1051902Swollman int (*writeit)(); 1061902Swollman caddr_t out_base; /* output buffer (points to frag header) */ 1071902Swollman caddr_t out_finger; /* next output position */ 1081902Swollman caddr_t out_boundry; /* data cannot up to this address */ 1091902Swollman u_long *frag_header; /* beginning of curren fragment */ 1101902Swollman bool_t frag_sent; /* true if buffer sent in middle of record */ 1111902Swollman /* 1121902Swollman * in-coming bits 1131902Swollman */ 1141902Swollman int (*readit)(); 1151902Swollman u_long in_size; /* fixed size of the input buffer */ 1161902Swollman caddr_t in_base; 1171902Swollman caddr_t in_finger; /* location of next byte to be had */ 1181902Swollman caddr_t in_boundry; /* can read up to this location */ 1191902Swollman long fbtbc; /* fragment bytes to be consumed */ 1201902Swollman bool_t last_frag; 1211902Swollman u_int sendsize; 1221902Swollman u_int recvsize; 1231902Swollman} RECSTREAM; 1241902Swollman 1251902Swollman 1261902Swollman/* 1271902Swollman * Create an xdr handle for xdrrec 1281902Swollman * xdrrec_create fills in xdrs. Sendsize and recvsize are 1291902Swollman * send and recv buffer sizes (0 => use default). 1301902Swollman * tcp_handle is an opaque handle that is passed as the first parameter to 1311902Swollman * the procedures readit and writeit. Readit and writeit are read and 1321902Swollman * write respectively. They are like the system 1331902Swollman * calls expect that they take an opaque handle rather than an fd. 1341902Swollman */ 1351902Swollmanvoid 1361902Swollmanxdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) 1371902Swollman register XDR *xdrs; 1381902Swollman register u_int sendsize; 1391902Swollman register u_int recvsize; 1401902Swollman caddr_t tcp_handle; 1411902Swollman int (*readit)(); /* like read, but pass it a tcp_handle, not sock */ 1421902Swollman int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */ 1431902Swollman{ 1441902Swollman register RECSTREAM *rstrm = 1451902Swollman (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); 1461902Swollman 1471902Swollman if (rstrm == NULL) { 1481902Swollman (void)fprintf(stderr, "xdrrec_create: out of memory\n"); 1498870Srgrimes /* 1508870Srgrimes * This is bad. Should rework xdrrec_create to 1511902Swollman * return a handle, and in this case return NULL 1521902Swollman */ 1531902Swollman return; 1541902Swollman } 1551902Swollman /* 1561902Swollman * adjust sizes and allocate buffer quad byte aligned 1571902Swollman */ 1581902Swollman rstrm->sendsize = sendsize = fix_buf_size(sendsize); 1591902Swollman rstrm->recvsize = recvsize = fix_buf_size(recvsize); 1601902Swollman rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); 1611902Swollman if (rstrm->the_buffer == NULL) { 1621902Swollman (void)fprintf(stderr, "xdrrec_create: out of memory\n"); 1631902Swollman return; 1641902Swollman } 1651902Swollman for (rstrm->out_base = rstrm->the_buffer; 1661902Swollman (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0; 1671902Swollman rstrm->out_base++); 1681902Swollman rstrm->in_base = rstrm->out_base + sendsize; 1691902Swollman /* 1701902Swollman * now the rest ... 1711902Swollman */ 1721902Swollman xdrs->x_ops = &xdrrec_ops; 1731902Swollman xdrs->x_private = (caddr_t)rstrm; 1741902Swollman rstrm->tcp_handle = tcp_handle; 1751902Swollman rstrm->readit = readit; 1761902Swollman rstrm->writeit = writeit; 1771902Swollman rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; 1781902Swollman rstrm->frag_header = (u_long *)rstrm->out_base; 1791902Swollman rstrm->out_finger += sizeof(u_long); 1801902Swollman rstrm->out_boundry += sendsize; 1811902Swollman rstrm->frag_sent = FALSE; 1821902Swollman rstrm->in_size = recvsize; 1831902Swollman rstrm->in_boundry = rstrm->in_base; 1841902Swollman rstrm->in_finger = (rstrm->in_boundry += recvsize); 1851902Swollman rstrm->fbtbc = 0; 1861902Swollman rstrm->last_frag = TRUE; 1871902Swollman} 1881902Swollman 1891902Swollman 1901902Swollman/* 1911902Swollman * The reoutines defined below are the xdr ops which will go into the 1921902Swollman * xdr handle filled in by xdrrec_create. 1931902Swollman */ 1941902Swollman 1951902Swollmanstatic bool_t 1961902Swollmanxdrrec_getlong(xdrs, lp) 1971902Swollman XDR *xdrs; 1981902Swollman long *lp; 1991902Swollman{ 2001902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2011902Swollman register long *buflp = (long *)(rstrm->in_finger); 2021902Swollman long mylong; 2031902Swollman 2041902Swollman /* first try the inline, fast case */ 2051902Swollman if ((rstrm->fbtbc >= sizeof(long)) && 2061902Swollman (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) { 2071902Swollman *lp = (long)ntohl((u_long)(*buflp)); 2081902Swollman rstrm->fbtbc -= sizeof(long); 2091902Swollman rstrm->in_finger += sizeof(long); 2101902Swollman } else { 2111902Swollman if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long))) 2121902Swollman return (FALSE); 2131902Swollman *lp = (long)ntohl((u_long)mylong); 2141902Swollman } 2151902Swollman return (TRUE); 2161902Swollman} 2171902Swollman 2181902Swollmanstatic bool_t 2191902Swollmanxdrrec_putlong(xdrs, lp) 2201902Swollman XDR *xdrs; 2211902Swollman long *lp; 2221902Swollman{ 2231902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2241902Swollman register long *dest_lp = ((long *)(rstrm->out_finger)); 2251902Swollman 2261902Swollman if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) { 2271902Swollman /* 2281902Swollman * this case should almost never happen so the code is 2291902Swollman * inefficient 2301902Swollman */ 2311902Swollman rstrm->out_finger -= sizeof(long); 2321902Swollman rstrm->frag_sent = TRUE; 2331902Swollman if (! flush_out(rstrm, FALSE)) 2341902Swollman return (FALSE); 2351902Swollman dest_lp = ((long *)(rstrm->out_finger)); 2361902Swollman rstrm->out_finger += sizeof(long); 2371902Swollman } 2381902Swollman *dest_lp = (long)htonl((u_long)(*lp)); 2391902Swollman return (TRUE); 2401902Swollman} 2411902Swollman 2421902Swollmanstatic bool_t /* must manage buffers, fragments, and records */ 2431902Swollmanxdrrec_getbytes(xdrs, addr, len) 2441902Swollman XDR *xdrs; 2451902Swollman register caddr_t addr; 2461902Swollman register u_int len; 2471902Swollman{ 2481902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2491902Swollman register int current; 2501902Swollman 2511902Swollman while (len > 0) { 2521902Swollman current = rstrm->fbtbc; 2531902Swollman if (current == 0) { 2541902Swollman if (rstrm->last_frag) 2551902Swollman return (FALSE); 2561902Swollman if (! set_input_fragment(rstrm)) 2571902Swollman return (FALSE); 2581902Swollman continue; 2591902Swollman } 2601902Swollman current = (len < current) ? len : current; 2611902Swollman if (! get_input_bytes(rstrm, addr, current)) 2621902Swollman return (FALSE); 2638870Srgrimes addr += current; 2641902Swollman rstrm->fbtbc -= current; 2651902Swollman len -= current; 2661902Swollman } 2671902Swollman return (TRUE); 2681902Swollman} 2691902Swollman 2701902Swollmanstatic bool_t 2711902Swollmanxdrrec_putbytes(xdrs, addr, len) 2721902Swollman XDR *xdrs; 2731902Swollman register caddr_t addr; 2741902Swollman register u_int len; 2751902Swollman{ 2761902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 2771902Swollman register int current; 2781902Swollman 2791902Swollman while (len > 0) { 2801902Swollman current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger; 2811902Swollman current = (len < current) ? len : current; 2821902Swollman bcopy(addr, rstrm->out_finger, current); 2831902Swollman rstrm->out_finger += current; 2841902Swollman addr += current; 2851902Swollman len -= current; 2861902Swollman if (rstrm->out_finger == rstrm->out_boundry) { 2871902Swollman rstrm->frag_sent = TRUE; 2881902Swollman if (! flush_out(rstrm, FALSE)) 2891902Swollman return (FALSE); 2901902Swollman } 2911902Swollman } 2921902Swollman return (TRUE); 2931902Swollman} 2941902Swollman 2951902Swollmanstatic u_int 2961902Swollmanxdrrec_getpos(xdrs) 2971902Swollman register XDR *xdrs; 2981902Swollman{ 2991902Swollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3001902Swollman register long pos; 3011902Swollman 3021902Swollman pos = lseek((int)rstrm->tcp_handle, (long) 0, 1); 3031902Swollman if (pos != -1) 3041902Swollman switch (xdrs->x_op) { 3051902Swollman 3061902Swollman case XDR_ENCODE: 3071902Swollman pos += rstrm->out_finger - rstrm->out_base; 3081902Swollman break; 3091902Swollman 3101902Swollman case XDR_DECODE: 3111902Swollman pos -= rstrm->in_boundry - rstrm->in_finger; 3121902Swollman break; 3131902Swollman 3141902Swollman default: 3151902Swollman pos = (u_int) -1; 3161902Swollman break; 3171902Swollman } 3181902Swollman return ((u_int) pos); 3191902Swollman} 3201902Swollman 3211902Swollmanstatic bool_t 3221902Swollmanxdrrec_setpos(xdrs, pos) 3231902Swollman register XDR *xdrs; 3241902Swollman u_int pos; 3251902Swollman{ 3261902Swollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3271902Swollman u_int currpos = xdrrec_getpos(xdrs); 3281902Swollman int delta = currpos - pos; 3291902Swollman caddr_t newpos; 3301902Swollman 3311902Swollman if ((int)currpos != -1) 3321902Swollman switch (xdrs->x_op) { 3331902Swollman 3341902Swollman case XDR_ENCODE: 3351902Swollman newpos = rstrm->out_finger - delta; 3361902Swollman if ((newpos > (caddr_t)(rstrm->frag_header)) && 3371902Swollman (newpos < rstrm->out_boundry)) { 3381902Swollman rstrm->out_finger = newpos; 3391902Swollman return (TRUE); 3401902Swollman } 3411902Swollman break; 3421902Swollman 3431902Swollman case XDR_DECODE: 3441902Swollman newpos = rstrm->in_finger - delta; 3451902Swollman if ((delta < (int)(rstrm->fbtbc)) && 3461902Swollman (newpos <= rstrm->in_boundry) && 3471902Swollman (newpos >= rstrm->in_base)) { 3481902Swollman rstrm->in_finger = newpos; 3491902Swollman rstrm->fbtbc -= delta; 3501902Swollman return (TRUE); 3511902Swollman } 3521902Swollman break; 3531902Swollman } 3541902Swollman return (FALSE); 3551902Swollman} 3561902Swollman 3571902Swollmanstatic long * 3581902Swollmanxdrrec_inline(xdrs, len) 3591902Swollman register XDR *xdrs; 3601902Swollman int len; 3611902Swollman{ 3621902Swollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3631902Swollman long * buf = NULL; 3641902Swollman 3651902Swollman switch (xdrs->x_op) { 3661902Swollman 3671902Swollman case XDR_ENCODE: 3681902Swollman if ((rstrm->out_finger + len) <= rstrm->out_boundry) { 3691902Swollman buf = (long *) rstrm->out_finger; 3701902Swollman rstrm->out_finger += len; 3711902Swollman } 3721902Swollman break; 3731902Swollman 3741902Swollman case XDR_DECODE: 3751902Swollman if ((len <= rstrm->fbtbc) && 3761902Swollman ((rstrm->in_finger + len) <= rstrm->in_boundry)) { 3771902Swollman buf = (long *) rstrm->in_finger; 3781902Swollman rstrm->fbtbc -= len; 3791902Swollman rstrm->in_finger += len; 3801902Swollman } 3811902Swollman break; 3821902Swollman } 3831902Swollman return (buf); 3841902Swollman} 3851902Swollman 3861902Swollmanstatic void 3871902Swollmanxdrrec_destroy(xdrs) 3881902Swollman register XDR *xdrs; 3891902Swollman{ 3901902Swollman register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 3911902Swollman 3921902Swollman mem_free(rstrm->the_buffer, 3931902Swollman rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); 3941902Swollman mem_free((caddr_t)rstrm, sizeof(RECSTREAM)); 3951902Swollman} 3961902Swollman 3971902Swollman 3981902Swollman/* 3991902Swollman * Exported routines to manage xdr records 4001902Swollman */ 4011902Swollman 4021902Swollman/* 4031902Swollman * Before reading (deserializing from the stream, one should always call 4041902Swollman * this procedure to guarantee proper record alignment. 4051902Swollman */ 4061902Swollmanbool_t 4071902Swollmanxdrrec_skiprecord(xdrs) 4081902Swollman XDR *xdrs; 4091902Swollman{ 4101902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 4111902Swollman 4121902Swollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 4131902Swollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 4141902Swollman return (FALSE); 4151902Swollman rstrm->fbtbc = 0; 4161902Swollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 4171902Swollman return (FALSE); 4181902Swollman } 4191902Swollman rstrm->last_frag = FALSE; 4201902Swollman return (TRUE); 4211902Swollman} 4221902Swollman 4231902Swollman/* 4241902Swollman * Look ahead fuction. 4258870Srgrimes * Returns TRUE iff there is no more input in the buffer 4261902Swollman * after consuming the rest of the current record. 4271902Swollman */ 4281902Swollmanbool_t 4291902Swollmanxdrrec_eof(xdrs) 4301902Swollman XDR *xdrs; 4311902Swollman{ 4321902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 4331902Swollman 4341902Swollman while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 4351902Swollman if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 4361902Swollman return (TRUE); 4371902Swollman rstrm->fbtbc = 0; 4381902Swollman if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 4391902Swollman return (TRUE); 4401902Swollman } 4411902Swollman if (rstrm->in_finger == rstrm->in_boundry) 4421902Swollman return (TRUE); 4431902Swollman return (FALSE); 4441902Swollman} 4451902Swollman 4461902Swollman/* 4471902Swollman * The client must tell the package when an end-of-record has occurred. 4481902Swollman * The second paraemters tells whether the record should be flushed to the 4491902Swollman * (output) tcp stream. (This let's the package support batched or 4501902Swollman * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. 4511902Swollman */ 4521902Swollmanbool_t 4531902Swollmanxdrrec_endofrecord(xdrs, sendnow) 4541902Swollman XDR *xdrs; 4551902Swollman bool_t sendnow; 4561902Swollman{ 4571902Swollman register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 4581902Swollman register u_long len; /* fragment length */ 4591902Swollman 4601902Swollman if (sendnow || rstrm->frag_sent || 4611902Swollman ((u_long)rstrm->out_finger + sizeof(u_long) >= 4621902Swollman (u_long)rstrm->out_boundry)) { 4631902Swollman rstrm->frag_sent = FALSE; 4641902Swollman return (flush_out(rstrm, TRUE)); 4651902Swollman } 4661902Swollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - 4671902Swollman sizeof(u_long); 4681902Swollman *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG); 4691902Swollman rstrm->frag_header = (u_long *)rstrm->out_finger; 4701902Swollman rstrm->out_finger += sizeof(u_long); 4711902Swollman return (TRUE); 4721902Swollman} 4731902Swollman 4741902Swollman 4751902Swollman/* 4761902Swollman * Internal useful routines 4771902Swollman */ 4781902Swollmanstatic bool_t 4791902Swollmanflush_out(rstrm, eor) 4801902Swollman register RECSTREAM *rstrm; 4811902Swollman bool_t eor; 4821902Swollman{ 4831902Swollman register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; 4848870Srgrimes register u_long len = (u_long)(rstrm->out_finger) - 4851902Swollman (u_long)(rstrm->frag_header) - sizeof(u_long); 4861902Swollman 4871902Swollman *(rstrm->frag_header) = htonl(len | eormask); 4881902Swollman len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base); 4891902Swollman if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) 4901902Swollman != (int)len) 4911902Swollman return (FALSE); 4921902Swollman rstrm->frag_header = (u_long *)rstrm->out_base; 4931902Swollman rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long); 4941902Swollman return (TRUE); 4951902Swollman} 4961902Swollman 4971902Swollmanstatic bool_t /* knows nothing about records! Only about input buffers */ 4981902Swollmanfill_input_buf(rstrm) 4991902Swollman register RECSTREAM *rstrm; 5001902Swollman{ 5011902Swollman register caddr_t where; 5021902Swollman u_int i; 5031902Swollman register int len; 5041902Swollman 5051902Swollman where = rstrm->in_base; 5061902Swollman i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT; 5071902Swollman where += i; 5081902Swollman len = rstrm->in_size - i; 5091902Swollman if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) 5101902Swollman return (FALSE); 5111902Swollman rstrm->in_finger = where; 5121902Swollman where += len; 5131902Swollman rstrm->in_boundry = where; 5141902Swollman return (TRUE); 5151902Swollman} 5161902Swollman 5171902Swollmanstatic bool_t /* knows nothing about records! Only about input buffers */ 5181902Swollmanget_input_bytes(rstrm, addr, len) 5191902Swollman register RECSTREAM *rstrm; 5201902Swollman register caddr_t addr; 5211902Swollman register int len; 5221902Swollman{ 5231902Swollman register int current; 5241902Swollman 5251902Swollman while (len > 0) { 5261902Swollman current = (int)rstrm->in_boundry - (int)rstrm->in_finger; 5271902Swollman if (current == 0) { 5281902Swollman if (! fill_input_buf(rstrm)) 5291902Swollman return (FALSE); 5301902Swollman continue; 5311902Swollman } 5321902Swollman current = (len < current) ? len : current; 5331902Swollman bcopy(rstrm->in_finger, addr, current); 5341902Swollman rstrm->in_finger += current; 5351902Swollman addr += current; 5361902Swollman len -= current; 5371902Swollman } 5381902Swollman return (TRUE); 5391902Swollman} 5401902Swollman 5411902Swollmanstatic bool_t /* next two bytes of the input stream are treated as a header */ 5421902Swollmanset_input_fragment(rstrm) 5431902Swollman register RECSTREAM *rstrm; 5441902Swollman{ 5451902Swollman u_long header; 5461902Swollman 5471902Swollman if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) 5481902Swollman return (FALSE); 5491902Swollman header = (long)ntohl(header); 5501902Swollman rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; 5511902Swollman rstrm->fbtbc = header & (~LAST_FRAG); 5521902Swollman return (TRUE); 5531902Swollman} 5541902Swollman 5551902Swollmanstatic bool_t /* consumes input bytes; knows nothing about records! */ 5561902Swollmanskip_input_bytes(rstrm, cnt) 5571902Swollman register RECSTREAM *rstrm; 5581902Swollman long cnt; 5591902Swollman{ 5601902Swollman register int current; 5611902Swollman 5621902Swollman while (cnt > 0) { 5631902Swollman current = (int)rstrm->in_boundry - (int)rstrm->in_finger; 5641902Swollman if (current == 0) { 5651902Swollman if (! fill_input_buf(rstrm)) 5661902Swollman return (FALSE); 5671902Swollman continue; 5681902Swollman } 5691902Swollman current = (cnt < current) ? cnt : current; 5701902Swollman rstrm->in_finger += current; 5711902Swollman cnt -= current; 5721902Swollman } 5731902Swollman return (TRUE); 5741902Swollman} 5751902Swollman 5761902Swollmanstatic u_int 5771902Swollmanfix_buf_size(s) 5781902Swollman register u_int s; 5791902Swollman{ 5801902Swollman 5811902Swollman if (s < 100) 5821902Swollman s = 4000; 5831902Swollman return (RNDUP(s)); 5841902Swollman} 585