00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #if !defined(lint) && defined(SCCSIDS)
00042 static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
00043 #endif
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #if !defined(UNDER_CE) && !defined(WINDOWS_CE)
00063 #include <stdio.h>
00064 #endif
00065
00066 #include "xdr.h"
00067
00068 #ifdef WIN32
00069 #include <io.h>
00070 #else
00071 #include <netinet/in.h>
00072
00073 extern long lseek();
00074 #endif
00075
00076 static u_int fix_buf_size();
00077
00078 static bool_t xdrrec_getlong();
00079 static bool_t xdrrec_putlong();
00080 static bool_t xdrrec_getbytes();
00081 static bool_t xdrrec_putbytes();
00082 static u_int xdrrec_getpos();
00083 static bool_t xdrrec_setpos();
00084 static long * xdrrec_inline();
00085 static void xdrrec_destroy();
00086
00087 static struct xdr_ops xdrrec_ops = {
00088 xdrrec_getlong,
00089 xdrrec_putlong,
00090 xdrrec_getbytes,
00091 xdrrec_putbytes,
00092 xdrrec_getpos,
00093 xdrrec_setpos,
00094 xdrrec_inline,
00095 xdrrec_destroy
00096 };
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #define LAST_FRAG ((u_long)(1 << 31))
00112
00113 typedef struct rec_strm {
00114 caddr_t tcp_handle;
00115 caddr_t the_buffer;
00116
00117
00118
00119 int (*writeit)();
00120 caddr_t out_base;
00121 caddr_t out_finger;
00122 caddr_t out_boundry;
00123 u_long *frag_header;
00124 bool_t frag_sent;
00125
00126
00127
00128 int (*readit)();
00129 u_long in_size;
00130 caddr_t in_base;
00131 caddr_t in_finger;
00132 caddr_t in_boundry;
00133 long fbtbc;
00134 bool_t last_frag;
00135 u_int sendsize;
00136 u_int recvsize;
00137 } RECSTREAM;
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 void
00150 xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
00151 register XDR *xdrs;
00152 register u_int sendsize;
00153 register u_int recvsize;
00154 caddr_t tcp_handle;
00155 int (*readit)();
00156 int (*writeit)();
00157 {
00158 register RECSTREAM *rstrm =
00159 (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
00160
00161 if (rstrm == NULL) {
00162 #if !defined(UNDER_CE) && !defined(WINDOWS_CE)
00163 #ifdef WIN32
00164 nt_rpc_report("xdrrec_create: out of memory\n");
00165 #else
00166 (void)fprintf(stderr, "xdrrec_create: out of memory\n");
00167 #endif
00168 #endif
00169
00170
00171
00172
00173 return;
00174 }
00175
00176
00177
00178 rstrm->sendsize = sendsize = fix_buf_size(sendsize);
00179 rstrm->recvsize = recvsize = fix_buf_size(recvsize);
00180 rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
00181 if (rstrm->the_buffer == NULL) {
00182 #if !defined(UNDER_CE) && !defined(WINDOWS_CE)
00183 #ifdef WIN32
00184 nt_rpc_report("xdrrec_create: out of memory\n");
00185 #else
00186 (void)fprintf(stderr, "xdrrec_create: out of memory\n");
00187 #endif
00188 #endif
00189 return;
00190 }
00191 for (rstrm->out_base = rstrm->the_buffer;
00192 (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
00193 rstrm->out_base++);
00194 rstrm->in_base = rstrm->out_base + sendsize;
00195
00196
00197
00198 xdrs->x_ops = &xdrrec_ops;
00199 xdrs->x_private = (caddr_t)rstrm;
00200 rstrm->tcp_handle = tcp_handle;
00201 rstrm->readit = readit;
00202 rstrm->writeit = writeit;
00203 rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
00204 rstrm->frag_header = (u_long *)rstrm->out_base;
00205 rstrm->out_finger += sizeof(u_long);
00206 rstrm->out_boundry += sendsize;
00207 rstrm->frag_sent = FALSE;
00208 rstrm->in_size = recvsize;
00209 rstrm->in_boundry = rstrm->in_base;
00210 rstrm->in_finger = (rstrm->in_boundry += recvsize);
00211 rstrm->fbtbc = 0;
00212 rstrm->last_frag = TRUE;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 static bool_t
00222 xdrrec_getlong(xdrs, lp)
00223 XDR *xdrs;
00224 long *lp;
00225 {
00226 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00227 register long *buflp = (long *)(rstrm->in_finger);
00228 long mylong;
00229
00230
00231 if ((rstrm->fbtbc >= sizeof(long)) &&
00232 (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) {
00233 *lp = (long)ntohl((u_long)(*buflp));
00234 rstrm->fbtbc -= sizeof(long);
00235 rstrm->in_finger += sizeof(long);
00236 } else {
00237 if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long)))
00238 return (FALSE);
00239 *lp = (long)ntohl((u_long)mylong);
00240 }
00241 return (TRUE);
00242 }
00243
00244 static bool_t
00245 xdrrec_putlong(xdrs, lp)
00246 XDR *xdrs;
00247 long *lp;
00248 {
00249 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00250 register long *dest_lp = ((long *)(rstrm->out_finger));
00251
00252 if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
00253
00254
00255
00256
00257 rstrm->out_finger -= sizeof(long);
00258 rstrm->frag_sent = TRUE;
00259 if (! flush_out(rstrm, FALSE))
00260 return (FALSE);
00261 dest_lp = ((long *)(rstrm->out_finger));
00262 rstrm->out_finger += sizeof(long);
00263 }
00264 *dest_lp = (long)htonl((u_long)(*lp));
00265 return (TRUE);
00266 }
00267
00268 static bool_t
00269 xdrrec_getbytes(xdrs, addr, len)
00270 XDR *xdrs;
00271 register caddr_t addr;
00272 register u_int len;
00273 {
00274 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00275 register int current;
00276
00277 while (len > 0) {
00278 current = rstrm->fbtbc;
00279 if (current == 0) {
00280 if (rstrm->last_frag)
00281 return (FALSE);
00282 if (! set_input_fragment(rstrm))
00283 return (FALSE);
00284 continue;
00285 }
00286 current = (len < current) ? len : current;
00287 if (! get_input_bytes(rstrm, addr, current))
00288 return (FALSE);
00289 addr += current;
00290 rstrm->fbtbc -= current;
00291 len -= current;
00292 }
00293 return (TRUE);
00294 }
00295
00296 static bool_t
00297 xdrrec_putbytes(xdrs, addr, len)
00298 XDR *xdrs;
00299 register caddr_t addr;
00300 register u_int len;
00301 {
00302 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00303 register int current;
00304
00305 while (len > 0) {
00306 current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger;
00307 current = (len < current) ? len : current;
00308 bcopy(addr, rstrm->out_finger, current);
00309 rstrm->out_finger += current;
00310 addr += current;
00311 len -= current;
00312 if (rstrm->out_finger == rstrm->out_boundry) {
00313 rstrm->frag_sent = TRUE;
00314 if (! flush_out(rstrm, FALSE))
00315 return (FALSE);
00316 }
00317 }
00318 return (TRUE);
00319 }
00320
00321 static u_int
00322 xdrrec_getpos(xdrs)
00323 register XDR *xdrs;
00324 {
00325 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
00326 register long pos;
00327
00328 pos = lseek((int)rstrm->tcp_handle, (long) 0, 1);
00329 if (pos != -1)
00330 switch (xdrs->x_op) {
00331
00332 case XDR_ENCODE:
00333 pos += rstrm->out_finger - rstrm->out_base;
00334 break;
00335
00336 case XDR_DECODE:
00337 pos -= rstrm->in_boundry - rstrm->in_finger;
00338 break;
00339
00340 default:
00341 pos = (u_int) -1;
00342 break;
00343 }
00344 return ((u_int) pos);
00345 }
00346
00347 static bool_t
00348 xdrrec_setpos(xdrs, pos)
00349 register XDR *xdrs;
00350 u_int pos;
00351 {
00352 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
00353 u_int currpos = xdrrec_getpos(xdrs);
00354 int delta = currpos - pos;
00355 caddr_t newpos;
00356
00357 if ((int)currpos != -1)
00358 switch (xdrs->x_op) {
00359
00360 case XDR_ENCODE:
00361 newpos = rstrm->out_finger - delta;
00362 if ((newpos > (caddr_t)(rstrm->frag_header)) &&
00363 (newpos < rstrm->out_boundry)) {
00364 rstrm->out_finger = newpos;
00365 return (TRUE);
00366 }
00367 break;
00368
00369 case XDR_DECODE:
00370 newpos = rstrm->in_finger - delta;
00371 if ((delta < (int)(rstrm->fbtbc)) &&
00372 (newpos <= rstrm->in_boundry) &&
00373 (newpos >= rstrm->in_base)) {
00374 rstrm->in_finger = newpos;
00375 rstrm->fbtbc -= delta;
00376 return (TRUE);
00377 }
00378 break;
00379 }
00380 return (FALSE);
00381 }
00382
00383 static long *
00384 xdrrec_inline(xdrs, len)
00385 register XDR *xdrs;
00386 int len;
00387 {
00388 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
00389 long * buf = NULL;
00390
00391 switch (xdrs->x_op) {
00392
00393 case XDR_ENCODE:
00394 if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
00395 buf = (long *) rstrm->out_finger;
00396 rstrm->out_finger += len;
00397 }
00398 break;
00399
00400 case XDR_DECODE:
00401 if ((len <= rstrm->fbtbc) &&
00402 ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
00403 buf = (long *) rstrm->in_finger;
00404 rstrm->fbtbc -= len;
00405 rstrm->in_finger += len;
00406 }
00407 break;
00408 }
00409 return (buf);
00410 }
00411
00412 static void
00413 xdrrec_destroy(xdrs)
00414 register XDR *xdrs;
00415 {
00416 register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
00417
00418 mem_free(rstrm->the_buffer,
00419 rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
00420 mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 bool_t
00433 xdrrec_skiprecord(xdrs)
00434 XDR *xdrs;
00435 {
00436 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00437
00438 while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
00439 if (! skip_input_bytes(rstrm, rstrm->fbtbc))
00440 return (FALSE);
00441 rstrm->fbtbc = 0;
00442 if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
00443 return (FALSE);
00444 }
00445 rstrm->last_frag = FALSE;
00446 return (TRUE);
00447 }
00448
00449
00450
00451
00452
00453
00454 bool_t
00455 xdrrec_eof(xdrs)
00456 XDR *xdrs;
00457 {
00458 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00459
00460 while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
00461 if (! skip_input_bytes(rstrm, rstrm->fbtbc))
00462 return (TRUE);
00463 rstrm->fbtbc = 0;
00464 if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
00465 return (TRUE);
00466 }
00467 if (rstrm->in_finger == rstrm->in_boundry)
00468 return (TRUE);
00469 return (FALSE);
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 bool_t
00479 xdrrec_endofrecord(xdrs, sendnow)
00480 XDR *xdrs;
00481 bool_t sendnow;
00482 {
00483 register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
00484 register u_long len;
00485
00486 if (sendnow || rstrm->frag_sent ||
00487 ((u_long)rstrm->out_finger + sizeof(u_long) >=
00488 (u_long)rstrm->out_boundry)) {
00489 rstrm->frag_sent = FALSE;
00490 return (flush_out(rstrm, TRUE));
00491 }
00492 len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
00493 sizeof(u_long);
00494 *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
00495 rstrm->frag_header = (u_long *)rstrm->out_finger;
00496 rstrm->out_finger += sizeof(u_long);
00497 return (TRUE);
00498 }
00499
00500
00501
00502
00503
00504 static bool_t
00505 flush_out(rstrm, eor)
00506 register RECSTREAM *rstrm;
00507 bool_t eor;
00508 {
00509 register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
00510 register u_long len = (u_long)(rstrm->out_finger) -
00511 (u_long)(rstrm->frag_header) - sizeof(u_long);
00512
00513 *(rstrm->frag_header) = htonl(len | eormask);
00514 len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
00515 if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
00516 != (int)len)
00517 return (FALSE);
00518 rstrm->frag_header = (u_long *)rstrm->out_base;
00519 rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long);
00520 return (TRUE);
00521 }
00522
00523 static bool_t
00524 fill_input_buf(rstrm)
00525 register RECSTREAM *rstrm;
00526 {
00527 register caddr_t where;
00528 u_int i;
00529 register int len;
00530
00531 where = rstrm->in_base;
00532 i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
00533 where += i;
00534 len = rstrm->in_size - i;
00535 if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
00536 return (FALSE);
00537 rstrm->in_finger = where;
00538 where += len;
00539 rstrm->in_boundry = where;
00540 return (TRUE);
00541 }
00542
00543 static bool_t
00544 get_input_bytes(rstrm, addr, len)
00545 register RECSTREAM *rstrm;
00546 register caddr_t addr;
00547 register int len;
00548 {
00549 register int current;
00550
00551 while (len > 0) {
00552 current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
00553 if (current == 0) {
00554 if (! fill_input_buf(rstrm))
00555 return (FALSE);
00556 continue;
00557 }
00558 current = (len < current) ? len : current;
00559 bcopy(rstrm->in_finger, addr, current);
00560 rstrm->in_finger += current;
00561 addr += current;
00562 len -= current;
00563 }
00564 return (TRUE);
00565 }
00566
00567 static bool_t
00568 set_input_fragment(rstrm)
00569 register RECSTREAM *rstrm;
00570 {
00571 u_long header;
00572
00573 if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
00574 return (FALSE);
00575 header = (long)ntohl(header);
00576 rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
00577 rstrm->fbtbc = header & (~LAST_FRAG);
00578 return (TRUE);
00579 }
00580
00581 static bool_t
00582 skip_input_bytes(rstrm, cnt)
00583 register RECSTREAM *rstrm;
00584 long cnt;
00585 {
00586 register int current;
00587
00588 while (cnt > 0) {
00589 current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
00590 if (current == 0) {
00591 if (! fill_input_buf(rstrm))
00592 return (FALSE);
00593 continue;
00594 }
00595 current = (cnt < current) ? cnt : current;
00596 rstrm->in_finger += current;
00597 cnt -= current;
00598 }
00599 return (TRUE);
00600 }
00601
00602 static u_int
00603 fix_buf_size(s)
00604 register u_int s;
00605 {
00606
00607 if (s < 100)
00608 s = 4000;
00609 return (RNDUP(s));
00610 }