3 * Copyright (c) 2009, Sun Microsystems, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * - Neither the name of Sun Microsystems, Inc. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
31 * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
32 * layer above tcp (for rpc's use).
34 * Copyright (C) 1984, Sun Microsystems, Inc.
36 * These routines interface XDRSTREAMS to a tcp/ip connection.
37 * There is a record marking layer between the xdr stream
38 * and the tcp transport level. A record is composed on one or more
39 * record fragments. A record fragment is a thirty-two bit header followed
40 * by n bytes of data, where n is contained in the header. The header
41 * is represented as a htonl(u_long). Thegh order bit encodes
42 * whether or not the fragment is the last fragment of the record
43 * (1 => fragment is last, 0 => more fragments to follow.
44 * The other 31 bits encode the byte length of the fragment.
48 #include <sys/types.h>
56 #include <rpc/types.h>
59 #include "xdr_private.h"
62 # define ntohl(x) xdr_ntohl(x)
65 # define htonl(x) xdr_htonl(x)
75 static bool_t
xdrrec_getlong (XDR
*, long *);
76 static bool_t
xdrrec_putlong (XDR
*, const long *);
77 static bool_t
xdrrec_getbytes (XDR
*, char *, u_int
);
78 static bool_t
xdrrec_putbytes (XDR
*, const char *, u_int
);
79 static u_int
xdrrec_getpos (XDR
*);
80 static bool_t
xdrrec_setpos (XDR
*, u_int
);
81 static int32_t * xdrrec_inline (XDR
*, u_int
);
82 static void xdrrec_destroy (XDR
*);
83 static bool_t
xdrrec_getint32 (XDR
*, int32_t *);
84 static bool_t
xdrrec_putint32 (XDR
*, const int32_t *);
86 static const struct xdr_ops xdrrec_ops
= {
100 * A record is composed of one or more record fragments.
101 * A record fragment is a four-byte header followed by zero to
102 * 2**32-1 bytes. The header is treated as a long unsigned and is
103 * encode/decoded to the network via htonl/ntohl. The low order 31 bits
104 * are a byte count of the fragment. The highest order bit is a boolean:
105 * 1 => this fragment is the last fragment of the record,
106 * 0 => this fragment is followed by more fragment(s).
108 * The fragment/record machinery is not general; it is constructed to
109 * meet the needs of xdr and rpc based on tcp.
112 #define LAST_FRAG ((u_int32_t)(UINT32_C(1) << 31))
114 typedef struct rec_strm
120 caddr_t out_buffer
; /* buffer as allocated; may not be aligned */
121 int (*writeit
) (void *, void *, int);
122 caddr_t out_base
; /* output buffer (points to frag header) */
123 caddr_t out_finger
; /* next output position */
124 caddr_t out_boundry
; /* data cannot up to this address */
125 u_int32_t
*frag_header
; /* beginning of curren fragment */
126 bool_t frag_sent
; /* true if buffer sent in middle of record */
130 caddr_t in_buffer
; /* buffer as allocated; may not be aligned */
131 int (*readit
) (void *, void *, int);
132 u_long in_size
; /* fixed size of the input buffer */
134 caddr_t in_finger
; /* location of next byte to be had */
135 caddr_t in_boundry
; /* can read up to this location */
136 long fbtbc
; /* fragment bytes to be consumed */
138 u_int sendsize
; /* must be <= INT_MAX */
139 u_int recvsize
; /* must be <= INT_MAX */
142 bool_t in_haveheader
;
151 static u_int
fix_buf_size (u_int
);
152 static bool_t
flush_out (RECSTREAM
*, bool_t
);
153 static bool_t
fill_input_buf (RECSTREAM
*);
154 static bool_t
get_input_bytes (RECSTREAM
*, char *, size_t);
155 static bool_t
set_input_fragment (RECSTREAM
*);
156 static bool_t
skip_input_bytes (RECSTREAM
*, long);
157 static bool_t
realloc_stream (RECSTREAM
*, int);
159 bool_t
__xdrrec_getrec (XDR
*, enum xprt_stat
*, bool_t
);
160 bool_t
__xdrrec_setnonblock (XDR
*, int);
163 * Create an xdr handle for xdrrec
164 * xdrrec_create fills in xdrs. Sendsize and recvsize are
165 * send and recv buffer sizes (0 => use default), and must be <= INT_MAX.
166 * tcp_handle is an opaque handle that is passed as the first parameter to
167 * the procedures readit and writeit. Readit and writeit are read and
168 * write respectively. They are like the system
169 * calls except that they take an opaque handle rather than an fd.
172 xdrrec_create (XDR
* xdrs
,
176 int (*readit
) (void *, void *, int),
177 int (*writeit
) (void *, void *, int))
180 /* Although sendsize and recvsize are u_int, we require
181 * that they be less than INT_MAX, because often we need
182 * to compare against values held in (signed) integers.
183 * Please don't try to use send/recv buffers > 2GB...
185 assert (sendsize
< (u_int
)INT_MAX
);
186 assert (recvsize
< (u_int
)INT_MAX
);
188 rstrm
= (RECSTREAM
*) mem_alloc (sizeof (RECSTREAM
));
191 xdr_warnx ("xdrrec_create: out of memory");
193 * This is bad. Should rework xdrrec_create to
194 * return a handle, and in this case return NULL
201 /* allocate send buffer; insure BYTES_PER_UNIT alignment */
202 rstrm
->sendsize
= sendsize
= fix_buf_size (sendsize
);
203 rstrm
->out_buffer
= mem_alloc (rstrm
->sendsize
+ BYTES_PER_XDR_UNIT
);
204 if (rstrm
->out_buffer
== NULL
)
206 xdr_warnx ("xdrrec_create: out of memory");
207 mem_free (rstrm
, sizeof (RECSTREAM
));
211 for (rstrm
->out_base
= rstrm
->out_buffer
;
212 (long) rstrm
->out_base
% BYTES_PER_XDR_UNIT
!= 0; rstrm
->out_base
++)
215 /* allocate recv buffer; insure BYTES_PER_UNIT alignment */
216 rstrm
->recvsize
= recvsize
= fix_buf_size (recvsize
);
217 rstrm
->in_buffer
= mem_alloc (recvsize
+ BYTES_PER_XDR_UNIT
);
218 if (rstrm
->in_buffer
== NULL
)
220 xdr_warnx ("xdrrec_create: out of memory");
221 mem_free (rstrm
->out_buffer
, sendsize
+ BYTES_PER_XDR_UNIT
);
222 mem_free (rstrm
, sizeof (RECSTREAM
));
226 for (rstrm
->in_base
= rstrm
->in_buffer
;
227 (long) rstrm
->in_base
% BYTES_PER_XDR_UNIT
!= 0; rstrm
->in_base
++)
233 xdrs
->x_ops
= &xdrrec_ops
;
234 xdrs
->x_private
= rstrm
;
235 rstrm
->tcp_handle
= tcp_handle
;
236 rstrm
->readit
= readit
;
237 rstrm
->writeit
= writeit
;
238 rstrm
->out_finger
= rstrm
->out_boundry
= rstrm
->out_base
;
239 rstrm
->frag_header
= (u_int32_t
*) (void *) rstrm
->out_base
;
240 rstrm
->out_finger
+= sizeof (u_int32_t
);
241 rstrm
->out_boundry
+= sendsize
;
242 rstrm
->frag_sent
= FALSE
;
243 rstrm
->in_size
= recvsize
;
244 rstrm
->in_boundry
= rstrm
->in_base
;
245 rstrm
->in_finger
= (rstrm
->in_boundry
+= recvsize
);
247 rstrm
->last_frag
= TRUE
;
248 rstrm
->in_haveheader
= FALSE
;
249 rstrm
->in_hdrlen
= 0;
250 rstrm
->in_hdrp
= (char *) (void *) &rstrm
->in_header
;
251 rstrm
->nonblock
= FALSE
;
252 rstrm
->in_reclen
= 0;
253 rstrm
->in_received
= 0;
258 * The reoutines defined below are the xdr ops which will go into the
259 * xdr handle filled in by xdrrec_create.
263 xdrrec_getlong (XDR
* xdrs
,
266 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
267 int32_t *buflp
= (int32_t *) (void *) (rstrm
->in_finger
);
270 /* first try the inline, fast case */
271 if ((rstrm
->fbtbc
>= sizeof (int32_t)) &&
272 (((long) rstrm
->in_boundry
- (long) buflp
) >= sizeof (int32_t)))
274 *lp
= (long) ntohl ((u_int32_t
) (*buflp
));
275 rstrm
->fbtbc
-= sizeof (int32_t);
276 rstrm
->in_finger
+= sizeof (int32_t);
280 if (!xdrrec_getbytes (xdrs
, (char *) (void *) &mylong
,
283 *lp
= (long) ntohl ((u_int32_t
) mylong
);
289 xdrrec_putlong (XDR
* xdrs
,
292 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
293 int32_t *dest_lp
= ((int32_t *) (void *) (rstrm
->out_finger
));
295 if ((rstrm
->out_finger
+= sizeof (int32_t)) > rstrm
->out_boundry
)
298 * this case should almost never happen so the code is
301 rstrm
->out_finger
-= sizeof (int32_t);
302 rstrm
->frag_sent
= TRUE
;
303 if (!flush_out (rstrm
, FALSE
))
305 dest_lp
= ((int32_t *) (void *) (rstrm
->out_finger
));
306 rstrm
->out_finger
+= sizeof (int32_t);
308 *dest_lp
= (int32_t) htonl ((u_int32_t
) (*lp
));
312 static bool_t
/* must manage buffers, fragments, and records */
313 xdrrec_getbytes (XDR
* xdrs
,
317 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
322 current
= (int) rstrm
->fbtbc
;
325 if (rstrm
->last_frag
)
327 if (!set_input_fragment (rstrm
))
331 current
= (len
< current
) ? len
: current
;
332 if (!get_input_bytes (rstrm
, addr
, current
))
335 rstrm
->fbtbc
-= current
;
342 xdrrec_putbytes (XDR
* xdrs
,
346 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
351 current
= (size_t) ((u_long
) rstrm
->out_boundry
-
352 (u_long
) rstrm
->out_finger
);
353 current
= (len
< current
) ? len
: current
;
354 memmove (rstrm
->out_finger
, addr
, current
);
355 rstrm
->out_finger
+= current
;
358 if (rstrm
->out_finger
== rstrm
->out_boundry
)
360 rstrm
->frag_sent
= TRUE
;
361 if (!flush_out (rstrm
, FALSE
))
369 xdrrec_getpos (XDR
* xdrs
)
371 RECSTREAM
*rstrm
= (RECSTREAM
*) xdrs
->x_private
;
374 pos
= lseek ((int) (u_long
) rstrm
->tcp_handle
, (off_t
) 0, 1);
380 pos
+= rstrm
->out_finger
- rstrm
->out_base
;
384 pos
-= rstrm
->in_boundry
- rstrm
->in_finger
;
391 return ((u_int
) pos
);
395 xdrrec_setpos (XDR
* xdrs
,
398 RECSTREAM
*rstrm
= (RECSTREAM
*) xdrs
->x_private
;
399 u_int currpos
= xdrrec_getpos (xdrs
);
400 int delta
= currpos
- pos
;
403 if ((int) currpos
!= -1)
408 newpos
= rstrm
->out_finger
- delta
;
409 if ((newpos
> (char *) (void *) (rstrm
->frag_header
)) &&
410 (newpos
< rstrm
->out_boundry
))
412 rstrm
->out_finger
= newpos
;
418 newpos
= rstrm
->in_finger
- delta
;
419 if ((delta
< (int) (rstrm
->fbtbc
)) &&
420 (newpos
<= rstrm
->in_boundry
) && (newpos
>= rstrm
->in_base
))
422 rstrm
->in_finger
= newpos
;
423 rstrm
->fbtbc
-= delta
;
435 xdrrec_inline (XDR
* xdrs
,
438 RECSTREAM
*rstrm
= (RECSTREAM
*) xdrs
->x_private
;
440 /* len represents the number of bytes to extract
441 * from the buffer. The number of bytes remaining
442 * in the buffer is rstrm->fbtbc, which is a long.
443 * Thus, the buffer size maximum is 2GB (!), and
444 * we require that no one ever try to read more
445 * than than number of bytes at once.
447 assert (len
< (u_int
)LONG_MAX
);
453 if ((rstrm
->out_finger
+ len
) <= rstrm
->out_boundry
)
455 buf
= (int32_t *) (void *) rstrm
->out_finger
;
456 rstrm
->out_finger
+= len
;
461 if (((long)len
<= rstrm
->fbtbc
) &&
462 ((rstrm
->in_finger
+ len
) <= rstrm
->in_boundry
))
464 buf
= (int32_t *) (void *) rstrm
->in_finger
;
466 rstrm
->in_finger
+= len
;
477 xdrrec_destroy (XDR
* xdrs
)
479 RECSTREAM
*rstrm
= (RECSTREAM
*) xdrs
->x_private
;
481 mem_free (rstrm
->out_buffer
, rstrm
->sendsize
+ BYTES_PER_XDR_UNIT
);
482 mem_free (rstrm
->in_buffer
, rstrm
->recvsize
+ BYTES_PER_XDR_UNIT
);
483 mem_free (rstrm
, sizeof (RECSTREAM
));
487 xdrrec_getint32 (XDR
*xdrs
,
490 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
491 int32_t *bufip
= (int32_t *) (void *) (rstrm
->in_finger
);
494 /* first try the inline, fast case */
495 if ((rstrm
->fbtbc
>= sizeof (int32_t)) &&
496 (( rstrm
->in_boundry
- (char *) bufip
) >= sizeof (int32_t)))
498 *ip
= (int32_t) ntohl (*bufip
);
499 rstrm
->fbtbc
-= sizeof (int32_t);
500 rstrm
->in_finger
+= sizeof (int32_t);
504 if (!xdrrec_getbytes (xdrs
, (char *) (void *) &mylong
,
507 *ip
= (int32_t) ntohl (mylong
);
513 xdrrec_putint32 (XDR
*xdrs
,
516 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
517 int32_t *dest_ip
= ((int32_t *) (void *) (rstrm
->out_finger
));
519 if ((rstrm
->out_finger
+= sizeof (int32_t)) > rstrm
->out_boundry
)
522 * this case should almost never happen so the code is
525 rstrm
->out_finger
-= sizeof (int32_t);
526 rstrm
->frag_sent
= TRUE
;
527 if (!flush_out (rstrm
, FALSE
))
529 dest_ip
= ((int32_t *) (void *) (rstrm
->out_finger
));
530 rstrm
->out_finger
+= sizeof (int32_t);
532 *dest_ip
= (int32_t) htonl (*ip
);
537 * Exported routines to manage xdr records
541 * Before reading (deserializing from the stream, one should always call
542 * this procedure to guarantee proper record alignment.
545 xdrrec_skiprecord (XDR
* xdrs
)
547 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
548 enum xprt_stat xstat
;
552 if (__xdrrec_getrec (xdrs
, &xstat
, FALSE
))
557 if (rstrm
->in_finger
== rstrm
->in_boundry
&& xstat
== XPRT_MOREREQS
)
565 while (rstrm
->fbtbc
> 0 || (!rstrm
->last_frag
))
567 if (!skip_input_bytes (rstrm
, rstrm
->fbtbc
))
570 if ((!rstrm
->last_frag
) && (!set_input_fragment (rstrm
)))
573 rstrm
->last_frag
= FALSE
;
578 * Look ahead function.
579 * Returns TRUE iff there is no more input in the buffer
580 * after consuming the rest of the current record.
583 xdrrec_eof (XDR
* xdrs
)
585 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
587 while (rstrm
->fbtbc
> 0 || (!rstrm
->last_frag
))
589 if (!skip_input_bytes (rstrm
, rstrm
->fbtbc
))
592 if ((!rstrm
->last_frag
) && (!set_input_fragment (rstrm
)))
595 if (rstrm
->in_finger
== rstrm
->in_boundry
)
601 * The client must tell the package when an end-of-record has occurred.
602 * The second paraemters tells whether the record should be flushed to the
603 * (output) tcp stream. (This let's the package support batched or
604 * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
607 xdrrec_endofrecord (XDR
* xdrs
,
610 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
611 u_long len
; /* fragment length */
613 if (sendnow
|| rstrm
->frag_sent
||
614 ((u_long
) rstrm
->out_finger
+ sizeof (u_int32_t
) >=
615 (u_long
) rstrm
->out_boundry
))
617 rstrm
->frag_sent
= FALSE
;
618 return (flush_out (rstrm
, TRUE
));
620 len
= (u_long
) (rstrm
->out_finger
) - (u_long
) (rstrm
->frag_header
) -
622 *(rstrm
->frag_header
) = htonl ((u_int32_t
) len
| LAST_FRAG
);
623 rstrm
->frag_header
= (u_int32_t
*) (void *) rstrm
->out_finger
;
624 rstrm
->out_finger
+= sizeof (u_int32_t
);
629 * Fill the stream buffer with a record for a non-blocking connection.
630 * Return true if a record is available in the buffer, false if not.
633 __xdrrec_getrec (XDR
* xdrs
,
634 enum xprt_stat
* statp
,
637 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
641 if (!rstrm
->in_haveheader
)
643 n
= rstrm
->readit (rstrm
->tcp_handle
, rstrm
->in_hdrp
,
644 (int) sizeof (rstrm
->in_header
) - rstrm
->in_hdrlen
);
647 *statp
= expectdata
? XPRT_DIED
: XPRT_IDLE
;
656 rstrm
->in_hdrlen
+= n
;
657 if (rstrm
->in_hdrlen
< sizeof (rstrm
->in_header
))
659 *statp
= XPRT_MOREREQS
;
662 rstrm
->in_header
= ntohl (rstrm
->in_header
);
663 fraglen
= (int) (rstrm
->in_header
& ~LAST_FRAG
);
664 if (fraglen
== 0 || fraglen
> rstrm
->in_maxrec
||
665 (rstrm
->in_reclen
+ fraglen
) > rstrm
->in_maxrec
)
670 rstrm
->in_reclen
+= fraglen
;
671 if (rstrm
->in_reclen
> (int)rstrm
->recvsize
) /* guaranteed recvsize < INT_MAX */
672 realloc_stream (rstrm
, rstrm
->in_reclen
);
673 if (rstrm
->in_header
& LAST_FRAG
)
675 rstrm
->in_header
&= ~LAST_FRAG
;
676 rstrm
->last_frag
= TRUE
;
679 * We can only reasonably expect to read once from a
680 * non-blocking stream. Reading the fragment header
681 * may have drained the stream.
686 n
= rstrm
->readit (rstrm
->tcp_handle
,
687 rstrm
->in_base
+ rstrm
->in_received
,
688 (rstrm
->in_reclen
- rstrm
->in_received
));
698 *statp
= expectdata
? XPRT_DIED
: XPRT_IDLE
;
702 rstrm
->in_received
+= n
;
704 if (rstrm
->in_received
== rstrm
->in_reclen
)
706 rstrm
->in_haveheader
= FALSE
;
707 rstrm
->in_hdrp
= (char *) (void *) &rstrm
->in_header
;
708 rstrm
->in_hdrlen
= 0;
709 if (rstrm
->last_frag
)
711 rstrm
->fbtbc
= rstrm
->in_reclen
;
712 rstrm
->in_boundry
= rstrm
->in_base
+ rstrm
->in_reclen
;
713 rstrm
->in_finger
= rstrm
->in_base
;
714 rstrm
->in_reclen
= rstrm
->in_received
= 0;
715 *statp
= XPRT_MOREREQS
;
720 *statp
= XPRT_MOREREQS
;
725 __xdrrec_setnonblock (XDR
* xdrs
,
728 RECSTREAM
*rstrm
= (RECSTREAM
*) (xdrs
->x_private
);
730 rstrm
->nonblock
= TRUE
;
732 maxrec
= rstrm
->recvsize
;
733 rstrm
->in_maxrec
= maxrec
;
738 * Internal useful routines
741 flush_out (RECSTREAM
* rstrm
,
744 u_int32_t eormask
= (eor
== TRUE
) ? LAST_FRAG
: 0;
745 u_int32_t len
= (u_int32_t
) ((u_long
) (rstrm
->out_finger
) -
746 (u_long
) (rstrm
->frag_header
) -
749 *(rstrm
->frag_header
) = htonl (len
| eormask
);
750 len
= (u_int32_t
) ((u_long
) (rstrm
->out_finger
) -
751 (u_long
) (rstrm
->out_base
));
752 if ((*(rstrm
->writeit
)) (rstrm
->tcp_handle
, rstrm
->out_base
, (int) len
)
755 rstrm
->frag_header
= (u_int32_t
*) (void *) rstrm
->out_base
;
756 rstrm
->out_finger
= (char *) rstrm
->out_base
+ sizeof (u_int32_t
);
760 static bool_t
/* knows nothing about records! Only about input buffers */
761 fill_input_buf (RECSTREAM
* rstrm
)
770 where
= rstrm
->in_base
;
771 i
= (u_int32_t
) ((u_long
) rstrm
->in_boundry
% BYTES_PER_XDR_UNIT
);
773 len
= (u_int32_t
) (rstrm
->in_size
- i
);
774 if ((len
= (*(rstrm
->readit
)) (rstrm
->tcp_handle
, where
, len
)) == -1)
776 rstrm
->in_finger
= where
;
778 rstrm
->in_boundry
= where
;
782 static bool_t
/* knows nothing about records! Only about input buffers */
783 get_input_bytes (RECSTREAM
* rstrm
,
791 if ((rstrm
->in_boundry
< rstrm
->in_finger
) || /* <-- should never happen, but avoids... */
792 (len
> (size_t) (rstrm
->in_boundry
- rstrm
->in_finger
))) /* <-- signed/unsigned comparison */
794 memcpy (addr
, rstrm
->in_finger
, (size_t) len
);
795 rstrm
->in_finger
+= len
;
801 current
= (size_t) ((long) rstrm
->in_boundry
- (long) rstrm
->in_finger
);
804 if (!fill_input_buf (rstrm
))
808 current
= (len
< current
) ? len
: current
;
809 memmove (addr
, rstrm
->in_finger
, current
);
810 rstrm
->in_finger
+= current
;
817 static bool_t
/* next two bytes of the input stream are treated as a header */
818 set_input_fragment (RECSTREAM
* rstrm
)
824 if (!get_input_bytes (rstrm
, (char *) (void *) &header
, sizeof (header
)))
826 header
= ntohl (header
);
827 rstrm
->last_frag
= ((header
& LAST_FRAG
) == 0) ? FALSE
: TRUE
;
829 * Sanity check. Try not to accept wildly incorrect
830 * record sizes. Unfortunately, the only record size
831 * we can positively identify as being 'wildly incorrect'
832 * is zero. Ridiculously large record sizes may look wrong,
833 * but we don't have any way to be certain that they aren't
834 * what the client actually intended to send us.
838 rstrm
->fbtbc
= header
& (~LAST_FRAG
);
842 static bool_t
/* consumes input bytes; knows nothing about records! */
843 skip_input_bytes (RECSTREAM
* rstrm
,
850 current
= (size_t) ((long) rstrm
->in_boundry
- (long) rstrm
->in_finger
);
853 if (!fill_input_buf (rstrm
))
857 /* in this loop (prior to last line), cnt > 0 so size_t cast is safe*/
858 current
= (size_t) (((size_t)cnt
< current
) ? (size_t)cnt
: current
);
859 rstrm
->in_finger
+= current
;
866 fix_buf_size (u_int s
)
875 * Reallocate the input buffer for a non-block stream.
878 realloc_stream (RECSTREAM
* rstrm
,
885 if (size
> (int)rstrm
->recvsize
) /* recvsize guaranteed < INT_MAX */
887 buf
= realloc (rstrm
->in_buffer
, (size_t) (size
+ BYTES_PER_XDR_UNIT
));
891 (long) buf_algn
% BYTES_PER_XDR_UNIT
!= 0; buf_algn
++)
893 diff
= buf_algn
- rstrm
->in_base
;
894 rstrm
->in_finger
+= diff
;
895 rstrm
->in_base
= buf_algn
;
896 rstrm
->in_buffer
= buf
;
897 rstrm
->in_boundry
= buf_algn
+ size
;
898 rstrm
->recvsize
= size
;
899 rstrm
->in_size
= size
;