home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ldapsdk.zip / src / sockbuf.c < prev    next >
C/C++ Source or Header  |  2001-11-13  |  17KB  |  884 lines

  1. /* sockbuf.c - i/o routines with support for adding i/o layers. */
  2. /* $OpenLDAP: pkg/ldap/libraries/liblber/sockbuf.c,v 1.22.2.10 2001/05/06 19:53:58 kurt Exp $ */
  3. /*
  4.  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
  5.  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  6.  */
  7.  
  8. #include "portable.h"
  9.  
  10. #include <stdio.h>
  11.  
  12. #include <ac/stdlib.h>
  13.  
  14. #include <ac/ctype.h>
  15. #include <ac/errno.h>
  16. #include <ac/socket.h>
  17. #include <ac/string.h>
  18. #include <ac/unistd.h>
  19.  
  20. #ifdef HAVE_IO_H
  21. #include <io.h>
  22. #endif /* HAVE_IO_H */
  23.  
  24. #if defined( HAVE_FCNTL_H )
  25. #include <fcntl.h>
  26. #endif
  27.  
  28. #if defined( HAVE_SYS_FILIO_H )
  29. #include <sys/filio.h>
  30. #elif defined( HAVE_SYS_IOCTL_H )
  31. #include <sys/ioctl.h>
  32. #endif
  33.  
  34. #include "lber-int.h"
  35.  
  36. #define MIN_BUFF_SIZE        4096
  37. #define MAX_BUFF_SIZE        65536
  38. #define DEFAULT_READAHEAD    16384
  39.  
  40. Sockbuf *
  41. ber_sockbuf_alloc( void )
  42. {
  43.     Sockbuf            *sb;
  44.  
  45.     ber_int_options.lbo_valid = LBER_INITIALIZED;
  46.  
  47.     sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
  48.  
  49.     if( sb == NULL ) return NULL;
  50.  
  51.     ber_int_sb_init( sb );
  52.     return sb;
  53. }
  54.  
  55. void
  56. ber_sockbuf_free( Sockbuf *sb )
  57. {
  58.     assert( sb != NULL );
  59.     assert( SOCKBUF_VALID( sb ) );
  60.  
  61.     ber_int_sb_close( sb );
  62.     ber_int_sb_destroy( sb );
  63.     LBER_FREE( sb );
  64. }
  65.  
  66. /* Return values: -1: error, 0: no operation performed or the answer is false,
  67.  * 1: successful operation or the answer is true
  68.  */
  69. int
  70. ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
  71. {
  72.     Sockbuf_IO_Desc        *p;
  73.     int            ret = 0;
  74.  
  75.     assert( sb != NULL );
  76.     assert( SOCKBUF_VALID( sb ) );
  77.  
  78.     switch ( opt ) {
  79.         case LBER_SB_OPT_HAS_IO:
  80.             p = sb->sb_iod;
  81.             while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
  82.                 p = p->sbiod_next;
  83.             }
  84.    
  85.             if ( p ) {
  86.                 ret = 1;
  87.             }
  88.             break;
  89.  
  90.         case LBER_SB_OPT_GET_FD:
  91.             if ( arg != NULL ) {
  92.                 *((int *)arg) = sb->sb_fd;
  93.             }
  94.             ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
  95.             break;
  96.  
  97.         case LBER_SB_OPT_SET_FD:
  98.             sb->sb_fd = *((int *)arg);
  99.             ret = 1;
  100.             break;
  101.  
  102.         case LBER_SB_OPT_SET_NONBLOCK:
  103.             ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
  104.                 ? -1 : 1;
  105.             break;
  106.  
  107.         case LBER_SB_OPT_DRAIN: {
  108.                 /* Drain the data source to enable possible errors (e.g.
  109.                  * TLS) to be propagated to the upper layers
  110.                  */
  111.                 char buf[MIN_BUFF_SIZE];
  112.  
  113.                 do {
  114.                     ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
  115.                 } while ( ret == sizeof( buf ) );
  116.  
  117.                 ret = 1;
  118.             } break;
  119.  
  120.         case LBER_SB_OPT_NEEDS_READ:
  121.             ret = ( sb->sb_trans_needs_read ? 1 : 0 );
  122.             break;
  123.  
  124.         case LBER_SB_OPT_NEEDS_WRITE:
  125.             ret = ( sb->sb_trans_needs_write ? 1 : 0 );
  126.             break;
  127.  
  128.         case LBER_SB_OPT_GET_MAX_INCOMING:
  129.             if ( arg != NULL ) {
  130.                 *((ber_len_t *)arg) = sb->sb_max_incoming;
  131.             }
  132.             ret = 1;
  133.             break;
  134.  
  135.         case LBER_SB_OPT_SET_MAX_INCOMING:
  136.             sb->sb_max_incoming = *((ber_len_t *)arg);
  137.             ret = 1;
  138.             break;
  139.  
  140.         default:
  141.             ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
  142.                 opt, arg );
  143.             break;
  144.    }
  145.  
  146.     return ret;
  147. }
  148.  
  149. int
  150. ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
  151. {
  152.     Sockbuf_IO_Desc        *d, *p, **q;
  153.    
  154.     assert( sb != NULL );
  155.     assert( SOCKBUF_VALID( sb ) );
  156.    
  157.     if ( sbio == NULL ) {
  158.         return -1;
  159.     }
  160.    
  161.     q = &sb->sb_iod;
  162.     p = *q;
  163.     while ( p && p->sbiod_level > layer ) {
  164.         q = &p->sbiod_next;
  165.         p = *q;
  166.     }
  167.    
  168.     d = LBER_MALLOC( sizeof( *d ) );
  169.     if ( d == NULL ) {
  170.         return -1;
  171.     }
  172.    
  173.     d->sbiod_level = layer;
  174.     d->sbiod_sb = sb;
  175.     d->sbiod_io = sbio;
  176.     memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
  177.     d->sbiod_next = p;
  178.     *q = d;
  179.       
  180.     if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
  181.         return -1;
  182.     }
  183.       
  184.     return 0;
  185. }
  186.    
  187. int
  188. ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
  189. {
  190.     Sockbuf_IO_Desc        *p, **q;
  191.  
  192.     assert( sb != NULL );
  193.     assert( SOCKBUF_VALID( sb ) );
  194.    
  195.     if ( sb->sb_iod == NULL ) {
  196.         return -1;
  197.     }
  198.    
  199.     q = &sb->sb_iod;
  200.     while ( *q != NULL ) {
  201.         p = *q;
  202.         if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
  203.             if ( p->sbiod_io->sbi_remove != NULL &&
  204.                 p->sbiod_io->sbi_remove( p ) < 0 )
  205.             {
  206.                 return -1;
  207.             }
  208.             *q = p->sbiod_next;
  209.             LBER_FREE( p );
  210.         break;
  211.         }
  212.         q = &p->sbiod_next;
  213.     }
  214.  
  215.     return 0;
  216. }
  217.  
  218. void
  219. ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
  220. {
  221.     buf->buf_base = NULL;
  222.     buf->buf_ptr = 0;
  223.     buf->buf_end = 0;
  224.     buf->buf_size = 0;
  225. }
  226.  
  227. void
  228. ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
  229. {
  230.     assert( buf != NULL);
  231.  
  232.     if (buf->buf_base) {
  233.         LBER_FREE( buf->buf_base );
  234.     }
  235.     ber_pvt_sb_buf_init( buf );
  236. }
  237.  
  238. int
  239. ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
  240. {
  241.     ber_len_t        pw;
  242.     char            *p;
  243.    
  244.     assert( buf != NULL );
  245.  
  246.     for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
  247.         if (pw > MAX_BUFF_SIZE)
  248.       return -1;
  249.    }
  250.  
  251.     if ( buf->buf_size < pw ) {
  252.         p = LBER_REALLOC( buf->buf_base, pw );
  253.         if ( p == NULL )
  254.             return -1;
  255.         buf->buf_base = p;
  256.         buf->buf_size = pw;
  257.    }
  258.     return 0;
  259. }
  260.  
  261. ber_len_t
  262. ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
  263. {
  264.     ber_len_t        max;
  265.  
  266.     assert( buf != NULL );
  267.     assert( sbb != NULL );
  268. #if 0
  269.     assert( sbb->buf_size > 0 );
  270. #endif
  271.  
  272.     max = sbb->buf_end - sbb->buf_ptr;
  273.     max = ( max < len) ? max : len;
  274.     if ( max ) {
  275.         AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
  276.         sbb->buf_ptr += max;
  277.         if ( sbb->buf_ptr >= sbb->buf_end ) {
  278.             sbb->buf_ptr = sbb->buf_end = 0;
  279.         }
  280.    }
  281.     return max;
  282. }
  283.  
  284. ber_slen_t
  285. ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
  286. {
  287.     ber_len_t        to_go;
  288.     ber_slen_t ret;
  289.  
  290.     assert( sbiod != NULL );
  291.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  292.  
  293.     to_go = buf_out->buf_end - buf_out->buf_ptr;
  294.     assert( to_go > 0 );
  295.    
  296.     for(;;) {
  297.         ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
  298.             buf_out->buf_ptr, to_go );
  299. #ifdef EINTR
  300.         if ((ret<0) && (errno==EINTR)) continue;
  301. #endif
  302.         break;
  303.     }
  304.  
  305.     if ( ret <= 0 ) return ret;
  306.    
  307.     buf_out->buf_ptr += ret;
  308.     if (buf_out->buf_ptr == buf_out->buf_end) {
  309.         buf_out->buf_end = buf_out->buf_ptr = 0;
  310.     }
  311.  
  312.     if ( (ber_len_t)ret < to_go ) {
  313.         /* not enough data, so pretend no data was sent. */
  314.         return -1;
  315.     }
  316.  
  317.     return ret;
  318. }
  319.  
  320. int
  321. ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
  322. {
  323. #if HAVE_FCNTL
  324.     int flags = fcntl( sd, F_GETFL);
  325.     if( nb ) {
  326.         flags |= O_NONBLOCK;
  327.     } else {
  328.         flags &= ~O_NONBLOCK;
  329.     }
  330.     return fcntl( sd, F_SETFL, flags );
  331.         
  332. #elif defined( FIONBIO )
  333.     ioctl_t status = nb ? 1 : 0;
  334. #if defined(__OS2__) && defined(TCPV40HDRS)
  335.     return ioctl( sd, FIONBIO, (unsigned char *)&status, sizeof(status) );
  336. #else
  337.     return ioctl( sd, FIONBIO, &status );
  338. #endif
  339. #endif
  340. }
  341.  
  342. int
  343. ber_int_sb_init( Sockbuf *sb )
  344. {
  345.     assert( sb != NULL);
  346.  
  347.     sb->sb_valid=LBER_VALID_SOCKBUF;
  348.     sb->sb_options = 0;
  349.     sb->sb_debug = ber_int_debug;
  350.     sb->sb_fd = AC_SOCKET_INVALID;
  351.     sb->sb_iod = NULL;
  352.     sb->sb_trans_needs_read = 0;
  353.     sb->sb_trans_needs_write = 0;
  354.    
  355.     assert( SOCKBUF_VALID( sb ) );
  356.     return 0;
  357. }
  358.    
  359. int
  360. ber_int_sb_close( Sockbuf *sb )
  361. {
  362.     Sockbuf_IO_Desc        *p;
  363.  
  364.     assert( sb != NULL);
  365.    
  366.     p = sb->sb_iod;
  367.     while ( p ) {
  368.         if ( p->sbiod_io->sbi_close &&
  369.             p->sbiod_io->sbi_close( p ) < 0 )
  370.         {
  371.             return -1;
  372.         }
  373.         p = p->sbiod_next;
  374.     }
  375.    
  376.     sb->sb_fd = AC_SOCKET_INVALID;
  377.    
  378.     return 0;
  379. }
  380.  
  381. int
  382. ber_int_sb_destroy( Sockbuf *sb )
  383. {
  384.     Sockbuf_IO_Desc        *p;
  385.  
  386.     assert( sb != NULL);
  387.     assert( SOCKBUF_VALID( sb ) );
  388.    
  389.     while ( sb->sb_iod ) {
  390.         p = sb->sb_iod->sbiod_next;
  391.         ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
  392.             sb->sb_iod->sbiod_level );
  393.         sb->sb_iod = p;
  394.     }
  395.  
  396.     return ber_int_sb_init( sb );
  397. }
  398.  
  399. ber_slen_t
  400. ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
  401. {
  402.     ber_slen_t        ret;
  403.  
  404.     assert( buf != NULL );
  405.     assert( sb != NULL);
  406.     assert( sb->sb_iod != NULL );
  407.     assert( SOCKBUF_VALID( sb ) );
  408.  
  409.     for (;;) {
  410.         ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
  411.  
  412. #ifdef EINTR    
  413.         if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
  414. #endif
  415.         break;
  416.     }
  417.  
  418.     return ret;
  419. }
  420.  
  421. ber_slen_t
  422. ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
  423. {
  424.     ber_slen_t        ret;
  425.  
  426.     assert( buf != NULL );
  427.     assert( sb != NULL);
  428.     assert( sb->sb_iod != NULL );
  429.     assert( SOCKBUF_VALID( sb ) );
  430.  
  431.     for (;;) {
  432.         ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
  433.  
  434. #ifdef EINTR    
  435.         if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
  436. #endif
  437.         break;
  438.     }
  439.  
  440.     return ret;
  441. }
  442.  
  443. /*
  444.  * Support for TCP
  445.  */
  446.  
  447. static ber_slen_t
  448. sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  449. {
  450.     assert( sbiod != NULL);
  451.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  452.  
  453. #if defined(MACOS)
  454. /*
  455.  * MacTCP/OpenTransport
  456.  */
  457.     return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
  458.            len, NULL );
  459.  
  460. #elif defined( HAVE_PCNFS ) || \
  461.    defined( HAVE_WINSOCK ) || defined ( __BEOS__ ) || defined( __OS2__ )
  462. /*
  463.  * PCNFS (under DOS)
  464.  */
  465. /*
  466.  * Windows Socket API (under DOS/Windows 3.x)
  467.  */
  468. /*
  469.  * 32-bit Windows Socket API (under Windows NT or Windows 95)
  470.  */
  471.     {
  472.         int rc;
  473.  
  474.         rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
  475.  
  476. #ifdef HAVE_WINSOCK
  477.         if ( rc < 0 ) {
  478.             int err;
  479.  
  480.             err = WSAGetLastError();
  481.             errno = err;
  482.         }
  483. #endif
  484. #ifdef __OS2__
  485.         if ( rc < 0 ) {
  486.             int err;
  487.  
  488.             err = sock_errno();
  489.             errno = err;
  490.         }
  491. #endif
  492.  
  493.         return rc;
  494.     }
  495.  
  496. #elif defined( HAVE_NCSA )
  497. /*
  498.  * NCSA Telnet TCP/IP stack (under DOS)
  499.  */
  500.     return nread( sbiod->sbiod_sb->sb_fd, buf, len );
  501.  
  502. #else
  503.     return read( sbiod->sbiod_sb->sb_fd, buf, len );
  504. #endif
  505. }
  506.  
  507. static ber_slen_t
  508. sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  509. {
  510.     assert( sbiod != NULL);
  511.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  512.  
  513. #if defined(MACOS) 
  514. /*
  515.  * MacTCP/OpenTransport
  516.  */
  517. #define MAX_WRITE    65535
  518.     return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
  519.         (len<MAX_WRITE) ? len : MAX_WRITE );
  520.  
  521. #elif defined( HAVE_PCNFS) \
  522.     || defined( HAVE_WINSOCK) || defined ( __BEOS__ ) || defined( __OS2__ )
  523. /*
  524.  * PCNFS (under DOS)
  525.  */
  526. /*
  527.  * Windows Socket API (under DOS/Windows 3.x)
  528.  */
  529. /*
  530.  * 32-bit Windows Socket API (under Windows NT or Windows 95)
  531.  */
  532.     {
  533.         int rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
  534.  
  535. #ifdef HAVE_WINSOCK
  536.         if ( rc < 0 ) {
  537.             int err;
  538.             err = WSAGetLastError();
  539.             errno = err;
  540.         }
  541. #endif
  542. #ifdef __OS2__
  543.         if ( rc < 0 ) {
  544.             int err;
  545.             err = sock_errno();
  546.             errno = err;
  547.         }
  548. #endif
  549.         return rc;
  550.     }
  551.  
  552. #elif defined(HAVE_NCSA)
  553.     return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
  554.  
  555. #elif defined(VMS)
  556. /*
  557.  * VMS -- each write must be 64K or smaller
  558.  */
  559. #define MAX_WRITE 65535
  560.     return write( sbiod->sbiod_sb->sb_fd, buf,
  561.         (len<MAX_WRITE) ? len : MAX_WRITE);
  562. #else
  563.     return write( sbiod->sbiod_sb->sb_fd, buf, len );
  564. #endif   
  565. }   
  566.    
  567. static int 
  568. sb_stream_close( Sockbuf_IO_Desc *sbiod )
  569. {
  570.     assert( sbiod != NULL );
  571.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  572.     tcp_close( sbiod->sbiod_sb->sb_fd );
  573.    return 0;
  574. }
  575.  
  576. /* The argument is a pointer to the socket descriptor */
  577. static int
  578. sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
  579.     assert( sbiod != NULL );
  580.  
  581.     if ( arg != NULL ) {
  582.         sbiod->sbiod_sb->sb_fd = *((int *)arg);
  583.     }
  584.     return 0;
  585. }
  586.  
  587. static int
  588. sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
  589.     /* This is an end IO descriptor */
  590.     return 0;
  591. }
  592.  
  593. Sockbuf_IO ber_sockbuf_io_tcp = {
  594.     sb_stream_setup,    /* sbi_setup */
  595.     NULL,                /* sbi_remove */
  596.     sb_stream_ctrl,        /* sbi_ctrl */
  597.     sb_stream_read,        /* sbi_read */
  598.     sb_stream_write,    /* sbi_write */
  599.     sb_stream_close        /* sbi_close */
  600. };
  601.  
  602.  
  603. /*
  604.  * Support for readahead (UDP needs it)
  605.  */
  606.  
  607. static int
  608. sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
  609. {
  610.     Sockbuf_Buf        *p;
  611.  
  612.     assert( sbiod != NULL );
  613.  
  614.     p = LBER_MALLOC( sizeof( *p ) );
  615.     if ( p == NULL ) return -1;
  616.  
  617.     ber_pvt_sb_buf_init( p );
  618.  
  619.     if ( arg == NULL ) {
  620.         ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
  621.     } else {
  622.         ber_pvt_sb_grow_buffer( p, *((int *)arg) );
  623.     }
  624.  
  625.     sbiod->sbiod_pvt = p;
  626.     return 0;
  627. }
  628.  
  629. static int
  630. sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
  631. {
  632.     Sockbuf_Buf        *p;
  633.  
  634.     assert( sbiod != NULL );
  635.  
  636.     p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
  637.  
  638.     if ( p->buf_ptr != p->buf_end ) return -1;
  639.  
  640.     ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
  641.     LBER_FREE( sbiod->sbiod_pvt );
  642.     sbiod->sbiod_pvt = NULL;
  643.  
  644.     return 0;
  645. }
  646.  
  647. static ber_slen_t
  648. sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  649. {
  650.     Sockbuf_Buf        *p;
  651.     ber_slen_t        bufptr = 0, ret, max;
  652.  
  653.     assert( sbiod != NULL );
  654.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  655.     assert( sbiod->sbiod_next != NULL );
  656.  
  657.     p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
  658.  
  659.     assert( p->buf_size > 0 );
  660.  
  661.     /* Are there anything left in the buffer? */
  662.     ret = ber_pvt_sb_copy_out( p, buf, len );
  663.     bufptr += ret;
  664.     len -= ret;
  665.  
  666.     if ( len == 0 ) return bufptr;
  667.  
  668.     max = p->buf_size - p->buf_end;
  669.     ret = 0;
  670.     while ( max > 0 ) {
  671.         ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
  672.             max );
  673. #ifdef EINTR    
  674.         if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
  675. #endif
  676.         break;
  677.     }
  678.  
  679.     if ( ret < 0 ) {
  680.         return ( bufptr ? bufptr : ret );
  681.     }
  682.  
  683.     p->buf_end += ret;
  684.     bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
  685.     return bufptr;
  686. }
  687.  
  688. static ber_slen_t
  689. sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  690. {
  691.     assert( sbiod != NULL );
  692.     assert( sbiod->sbiod_next != NULL );
  693.  
  694.     return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
  695. }
  696.  
  697. static int
  698. sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
  699. {
  700.     assert( sbiod != NULL );
  701.  
  702.     /* Just erase the buffer */
  703.     ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
  704.     return 0;
  705. }
  706.  
  707. static int
  708. sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
  709. {
  710.     Sockbuf_Buf        *p;
  711.  
  712.     p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
  713.  
  714.     if ( opt == LBER_SB_OPT_DATA_READY ) {
  715.         if ( p->buf_ptr != p->buf_end ) {
  716.             return 1;
  717.         }
  718.  
  719.     } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
  720.         if ( p->buf_size >= *((ber_len_t *)arg) ) {
  721.             return 0;
  722.         }
  723.         return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
  724.             -1 : 1 );
  725.     }
  726.  
  727.     return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
  728. }
  729.  
  730. Sockbuf_IO ber_sockbuf_io_readahead = {
  731.     sb_rdahead_setup,    /* sbi_setup */
  732.     sb_rdahead_remove,    /* sbi_remove */
  733.     sb_rdahead_ctrl,    /* sbi_ctrl */
  734.     sb_rdahead_read,    /* sbi_read */
  735.     sb_rdahead_write,    /* sbi_write */
  736.     sb_rdahead_close    /* sbi_close */
  737. };
  738.  
  739. /*
  740.  * Support for simple file IO
  741.  */
  742.  
  743. static ber_slen_t
  744. sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  745. {
  746.     assert( sbiod != NULL);
  747.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  748.  
  749.     return read( sbiod->sbiod_sb->sb_fd, buf, len );
  750. }
  751.  
  752. static ber_slen_t
  753. sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  754. {
  755.     assert( sbiod != NULL);
  756.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  757.  
  758.     return write( sbiod->sbiod_sb->sb_fd, buf, len );
  759. }
  760.  
  761. static int 
  762. sb_fd_close( Sockbuf_IO_Desc *sbiod )
  763. {   
  764.     assert( sbiod != NULL );
  765.     assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
  766.  
  767.     close( sbiod->sbiod_sb->sb_fd );
  768.     return 0;
  769. }
  770.  
  771. /* The argument is a pointer to the file descriptor */
  772. static int
  773. sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
  774.     assert( sbiod != NULL );
  775.  
  776.     if ( arg != NULL )
  777.         sbiod->sbiod_sb->sb_fd = *((int *)arg);
  778.     return 0;
  779. }
  780.  
  781. static int
  782. sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
  783.     /* This is an end IO descriptor */
  784.     return 0;
  785. }
  786.  
  787. Sockbuf_IO ber_sockbuf_io_fd = {
  788.     sb_fd_setup,    /* sbi_setup */
  789.     NULL,            /* sbi_remove */
  790.     sb_fd_ctrl,        /* sbi_ctrl */
  791.     sb_fd_read,        /* sbi_read */
  792.     sb_fd_write,        /* sbi_write */
  793.     sb_fd_close        /* sbi_close */
  794. };
  795.  
  796. /*
  797.  * Debugging layer
  798.  */
  799.  
  800. static int
  801. sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
  802. {
  803.     assert( sbiod != NULL );
  804.     
  805.     if ( arg == NULL ) arg = "sockbuf_";
  806.  
  807.     sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
  808.     if ( sbiod->sbiod_pvt == NULL ) return -1;
  809.  
  810.     strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
  811.     return 0;
  812. }
  813.  
  814. static int
  815. sb_debug_remove( Sockbuf_IO_Desc *sbiod )
  816. {
  817.     assert( sbiod != NULL );
  818.     assert( sbiod->sbiod_pvt != NULL );
  819.  
  820.     LBER_FREE( sbiod->sbiod_pvt );
  821.     sbiod->sbiod_pvt = NULL;
  822.     return 0;
  823. }
  824.  
  825. static int
  826. sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
  827. {
  828.     return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
  829. }
  830.  
  831. static ber_slen_t
  832. sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  833. {
  834.     ber_slen_t        ret;
  835.  
  836.     ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
  837.     if ( ret < 0 ) {
  838.         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
  839.             "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
  840.             (long)len, STRERROR( errno ) );
  841.  
  842.     } else {
  843.         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
  844.             "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
  845.             (long)len, (long)ret );
  846.         ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
  847.             (const char *)buf, ret );
  848.     }
  849.     return ret;
  850. }
  851.  
  852. static ber_slen_t
  853. sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
  854. {
  855.     ber_slen_t        ret;
  856.  
  857.     ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
  858.     if ( ret < 0 ) {
  859.         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
  860.             "%swrite: want=%ld error=%s\n",
  861.             (char *)sbiod->sbiod_pvt, (long)len,
  862.             STRERROR( errno ) );
  863.  
  864.     } else {
  865.         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
  866.             "%swrite: want=%ld, written=%ld\n",
  867.             (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
  868.         ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
  869.             (const char *)buf, ret );
  870.     }
  871.  
  872.     return ret;
  873. }
  874.  
  875. Sockbuf_IO ber_sockbuf_io_debug = {
  876.     sb_debug_setup,        /* sbi_setup */
  877.     sb_debug_remove,    /* sbi_remove */
  878.     sb_debug_ctrl,        /* sbi_ctrl */
  879.     sb_debug_read,        /* sbi_read */
  880.     sb_debug_write,        /* sbi_write */
  881.     NULL                /* sbi_close */
  882. };
  883.  
  884.