xdr_rec.c revision ac9418faa9bc5d2e2b8fdb33f434b05183528026
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* layer above connection oriented transport layer (e.g. tcp) (for rpc's use).
*
*
* There is a record marking layer between the xdr stream
* and the (tcp) cv transport level. A record is composed on one or more
* record fragments. A record fragment is a thirty-two bit header followed
* by n bytes of data, where n is contained in the header. The header
* is represented as a htonl(ulong_t). The order bit encodes
* whether or not the fragment is the last fragment of the record
* (1 => fragment is last, 0 => more fragments to follow.
* The other 31 bits encode the byte length of the fragment.
*/
#include <stdio.h>
#include <syslog.h>
#include <memory.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include "rac_private.h"
/*
* A record is composed of one or more record fragments.
* A record fragment is a four-byte header followed by zero to
* 2**32-1 bytes. The header is treated as a long unsigned and is
* are a byte count of the fragment. The highest order bit is a boolean:
* 1 => this fragment is the last fragment of the record,
* 0 => this fragment is followed by more fragment(s).
*
* meet the needs of xdr and rpc based on tcp.
*/
typedef struct rec_strm {
/*
* out-going bits
*/
/*
* in-coming bits
*/
int fbtbc; /* fragment bytes to be consumed */
} RECSTREAM;
static struct xdr_ops *xdrrec_ops(void);
/*
* Create an xdr handle for xdrrec
* xdrrec_create fills in xdrs. Sendsize and recvsize are
* send and recv buffer sizes (0 => use default).
* vc_handle is an opaque handle that is passed as the first parameter to
* the procedures readit and writeit. Readit and writeit are read and
* write respectively. They are like the system calls expect that they
* take an opaque handle rather than an fd.
*/
static const char mem_err_msg_rec[] = "xdrrec_create: out of memory";
void
const caddr_t tcp_handle,
{
/*
* XXX: This is bad. Should rework xdrrec_create to
* return a handle, and in this case return NULL
*/
return;
}
/*
* adjust sizes and allocate buffer quad byte aligned
*/
return;
}
/*
* now the rest ...
*/
}
/*
* The routines defined below are the xdr ops which will go into the
* xdr handle filled in by xdrrec_create.
*/
static bool_t
{
/* first try the inline, fast case */
sizeof (int32_t))) {
} else {
sizeof (int32_t)))
return (FALSE);
}
return (TRUE);
}
static bool_t
{
/*
* this case should almost never happen so the code is
* inefficient
*/
return (FALSE);
}
return (TRUE);
}
static bool_t
{
int32_t i;
*lp = (long)i;
return (ret);
}
static bool_t
{
int32_t i;
#if defined(_LP64)
return (FALSE);
}
#endif
return (xdrrec_putint32(xdrs, &i));
}
static bool_t /* must manage buffers, fragments, and records */
{
int current;
while (len > 0) {
if (current == 0) {
return (FALSE);
if (!set_input_fragment(rstrm))
return (FALSE);
continue;
}
return (FALSE);
}
return (TRUE);
}
static bool_t
{
int current;
while (len > 0) {
return (FALSE);
}
}
return (TRUE);
}
/*
* This is just like the ops vector x_getbytes(), except that
* instead of returning success or failure on getting a certain number
* of bytes, it behaves much more like the read() system call against a
* pipe -- it returns up to the number of bytes requested and a return of
* zero indicates end-of-record. A -1 means something very bad happened.
*/
uint_t /* must manage buffers, fragments, and records */
{
len = l;
while (len > 0) {
if (current == 0) {
return (l - len);
if (!set_input_fragment(rstrm))
return ((uint_t)-1);
continue;
}
return ((uint_t)-1);
}
return (l - len);
}
static uint_t
{
int pos;
if (pos != -1)
case XDR_ENCODE:
break;
case XDR_DECODE:
break;
default:
break;
}
}
static bool_t
{
if ((int)currpos != -1)
case XDR_ENCODE:
return (TRUE);
}
break;
case XDR_DECODE:
return (TRUE);
}
break;
}
return (FALSE);
}
static rpc_inline_t *
{
case XDR_ENCODE:
}
break;
case XDR_DECODE:
}
break;
}
return (buf);
}
static void
{
}
/*
* Exported routines to manage xdr records
*/
/*
* Before reading (deserializing) from the stream, one should always call
* this procedure to guarantee proper record alignment.
*/
{
return (FALSE);
return (FALSE);
}
return (TRUE);
}
/*
* Look ahead fuction.
* Returns TRUE iff there is no more input in the buffer
* after consuming the rest of the current record.
*/
{
return (TRUE);
return (TRUE);
}
return (TRUE);
return (FALSE);
}
/*
* The client must tell the package when an end-of-record has occurred.
* The second parameters tells whether the record should be flushed to the
* (output) tcp stream. (This let's the package support batched or
* pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
*/
{
}
sizeof (uint_t);
return (TRUE);
}
void
{
}
/*
* Internal useful routines
*/
static bool_t
{
!= (int)len)
return (FALSE);
return (TRUE);
}
/* knows nothing about records! Only about input buffers */
static bool_t
{
uint_t i;
int len;
where += i;
return (FALSE);
return (TRUE);
}
/* knows nothing about records! Only about input buffers */
static bool_t
{
int current;
while (len > 0) {
if (current == 0) {
if (!fill_input_buf(rstrm))
return (FALSE);
continue;
}
}
return (TRUE);
}
/* next two bytes of the input stream are treated as a header */
static bool_t
{
return (FALSE);
return (TRUE);
}
/* consumes input bytes; knows nothing about records! */
static bool_t
{
int current;
while (cnt > 0) {
if (current == 0) {
if (!fill_input_buf(rstrm))
return (FALSE);
continue;
}
}
return (TRUE);
}
static uint_t
{
if (s < 100)
s = 4000;
return (RNDUP(s));
}
static struct xdr_ops *
xdrrec_ops(void)
{
#if defined(_LP64)
#endif
}
return (&ops);
}