source: rtems/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c @ 92ba0a51

4.104.114.95
Last change on this file since 92ba0a51 was 92ba0a51, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/04/08 at 08:15:10

Stop using old-style definitions.

  • Property mode set to 100644
File size: 11.2 KB
Line 
1/* $Id$ */
2
3/* xdr_mbuf is derived from xdr_mem */
4
5/* Author (mbuf specifica): Till Straumann <strauman@slac.stanford.edu>, 10/2002 */
6
7/*
8 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
9 * unrestricted use provided that this legend is included on all tape
10 * media and as a part of the software program in whole or part.  Users
11 * may copy or modify Sun RPC without charge, but are not authorized
12 * to license or distribute it to anyone else except as part of a product or
13 * program developed by the user.
14 *
15 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
16 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
18 *
19 * Sun RPC is provided with no support and without any obligation on the
20 * part of Sun Microsystems, Inc. to assist in its use, correction,
21 * modification or enhancement.
22 *
23 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
24 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
25 * OR ANY PART THEREOF.
26 *
27 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
28 * or profits or other special, indirect and consequential damages, even if
29 * Sun has been advised of the possibility of such damages.
30 *
31 * Sun Microsystems, Inc.
32 * 2550 Garcia Avenue
33 * Mountain View, California  94043
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
38/*static char *sccsid = "from: @(#)xdr_mem.c    2.1 88/07/29 4.0 RPCSRC";*/
39static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8 1999/08/28 00:02:56 peter Exp $";
40#endif
41
42/*
43 * xdr_mbuf,  XDR implementation using mbuf buffers
44 *
45 * derived from:
46 *
47 * xdr_mem.h, XDR implementation using memory buffers.
48 *
49 * Copyright (C) 1984, Sun Microsystems, Inc.
50 *
51 * The MBUF stream is useful for BSDNET kernel (or RTEMS for that matter)
52 * use.
53 */
54
55#include <string.h>
56#include <rpc/types.h>
57#include <rpc/xdr.h>
58#include <netinet/in.h>
59
60#include <stdlib.h>
61
62#define TODO
63
64/* TODO remove: a hack because malloc is redefined */
65#ifdef TODO
66static inline void *
67my_malloc(size_t i)
68{
69        return malloc(i);
70}
71
72static inline void
73my_free(void *p)
74{
75        return free(p);
76}
77#endif
78
79#define DEBUG_ASSERT    (1<<0)
80#define DEBUG_VERB              (1<<1)
81
82#define DEBUG                   DEBUG_ASSERT
83
84#define KERNEL
85#include <sys/mbuf.h>
86
87#include <assert.h>
88
89#if DEBUG & DEBUG_VERB || defined(TODO)
90#include <stdio.h>
91#endif
92
93static bool_t   xdrmbuf_getlong_aligned(XDR *xdrs, long *lp);
94static bool_t   xdrmbuf_putlong_aligned(XDR *xdrs, const long *lp);
95static bool_t   xdrmbuf_getlong_unaligned(XDR *xdrs, long *lp);
96static bool_t   xdrmbuf_putlong_unaligned(XDR *xdrs, const long *lp);
97static bool_t   xdrmbuf_getbytes(XDR *xdrs, caddr_t addr, u_int len);
98static bool_t   xdrmbuf_putbytes(XDR *xdrs, const char *addr, u_int len);
99static u_int    xdrmbuf_getpos(XDR *xdrs); /* XXX w/64-bit pointers, u_int not enough! */
100static bool_t   xdrmbuf_setpos(XDR *xdrs, u_int pos);
101static int32_t *xdrmbuf_inline_aligned(XDR *xdrs, u_int len);
102static int32_t *xdrmbuf_inline_unaligned(XDR *xdrs, u_int len);
103static void     xdrmbuf_destroy(XDR *);
104
105static struct   xdr_ops xdrmbuf_ops_aligned = {
106        xdrmbuf_getlong_aligned,
107        xdrmbuf_putlong_aligned,
108        xdrmbuf_getbytes,
109        xdrmbuf_putbytes,
110        xdrmbuf_getpos,
111        xdrmbuf_setpos,
112        xdrmbuf_inline_aligned,
113        xdrmbuf_destroy
114};
115
116static struct   xdr_ops xdrmbuf_ops_unaligned = {
117        xdrmbuf_getlong_unaligned,
118        xdrmbuf_putlong_unaligned,
119        xdrmbuf_getbytes,
120        xdrmbuf_putbytes,
121        xdrmbuf_getpos,
122        xdrmbuf_setpos,
123        xdrmbuf_inline_unaligned,
124        xdrmbuf_destroy
125};
126
127typedef struct MBPrivateRec_ {
128        struct mbuf             *mchain;
129        struct mbuf             *mcurrent;
130        u_int                   pos;            /* number of bytes contained in all MUBFS ahead
131                                                                 * of mcurrent
132                                                                 */
133} MBPrivateRec, *MBPrivate;
134
135/* NOTE: the stream position helper 'pos'
136 *       must be managed by the caller!
137 */
138static inline void
139xdrmbuf_setup(XDR *xdrs, struct mbuf *m)
140{
141MBPrivate       mbp = (MBPrivate)xdrs->x_base;
142
143                mbp->mcurrent    = m;
144                xdrs->x_private  = mtod(m,caddr_t);
145                xdrs->x_handy    = m->m_len;
146                xdrs->x_ops      = ((size_t)xdrs->x_private & (sizeof(int32_t) - 1))
147                                                                ? &xdrmbuf_ops_unaligned : &xdrmbuf_ops_aligned;
148}
149
150static struct mbuf *
151xdrmbuf_next(XDR *xdrs)
152{
153struct mbuf             *rval;
154MBPrivate               mbp = (MBPrivate)xdrs->x_base;
155
156        if (mbp->mcurrent) {
157                mbp->pos += mbp->mcurrent->m_len;
158                rval      = mbp->mcurrent->m_next;
159        } else {
160                rval      = 0;
161        }
162
163        if (rval) {
164                xdrmbuf_setup(xdrs, rval);
165        }
166#if DEBUG & DEBUG_VERB
167        else {
168                fprintf(stderr,"xdrmbuf: end of chain\n");
169        }
170#endif
171       
172        return rval;
173}
174
175/*
176 * The procedure xdrmbuf_create initializes a stream descriptor for a
177 * memory buffer.
178 */
179void
180xdrmbuf_create(XDR *xdrs, struct mbuf *mbuf, enum xdr_op op)
181{
182MBPrivate mbp;
183
184        xdrs->x_op = op;
185        assert( mbp = (MBPrivate)my_malloc(sizeof(*mbp)) );
186        xdrs->x_base  = (caddr_t) mbp;
187
188        mbp->mchain   = mbuf;
189        mbp->pos      = 0;
190
191#if DEBUG & DEBUG_VERB
192        {
193        struct mbuf *mbf;
194        fprintf(stderr,"Dumping chain:\n");
195        for (mbf = mbuf; mbf; mbf=mbf->m_next) {
196                int ii;
197                fprintf(stderr,"MBUF------------");
198                for (ii=0; ii<mbf->m_len; ii++) {
199                        fprintf(stderr,"%02x ",mtod(mbf,char*)[ii]);
200                        if (ii%16==0)
201                                fputc('\n',stderr);
202                }
203                fputc('\n',stderr);
204        }
205        }
206#endif
207
208        xdrmbuf_setup(xdrs, mbuf);
209}
210
211static void
212xdrmbuf_destroy(XDR *xdrs)
213{
214MBPrivate       mbp = (MBPrivate)xdrs->x_base;
215#if 0 /* leave destroying the chain to the user */
216struct mbuf *m = mbp->mchain;
217
218        rtems_bsdnet_semaphore_obtain();
219                m_freem(m);
220        rtems_bsdnet_semaphore_release();
221#endif
222
223        my_free(mbp);
224}
225
226static bool_t
227xdrmbuf_getlong_aligned(register XDR *xdrs, register long *lp)
228{
229        while ( (signed int)(xdrs->x_handy -= sizeof(int32_t)) < 0) {
230                if ((xdrs->x_handy += sizeof(int32_t)) == 0) {
231                        /* handy was 0 on entry; request a new buffer.
232                         * Coded this way, so the most frequently executed
233                         * path needs only one comparison...
234                         */
235                        if (!xdrmbuf_next(xdrs))
236                                return FALSE;
237                } else {
238                        /* uh-oh an aligned long spread over two MBUFS ??
239                         * let the unaligned handler deal with this rare
240                         * situation.
241                         */
242                        return xdrmbuf_getlong_unaligned(xdrs,lp);
243                }
244        }
245        *lp = ntohl(*(int32_t *)(xdrs->x_private));
246        xdrs->x_private += sizeof(int32_t);
247#if DEBUG & DEBUG_VERB
248        fprintf(stderr,"Got aligned long %x\n",*lp);
249#endif
250        return (TRUE);
251}
252
253static bool_t
254xdrmbuf_putlong_aligned(
255        XDR *xdrs,
256        const long *lp)
257{
258fprintf(stderr,"TODO: xdrmbuf_putlong_aligned() is unimplemented\n");
259        return FALSE;
260#if 0
261        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
262                return (FALSE);
263        *(int32_t *)xdrs->x_private = htonl(*lp);
264        xdrs->x_private += sizeof(int32_t);
265        return (TRUE);
266#endif
267}
268
269static bool_t
270xdrmbuf_getlong_unaligned(
271        XDR *xdrs,
272        long *lp)
273{
274union {
275        int32_t l;
276        char    c[sizeof(int32_t)];
277}       u;
278
279register int  i,j;
280register char *cp,*sp;
281
282        i = xdrs->x_handy - sizeof(int32_t);
283
284        /* handle the most common case first */
285        if ( i >= 0 ) {
286
287                xdrs->x_handy   = i;
288                sp                          = (char*)xdrs->x_private;
289                xdrs->x_private = sp + sizeof(int32_t);
290
291#ifdef CANDO_UNALIGNED
292                {
293                        *lp              = ntohl(*(int32_t *)sp);
294#        if DEBUG & DEBUG_VERB
295                        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
296#        endif
297                        return TRUE;
298                }
299#else   /* machine can't do unaligned access */
300                {
301                        u.c[0]          = *sp;
302                        u.c[1]          = *++sp;
303                        u.c[2]          = *++sp;
304                        u.c[3]          = *++sp;
305
306                        goto done;
307                }
308#endif /* CANDO_UNALIGNED */
309        }
310
311        /* here the messy 'crossing buffers' business starts */
312
313
314        j  = sizeof(int32_t);
315
316        cp = u.c-1;
317
318        /* NOTE: on entry to this section,  handy < j holds */
319        do {
320                sp = ((char*)xdrs->x_private)-1;
321
322                if ( (i=xdrs->x_handy) >= j ) {
323                        /* more data in the buffer than we need:
324                         * copy everything we need and goto 'done'
325                         */
326                        xdrs->x_handy    = i-j;
327                        do {
328                                *++cp = *++sp;
329                        } while (--j > 0);
330                        xdrs->x_private  = (caddr_t)++sp;
331
332                        goto done;
333
334                } else {
335                        /* not enough data - copy as much as possible
336                         * then get retrieve the next MBUF and start
337                         * over
338                         */
339                        j-=i;
340                        while (i--)
341                                *++cp = *++sp;
342                        if (!xdrmbuf_next(xdrs))
343                                return FALSE;
344#if DEBUG & DEBUG_VERB
345                        fprintf(stderr,"getlong_unaligned: crossed mbuf boundary\n");
346#endif
347                }
348        } while (j > 0);
349
350done:
351
352        *lp = ntohl(u.l);
353
354#if DEBUG & DEBUG_VERB
355        fprintf(stderr,"Got unaligned long %x (%i remaining)\n",*lp, xdrs->x_handy);
356#endif
357        return (TRUE);
358}
359
360static bool_t
361xdrmbuf_putlong_unaligned(
362        XDR *xdrs,
363        const long *lp )
364{
365
366        fprintf(stderr,"TODO: xdrmbuf_putlong_unaligned() is unimplemented\n");
367        return FALSE;
368#if 0
369        {
370        int32_t l;
371
372        if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
373                return (FALSE);
374        l = htonl(*lp);
375        memcpy(xdrs->x_private, &l, sizeof(int32_t));
376        xdrs->x_private += sizeof(int32_t);
377        return (TRUE);
378        }
379#endif
380}
381
382static bool_t
383xdrmbuf_getbytes(
384        XDR *xdrs,
385        caddr_t addr,
386        u_int len)
387{
388#if DEBUG & DEBUG_VERB
389int     olen=len,bufs=0;
390#endif
391
392#if DEBUG & DEBUG_VERB
393        fprintf(stderr,"wanting %i bytes (have %i)\n",olen,xdrs->x_handy);
394#endif
395
396        while (len>0) {
397                if (xdrs->x_handy >= len) {
398                        memcpy(addr, xdrs->x_private, len);
399                        xdrs->x_private += len;
400                        xdrs->x_handy   -= len;
401#if 0 /* save a couple of instructions */
402                        len = 0;
403#else
404                        goto done;
405#endif
406                } else {
407                        if (xdrs->x_handy > 0) {
408                                memcpy(addr, xdrs->x_private, xdrs->x_handy);
409                                len  -= xdrs->x_handy;
410                                addr += xdrs->x_handy;
411                        }
412                        if (!xdrmbuf_next(xdrs))
413                                return FALSE;
414#if DEBUG & DEBUG_VERB
415                        bufs++;
416#endif
417                }
418        }
419done:
420#if DEBUG & DEBUG_VERB
421        fprintf(stderr,"Got %i bytes (out of %i mbufs)\n",olen,bufs);
422#endif
423        return (TRUE);
424}
425
426static bool_t
427xdrmbuf_putbytes(
428        XDR *xdrs,
429        const char *addr,
430        u_int len )
431{
432
433        fprintf(stderr,"TODO: xdrmbuf_putbytes() is unimplemented\n");
434        return FALSE;
435#if 0
436        if ((xdrs->x_handy -= len) < 0)
437                return (FALSE);
438        memcpy(xdrs->x_private, addr, len);
439        xdrs->x_private += len;
440        return (TRUE);
441#endif
442}
443
444static u_int
445xdrmbuf_getpos(
446        XDR *xdrs)
447{
448#if 1
449MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
450struct mbuf *m   = mbp->mcurrent;
451u_int       rval = mbp->pos;
452
453        if (m) {
454                rval += (u_long)xdrs->x_private - mtod(m, u_long);
455        }
456#else
457struct mbuf *m;
458u_int           rval = 0;
459MBPrivate       mbp  = (MBPrivate)xdrs->x_base;
460
461        for ( m = mbp->mchain; m && m != mbp->mcurrent; m = m->m_next )
462                rval += m->m_len;
463        if (m) {
464                rval += (u_long)xdrs->x_private - mtod(m, u_long);
465        }
466
467#endif
468        return rval;
469}
470
471static bool_t
472xdrmbuf_setpos(
473        XDR *xdrs,
474        u_int pos)
475{
476struct          mbuf *m;
477MBPrivate       mbp   = (MBPrivate)xdrs->x_base;
478
479        if (pos >= mbp->pos) {
480                pos      -= mbp->pos;
481                m         = mbp->mcurrent;
482        } else {
483                m         = mbp->mchain;
484                mbp->pos  = 0;
485        }
486
487        while ( m && pos >= m->m_len ) {
488                pos      -= m->m_len;
489                mbp->pos += m->m_len;
490                m         = m->m_next;
491        }
492
493        if (m) {
494                xdrmbuf_setup(xdrs, m);
495                xdrs->x_private += pos;
496                return TRUE;
497        }
498
499        return 0 == pos ? TRUE : FALSE;
500}
501
502static int32_t *
503xdrmbuf_inline_aligned(
504        XDR *xdrs,
505        u_int len)
506{
507int32_t *buf = 0;
508
509        if (xdrs->x_handy == 0 && !xdrmbuf_next(xdrs))
510                return 0;
511
512        if (xdrs->x_handy >= len) {
513                xdrs->x_handy -= len;
514                buf = (int32_t *) xdrs->x_private;
515                xdrs->x_private += len;
516#if DEBUG & DEBUG_VERB
517                fprintf(stderr,"Got %i aligned inline bytes at %x\n", len, buf);
518#endif
519        }
520#if DEBUG & DEBUG_VERB
521        else {
522                fprintf(stderr,"Skipped %i aligned inline bytes\n",len);
523        }
524#endif
525        return (buf);
526}
527
528static int32_t *
529xdrmbuf_inline_unaligned(
530        XDR *xdrs,
531        u_int len )
532{
533        return (0);
534}
Note: See TracBrowser for help on using the repository browser.