source: rtems/cpukit/libfs/src/nfsclient/src/xdr_mbuf.c @ 4e59276

4.115
Last change on this file since 4e59276 was 4e59276, checked in by Mathew Kallada <matkallada@…>, on 12/28/12 at 14:05:20

libfs: Doxygen Enhancement Task #5

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