xdr_rec.c revision 21062
138032Speter/* 2261363Sgshapiro * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 364562Sgshapiro * unrestricted use provided that this legend is included on all tape 438032Speter * media and as a part of the software program in whole or part. Users 538032Speter * may copy or modify Sun RPC without charge, but are not authorized 638032Speter * to license or distribute it to anyone else except as part of a product or 738032Speter * program developed by the user. 838032Speter * 938032Speter * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1038032Speter * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1138032Speter * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1238032Speter * 1338032Speter * Sun RPC is provided with no support and without any obligation on the 1464562Sgshapiro * part of Sun Microsystems, Inc. to assist in its use, correction, 1538032Speter * modification or enhancement. 1638032Speter * 1764562Sgshapiro * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 1890792Sgshapiro * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 1964562Sgshapiro * OR ANY PART THEREOF. 20132943Sgshapiro * 21132943Sgshapiro * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22132943Sgshapiro * or profits or other special, indirect and consequential damages, even if 23132943Sgshapiro * Sun has been advised of the possibility of such damages. 2464562Sgshapiro * 2538032Speter * Sun Microsystems, Inc. 2664562Sgshapiro * 2550 Garcia Avenue 2738032Speter * Mountain View, California 94043 2864562Sgshapiro */ 2938032Speter#if defined(LIBC_SCCS) && !defined(lint) 3064562Sgshapiro/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ 3164562Sgshapiro/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/ 3264562Sgshapirostatic char *rcsid = "$Id: xdr_rec.c,v 1.4 1995/10/22 14:53:56 phk Exp $"; 3364562Sgshapiro#endif 3464562Sgshapiro 3590792Sgshapiro/* 3664562Sgshapiro * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" 3764562Sgshapiro * layer above tcp (for rpc's use). 3864562Sgshapiro * 3964562Sgshapiro * Copyright (C) 1984, Sun Microsystems, Inc. 4038032Speter * 4138032Speter * These routines interface XDRSTREAMS to a tcp/ip connection. 4264562Sgshapiro * There is a record marking layer between the xdr stream 4338032Speter * and the tcp transport level. A record is composed on one or more 4464562Sgshapiro * record fragments. A record fragment is a thirty-two bit header followed 4590792Sgshapiro * by n bytes of data, where n is contained in the header. The header 4690792Sgshapiro * is represented as a htonl(u_long). Thegh order bit encodes 4790792Sgshapiro * whether or not the fragment is the last fragment of the record 4890792Sgshapiro * (1 => fragment is last, 0 => more fragments to follow. 4990792Sgshapiro * The other 31 bits encode the byte length of the fragment. 5090792Sgshapiro */ 5190792Sgshapiro 5290792Sgshapiro#include <stdio.h> 5390792Sgshapiro#include <stdlib.h> 5490792Sgshapiro#include <string.h> 55266692Sgshapiro#include <rpc/types.h> 5690792Sgshapiro#include <rpc/xdr.h> 5790792Sgshapiro#include <netinet/in.h> 5890792Sgshapiro 5964562Sgshapirostatic u_int fix_buf_size(); 6064562Sgshapirostatic bool_t flush_out(); 6190792Sgshapirostatic bool_t get_input_bytes(); 6290792Sgshapirostatic bool_t set_input_fragment(); 6390792Sgshapirostatic bool_t skip_input_bytes(); 6490792Sgshapiro 6590792Sgshapirostatic bool_t xdrrec_getlong(); 6690792Sgshapirostatic bool_t xdrrec_putlong(); 6790792Sgshapirostatic bool_t xdrrec_getbytes(); 6890792Sgshapirostatic bool_t xdrrec_putbytes(); 6990792Sgshapirostatic u_int xdrrec_getpos(); 7090792Sgshapirostatic bool_t xdrrec_setpos(); 7190792Sgshapirostatic int32_t *xdrrec_inline(); 7290792Sgshapirostatic void xdrrec_destroy(); 73168515Sgshapiro 7438032Speterstatic struct xdr_ops xdrrec_ops = { 7564562Sgshapiro xdrrec_getlong, 7638032Speter xdrrec_putlong, 7764562Sgshapiro xdrrec_getbytes, 7838032Speter xdrrec_putbytes, 7964562Sgshapiro xdrrec_getpos, 8064562Sgshapiro xdrrec_setpos, 8164562Sgshapiro xdrrec_inline, 8264562Sgshapiro xdrrec_destroy 8364562Sgshapiro}; 8438032Speter 8564562Sgshapiro/* 8664562Sgshapiro * A record is composed of one or more record fragments. 8764562Sgshapiro * A record fragment is a two-byte header followed by zero to 8864562Sgshapiro * 2**32-1 bytes. The header is treated as a long unsigned and is 8964562Sgshapiro * encode/decoded to the network via htonl/ntohl. The low order 31 bits 9064562Sgshapiro * are a byte count of the fragment. The highest order bit is a boolean: 9164562Sgshapiro * 1 => this fragment is the last fragment of the record, 9264562Sgshapiro * 0 => this fragment is followed by more fragment(s). 9364562Sgshapiro * 9464562Sgshapiro * The fragment/record machinery is not general; it is constructed to 9564562Sgshapiro * meet the needs of xdr and rpc based on tcp. 9638032Speter */ 9764562Sgshapiro 9864562Sgshapiro#define LAST_FRAG ((u_int32_t)(1 << 31)) 9938032Speter 10064562Sgshapirotypedef struct rec_strm { 10164562Sgshapiro caddr_t tcp_handle; 10238032Speter caddr_t the_buffer; 10364562Sgshapiro /* 10464562Sgshapiro * out-goung bits 10538032Speter */ 10664562Sgshapiro int (*writeit) __P((caddr_t, caddr_t, int)); 10764562Sgshapiro caddr_t out_base; /* output buffer (points to frag header) */ 10864562Sgshapiro caddr_t out_finger; /* next output position */ 10964562Sgshapiro caddr_t out_boundry; /* data cannot up to this address */ 11064562Sgshapiro u_int32_t *frag_header; /* beginning of current fragment */ 11164562Sgshapiro bool_t frag_sent; /* true if buffer sent in middle of record */ 11290792Sgshapiro /* 11390792Sgshapiro * in-coming bits 11490792Sgshapiro */ 11564562Sgshapiro int (*readit) __P((caddr_t, caddr_t, int)); 11638032Speter u_long in_size; /* fixed size of the input buffer */ 11790792Sgshapiro caddr_t in_base; 11864562Sgshapiro caddr_t in_finger; /* location of next byte to be had */ 11964562Sgshapiro caddr_t in_boundry; /* can read up to this location */ 12064562Sgshapiro long fbtbc; /* fragment bytes to be consumed */ 12164562Sgshapiro bool_t last_frag; 12264562Sgshapiro u_int sendsize; 12338032Speter u_int recvsize; 12464562Sgshapiro} RECSTREAM; 125285303Sgshapiro 12690792Sgshapiro 127249729Sgshapiro/* 128249729Sgshapiro * Create an xdr handle for xdrrec 129249729Sgshapiro * xdrrec_create fills in xdrs. Sendsize and recvsize are 130249729Sgshapiro * send and recv buffer sizes (0 => use default). 131249729Sgshapiro * tcp_handle is an opaque handle that is passed as the first parameter to 13290792Sgshapiro * the procedures readit and writeit. Readit and writeit are read and 13364562Sgshapiro * write respectively. They are like the system 13464562Sgshapiro * calls expect that they take an opaque handle rather than an fd. 13564562Sgshapiro */ 13698121Sgshapirovoid 13798121Sgshapiroxdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit) 13898121Sgshapiro register XDR *xdrs; 13998121Sgshapiro register u_int sendsize; 140225906Sume register u_int recvsize; 14198121Sgshapiro caddr_t tcp_handle; 142225906Sume int (*readit)(); /* like read, but pass it a tcp_handle, not sock */ 143225906Sume int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */ 144261363Sgshapiro{ 14598121Sgshapiro register RECSTREAM *rstrm = 14698121Sgshapiro (RECSTREAM *)mem_alloc(sizeof(RECSTREAM)); 14798121Sgshapiro 148225906Sume if (rstrm == NULL) { 14998121Sgshapiro (void)fprintf(stderr, "xdrrec_create: out of memory\n"); 15064562Sgshapiro /* 15164562Sgshapiro * This is bad. Should rework xdrrec_create to 15298121Sgshapiro * return a handle, and in this case return NULL 15364562Sgshapiro */ 15464562Sgshapiro return; 15598121Sgshapiro } 15664562Sgshapiro /* 15764562Sgshapiro * adjust sizes and allocate buffer quad byte aligned 15864562Sgshapiro */ 15964562Sgshapiro rstrm->sendsize = sendsize = fix_buf_size(sendsize); 16098121Sgshapiro rstrm->recvsize = recvsize = fix_buf_size(recvsize); 16164562Sgshapiro rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT); 16264562Sgshapiro if (rstrm->the_buffer == NULL) { 16364562Sgshapiro (void)fprintf(stderr, "xdrrec_create: out of memory\n"); 16464562Sgshapiro return; 16564562Sgshapiro } 16664562Sgshapiro for (rstrm->out_base = rstrm->the_buffer; 16764562Sgshapiro (u_long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0; 16864562Sgshapiro rstrm->out_base++); 16938032Speter rstrm->in_base = rstrm->out_base + sendsize; 17038032Speter /* 17138032Speter * now the rest ... 17238032Speter */ 17338032Speter xdrs->x_ops = &xdrrec_ops; 17438032Speter xdrs->x_private = (caddr_t)rstrm; 17538032Speter rstrm->tcp_handle = tcp_handle; 17638032Speter rstrm->readit = readit; 17738032Speter rstrm->writeit = writeit; 17838032Speter rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; 17938032Speter rstrm->frag_header = (u_int32_t *)rstrm->out_base; 18064562Sgshapiro rstrm->out_finger += sizeof(u_int32_t); 18164562Sgshapiro rstrm->out_boundry += sendsize; 18264562Sgshapiro rstrm->frag_sent = FALSE; 18364562Sgshapiro rstrm->in_size = recvsize; 18438032Speter rstrm->in_boundry = rstrm->in_base; 18538032Speter rstrm->in_finger = (rstrm->in_boundry += recvsize); 18664562Sgshapiro rstrm->fbtbc = 0; 18738032Speter rstrm->last_frag = TRUE; 18838032Speter} 18964562Sgshapiro 19073188Sgshapiro 19173188Sgshapiro/* 19273188Sgshapiro * The reoutines defined below are the xdr ops which will go into the 19338032Speter * xdr handle filled in by xdrrec_create. 19464562Sgshapiro */ 19564562Sgshapiro 19664562Sgshapirostatic bool_t 19738032Speterxdrrec_getlong(xdrs, lp) 19864562Sgshapiro XDR *xdrs; 19964562Sgshapiro long *lp; 20064562Sgshapiro{ 20138032Speter register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 202285303Sgshapiro register int32_t *buflp = (int32_t *)(rstrm->in_finger); 203285303Sgshapiro int32_t mylong; 204285303Sgshapiro 205285303Sgshapiro /* first try the inline, fast case */ 20664562Sgshapiro if ((rstrm->fbtbc >= sizeof(int32_t)) && 207120256Sgshapiro (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) { 208285303Sgshapiro *lp = (long)ntohl((u_int32_t)(*buflp)); 209120256Sgshapiro rstrm->fbtbc -= sizeof(int32_t); 210285303Sgshapiro rstrm->in_finger += sizeof(int32_t); 211285303Sgshapiro } else { 212285303Sgshapiro if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(int32_t))) 213120256Sgshapiro return (FALSE); 214285303Sgshapiro *lp = (long)ntohl((u_int32_t)mylong); 215285303Sgshapiro } 21690792Sgshapiro return (TRUE); 21790792Sgshapiro} 21890792Sgshapiro 21990792Sgshapirostatic bool_t 22090792Sgshapiroxdrrec_putlong(xdrs, lp) 22190792Sgshapiro XDR *xdrs; 22290792Sgshapiro long *lp; 22390792Sgshapiro{ 22490792Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 22590792Sgshapiro register int32_t *dest_lp = ((int32_t *)(rstrm->out_finger)); 22690792Sgshapiro 22790792Sgshapiro if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) { 22890792Sgshapiro /* 22990792Sgshapiro * this case should almost never happen so the code is 23090792Sgshapiro * inefficient 23190792Sgshapiro */ 23238032Speter rstrm->out_finger -= sizeof(int32_t); 23338032Speter rstrm->frag_sent = TRUE; 23438032Speter if (! flush_out(rstrm, FALSE)) 23590792Sgshapiro return (FALSE); 23638032Speter dest_lp = ((int32_t *)(rstrm->out_finger)); 23790792Sgshapiro rstrm->out_finger += sizeof(int32_t); 23838032Speter } 23938032Speter *dest_lp = (int32_t)htonl((u_int32_t)(*lp)); 24038032Speter return (TRUE); 24138032Speter} 24238032Speter 24338032Speterstatic bool_t /* must manage buffers, fragments, and records */ 24438032Speterxdrrec_getbytes(xdrs, addr, len) 24538032Speter XDR *xdrs; 24638032Speter register caddr_t addr; 24738032Speter register u_int len; 24838032Speter{ 24990792Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 25038032Speter register int current; 25138032Speter 25238032Speter while (len > 0) { 25338032Speter current = rstrm->fbtbc; 25438032Speter if (current == 0) { 25538032Speter if (rstrm->last_frag) 25638032Speter return (FALSE); 25738032Speter if (! set_input_fragment(rstrm)) 25890792Sgshapiro return (FALSE); 25990792Sgshapiro continue; 26090792Sgshapiro } 26190792Sgshapiro current = (len < current) ? len : current; 26238032Speter if (! get_input_bytes(rstrm, addr, current)) 26338032Speter return (FALSE); 26438032Speter addr += current; 26538032Speter rstrm->fbtbc -= current; 26638032Speter len -= current; 26764562Sgshapiro } 26890792Sgshapiro return (TRUE); 26990792Sgshapiro} 27090792Sgshapiro 27190792Sgshapirostatic bool_t 27238032Speterxdrrec_putbytes(xdrs, addr, len) 27338032Speter XDR *xdrs; 27438032Speter register caddr_t addr; 27538032Speter register u_int len; 27664562Sgshapiro{ 27764562Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 27864562Sgshapiro register long current; 27964562Sgshapiro 28064562Sgshapiro while (len > 0) { 28164562Sgshapiro current = (u_long)rstrm->out_boundry - 28264562Sgshapiro (u_long)rstrm->out_finger; 28364562Sgshapiro current = (len < current) ? len : current; 28464562Sgshapiro memcpy(rstrm->out_finger, addr, current); 28564562Sgshapiro rstrm->out_finger += current; 28690792Sgshapiro addr += current; 28764562Sgshapiro len -= current; 28864562Sgshapiro if (rstrm->out_finger == rstrm->out_boundry) { 28964562Sgshapiro rstrm->frag_sent = TRUE; 29064562Sgshapiro if (! flush_out(rstrm, FALSE)) 29164562Sgshapiro return (FALSE); 29290792Sgshapiro } 29390792Sgshapiro } 29490792Sgshapiro return (TRUE); 295285303Sgshapiro} 296285303Sgshapiro 29764562Sgshapirostatic u_int 29864562Sgshapiroxdrrec_getpos(xdrs) 29938032Speter register XDR *xdrs; 300285303Sgshapiro{ 301285303Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 30264562Sgshapiro register long pos; 30338032Speter 304285303Sgshapiro pos = lseek((int)(long)rstrm->tcp_handle, (off_t) 0, 1); 305285303Sgshapiro if (pos != -1) 306285303Sgshapiro switch (xdrs->x_op) { 307285303Sgshapiro 308285303Sgshapiro case XDR_ENCODE: 309285303Sgshapiro pos += rstrm->out_finger - rstrm->out_base; 310285303Sgshapiro break; 311285303Sgshapiro 31264562Sgshapiro case XDR_DECODE: 31364562Sgshapiro pos -= rstrm->in_boundry - rstrm->in_finger; 31464562Sgshapiro break; 31564562Sgshapiro 31664562Sgshapiro default: 31790792Sgshapiro pos = -1; 31890792Sgshapiro break; 31938032Speter } 32090792Sgshapiro return ((u_int) pos); 32190792Sgshapiro} 32290792Sgshapiro 32390792Sgshapirostatic bool_t 32490792Sgshapiroxdrrec_setpos(xdrs, pos) 32590792Sgshapiro register XDR *xdrs; 32690792Sgshapiro u_int pos; 32790792Sgshapiro{ 32890792Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 32990792Sgshapiro u_int currpos = xdrrec_getpos(xdrs); 33090792Sgshapiro int delta = currpos - pos; 33190792Sgshapiro caddr_t newpos; 33290792Sgshapiro 33390792Sgshapiro if ((int)currpos != -1) 33490792Sgshapiro switch (xdrs->x_op) { 335102528Sgshapiro 33690792Sgshapiro case XDR_ENCODE: 33764562Sgshapiro newpos = rstrm->out_finger - delta; 33864562Sgshapiro if ((newpos > (caddr_t)(rstrm->frag_header)) && 33964562Sgshapiro (newpos < rstrm->out_boundry)) { 34064562Sgshapiro rstrm->out_finger = newpos; 34164562Sgshapiro return (TRUE); 34290792Sgshapiro } 34364562Sgshapiro break; 34464562Sgshapiro 34564562Sgshapiro case XDR_DECODE: 34664562Sgshapiro newpos = rstrm->in_finger - delta; 34764562Sgshapiro if ((delta < (int)(rstrm->fbtbc)) && 34890792Sgshapiro (newpos <= rstrm->in_boundry) && 34964562Sgshapiro (newpos >= rstrm->in_base)) { 35090792Sgshapiro rstrm->in_finger = newpos; 35190792Sgshapiro rstrm->fbtbc -= delta; 35264562Sgshapiro return (TRUE); 35390792Sgshapiro } 35490792Sgshapiro break; 35564562Sgshapiro } 35690792Sgshapiro return (FALSE); 357173340Sgshapiro} 358173340Sgshapiro 35990792Sgshapirostatic int32_t * 360223067Sgshapiroxdrrec_inline(xdrs, len) 36164562Sgshapiro register XDR *xdrs; 36264562Sgshapiro int len; 36364562Sgshapiro{ 36464562Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 36564562Sgshapiro int32_t * buf = NULL; 366285303Sgshapiro 367285303Sgshapiro switch (xdrs->x_op) { 368285303Sgshapiro 36938032Speter case XDR_ENCODE: 370168515Sgshapiro if ((rstrm->out_finger + len) <= rstrm->out_boundry) { 371111823Sgshapiro buf = (int32_t *) rstrm->out_finger; 37264562Sgshapiro rstrm->out_finger += len; 37364562Sgshapiro } 37464562Sgshapiro break; 37590792Sgshapiro 37690792Sgshapiro case XDR_DECODE: 37790792Sgshapiro if ((len <= rstrm->fbtbc) && 378132943Sgshapiro ((rstrm->in_finger + len) <= rstrm->in_boundry)) { 379132943Sgshapiro buf = (int32_t *) rstrm->in_finger; 38038032Speter rstrm->fbtbc -= len; 38164562Sgshapiro rstrm->in_finger += len; 38290792Sgshapiro } 38338032Speter break; 38438032Speter } 38590792Sgshapiro return (buf); 38664562Sgshapiro} 38790792Sgshapiro 38864562Sgshapirostatic void 389168515Sgshapiroxdrrec_destroy(xdrs) 390168515Sgshapiro register XDR *xdrs; 391168515Sgshapiro{ 392168515Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private; 393168515Sgshapiro 394168515Sgshapiro mem_free(rstrm->the_buffer, 39564562Sgshapiro rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); 39690792Sgshapiro mem_free((caddr_t)rstrm, sizeof(RECSTREAM)); 39790792Sgshapiro} 39890792Sgshapiro 39990792Sgshapiro 400168515Sgshapiro/* 401168515Sgshapiro * Exported routines to manage xdr records 402168515Sgshapiro */ 403168515Sgshapiro 404168515Sgshapiro/* 405168515Sgshapiro * Before reading (deserializing from the stream, one should always call 406168515Sgshapiro * this procedure to guarantee proper record alignment. 407168515Sgshapiro */ 40838032Speterbool_t 40938032Speterxdrrec_skiprecord(xdrs) 41038032Speter XDR *xdrs; 41138032Speter{ 41238032Speter register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 41338032Speter 41438032Speter while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 41538032Speter if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 41638032Speter return (FALSE); 41738032Speter rstrm->fbtbc = 0; 41838032Speter if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 41938032Speter return (FALSE); 42038032Speter } 42138032Speter rstrm->last_frag = FALSE; 42238032Speter return (TRUE); 42338032Speter} 42438032Speter 42538032Speter/* 42664562Sgshapiro * Look ahead fuction. 42738032Speter * Returns TRUE iff there is no more input in the buffer 42838032Speter * after consuming the rest of the current record. 42938032Speter */ 43038032Speterbool_t 43138032Speterxdrrec_eof(xdrs) 43238032Speter XDR *xdrs; 43338032Speter{ 43438032Speter register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 43538032Speter 43638032Speter while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) { 43764562Sgshapiro if (! skip_input_bytes(rstrm, rstrm->fbtbc)) 43838032Speter return (TRUE); 43964562Sgshapiro rstrm->fbtbc = 0; 44038032Speter if ((! rstrm->last_frag) && (! set_input_fragment(rstrm))) 44138032Speter return (TRUE); 44238032Speter } 44364562Sgshapiro if (rstrm->in_finger == rstrm->in_boundry) 44464562Sgshapiro return (TRUE); 44590792Sgshapiro return (FALSE); 44638032Speter} 44738032Speter 44838032Speter/* 449285303Sgshapiro * The client must tell the package when an end-of-record has occurred. 45090792Sgshapiro * The second paraemters tells whether the record should be flushed to the 45164562Sgshapiro * (output) tcp stream. (This let's the package support batched or 45264562Sgshapiro * pipelined procedure calls.) TRUE => immmediate flush to tcp connection. 453141858Sgshapiro */ 45464562Sgshapirobool_t 45564562Sgshapiroxdrrec_endofrecord(xdrs, sendnow) 45664562Sgshapiro XDR *xdrs; 45738032Speter bool_t sendnow; 45864562Sgshapiro{ 45964562Sgshapiro register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private); 46064562Sgshapiro register u_long len; /* fragment length */ 46138032Speter 46264562Sgshapiro if (sendnow || rstrm->frag_sent || 46364562Sgshapiro ((u_long)rstrm->out_finger + sizeof(u_int32_t) >= 46464562Sgshapiro (u_long)rstrm->out_boundry)) { 46564562Sgshapiro rstrm->frag_sent = FALSE; 46664562Sgshapiro return (flush_out(rstrm, TRUE)); 46764562Sgshapiro } 46864562Sgshapiro len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) - 46964562Sgshapiro sizeof(u_int32_t); 47064562Sgshapiro *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG); 47164562Sgshapiro rstrm->frag_header = (u_int32_t *)rstrm->out_finger; 47264562Sgshapiro rstrm->out_finger += sizeof(u_int32_t); 47338032Speter return (TRUE); 47464562Sgshapiro} 47564562Sgshapiro 47664562Sgshapiro 477285303Sgshapiro/* 47864562Sgshapiro * Internal useful routines 47938032Speter */ 48064562Sgshapirostatic bool_t 48164562Sgshapiroflush_out(rstrm, eor) 48264562Sgshapiro register RECSTREAM *rstrm; 48364562Sgshapiro bool_t eor; 48464562Sgshapiro{ 48564562Sgshapiro register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; 48664562Sgshapiro register u_int32_t len = (u_long)(rstrm->out_finger) - 48764562Sgshapiro (u_long)(rstrm->frag_header) - sizeof(u_int32_t); 48838032Speter 48964562Sgshapiro *(rstrm->frag_header) = htonl(len | eormask); 490132943Sgshapiro len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base); 49138032Speter if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len) 49264562Sgshapiro != (int)len) 493285303Sgshapiro return (FALSE); 494285303Sgshapiro rstrm->frag_header = (u_int32_t *)rstrm->out_base; 49564562Sgshapiro rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_int32_t); 49690792Sgshapiro return (TRUE); 49764562Sgshapiro} 49864562Sgshapiro 49990792Sgshapirostatic bool_t /* knows nothing about records! Only about input buffers */ 500285303Sgshapirofill_input_buf(rstrm) 50164562Sgshapiro register RECSTREAM *rstrm; 50264562Sgshapiro{ 50364562Sgshapiro register caddr_t where; 50464562Sgshapiro u_long i; 50564562Sgshapiro register long len; 50664562Sgshapiro 50764562Sgshapiro where = rstrm->in_base; 50864562Sgshapiro i = (u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT; 50964562Sgshapiro where += i; 51064562Sgshapiro len = rstrm->in_size - i; 51164562Sgshapiro if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1) 51264562Sgshapiro return (FALSE); 51364562Sgshapiro rstrm->in_finger = where; 51464562Sgshapiro where += len; 515261363Sgshapiro rstrm->in_boundry = where; 51638032Speter return (TRUE); 51764562Sgshapiro} 51864562Sgshapiro 51964562Sgshapirostatic bool_t /* knows nothing about records! Only about input buffers */ 52090792Sgshapiroget_input_bytes(rstrm, addr, len) 521141858Sgshapiro register RECSTREAM *rstrm; 52294334Sgshapiro register caddr_t addr; 52394334Sgshapiro register int len; 52494334Sgshapiro{ 52538032Speter register long current; 52690792Sgshapiro 52790792Sgshapiro while (len > 0) { 52890792Sgshapiro current = (long)rstrm->in_boundry - (long)rstrm->in_finger; 52990792Sgshapiro if (current == 0) { 530285303Sgshapiro if (! fill_input_buf(rstrm)) 531285303Sgshapiro return (FALSE); 532285303Sgshapiro continue; 53390792Sgshapiro } 534285303Sgshapiro current = (len < current) ? len : current; 53590792Sgshapiro memcpy(addr, rstrm->in_finger, current); 53690792Sgshapiro rstrm->in_finger += current; 53790792Sgshapiro addr += current; 53890792Sgshapiro len -= current; 53990792Sgshapiro } 54090792Sgshapiro return (TRUE); 54190792Sgshapiro} 54290792Sgshapiro 54390792Sgshapirostatic bool_t /* next two bytes of the input stream are treated as a header */ 54490792Sgshapiroset_input_fragment(rstrm) 54590792Sgshapiro register RECSTREAM *rstrm; 54690792Sgshapiro{ 54790792Sgshapiro u_int32_t header; 54890792Sgshapiro 54990792Sgshapiro if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header))) 55090792Sgshapiro return (FALSE); 55190792Sgshapiro header = (long)ntohl(header); 55290792Sgshapiro rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; 55390792Sgshapiro rstrm->fbtbc = header & (~LAST_FRAG); 55490792Sgshapiro return (TRUE); 55590792Sgshapiro} 55690792Sgshapiro 55790792Sgshapirostatic bool_t /* consumes input bytes; knows nothing about records! */ 55890792Sgshapiroskip_input_bytes(rstrm, cnt) 55990792Sgshapiro register RECSTREAM *rstrm; 56090792Sgshapiro long cnt; 56190792Sgshapiro{ 56290792Sgshapiro register long current; 56390792Sgshapiro 56490792Sgshapiro while (cnt > 0) { 56590792Sgshapiro current = (long)rstrm->in_boundry - (long)rstrm->in_finger; 56690792Sgshapiro if (current == 0) { 56790792Sgshapiro if (! fill_input_buf(rstrm)) 56890792Sgshapiro return (FALSE); 56990792Sgshapiro continue; 57090792Sgshapiro } 57190792Sgshapiro current = (cnt < current) ? cnt : current; 57290792Sgshapiro rstrm->in_finger += current; 57390792Sgshapiro cnt -= current; 57490792Sgshapiro } 57590792Sgshapiro return (TRUE); 57690792Sgshapiro} 57790792Sgshapiro 57890792Sgshapirostatic u_int 57990792Sgshapirofix_buf_size(s) 58090792Sgshapiro register u_int s; 58190792Sgshapiro{ 58290792Sgshapiro 58390792Sgshapiro if (s < 100) 58494334Sgshapiro s = 4000; 58594334Sgshapiro return (RNDUP(s)); 58694334Sgshapiro} 58794334Sgshapiro