1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
4 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/stdlib.h>
16 #include <ac/socket.h>
17 #include <ac/string.h>
18 #include <ac/unistd.h>
22 #endif /* HAVE_IO_H */
24 #if defined( HAVE_FCNTL_H )
28 #if defined( HAVE_SYS_FILIO_H )
29 #include <sys/filio.h>
30 #elif defined( HAVE_SYS_IOCTL_H )
31 #include <sys/ioctl.h>
36 #define MIN_BUFF_SIZE 4096
37 #define MAX_BUFF_SIZE 65536
38 #define DEFAULT_READAHEAD 16384
41 ber_sockbuf_alloc( void )
45 ber_int_options.lbo_valid = LBER_INITIALIZED;
47 sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
49 if( sb == NULL ) return NULL;
51 ber_int_sb_init( sb );
56 ber_sockbuf_free( Sockbuf *sb )
59 assert( SOCKBUF_VALID( sb ) );
61 ber_int_sb_close( sb );
62 ber_int_sb_destroy( sb );
66 /* Return values: -1: error, 0: no operation performed or the answer is false,
67 * 1: successful operation or the answer is true
70 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
76 assert( SOCKBUF_VALID( sb ) );
79 case LBER_SB_OPT_HAS_IO:
81 while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
90 case LBER_SB_OPT_GET_FD:
92 *((int *)arg) = sb->sb_fd;
94 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
97 case LBER_SB_OPT_SET_FD:
98 sb->sb_fd = *((int *)arg);
102 case LBER_SB_OPT_SET_NONBLOCK:
103 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
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
111 char buf[MIN_BUFF_SIZE];
114 ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
115 } while ( ret == sizeof( buf ) );
120 case LBER_SB_OPT_NEEDS_READ:
121 ret = ( sb->sb_trans_needs_read ? 1 : 0 );
124 case LBER_SB_OPT_NEEDS_WRITE:
125 ret = ( sb->sb_trans_needs_write ? 1 : 0 );
128 case LBER_SB_OPT_GET_MAX_INCOMING:
130 *((ber_len_t *)arg) = sb->sb_max_incoming;
135 case LBER_SB_OPT_SET_MAX_INCOMING:
136 sb->sb_max_incoming = *((ber_len_t *)arg);
141 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
150 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
152 Sockbuf_IO_Desc *d, *p, **q;
154 assert( sb != NULL );
155 assert( SOCKBUF_VALID( sb ) );
157 if ( sbio == NULL ) {
163 while ( p && p->sbiod_level > layer ) {
168 d = LBER_MALLOC( sizeof( *d ) );
173 d->sbiod_level = layer;
176 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
180 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
188 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
190 Sockbuf_IO_Desc *p, **q;
192 assert( sb != NULL );
193 assert( SOCKBUF_VALID( sb ) );
195 if ( sb->sb_iod == NULL ) {
200 while ( *q != NULL ) {
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 )
219 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
221 buf->buf_base = NULL;
228 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
230 assert( buf != NULL);
233 LBER_FREE( buf->buf_base );
235 ber_pvt_sb_buf_init( buf );
239 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
244 assert( buf != NULL );
246 for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
247 if (pw > MAX_BUFF_SIZE) return -1;
250 if ( buf->buf_size < pw ) {
251 p = LBER_REALLOC( buf->buf_base, pw );
252 if ( p == NULL ) return -1;
260 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
264 assert( buf != NULL );
265 assert( sbb != NULL );
267 assert( sbb->buf_size > 0 );
270 max = sbb->buf_end - sbb->buf_ptr;
271 max = ( max < len) ? max : len;
273 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
275 if ( sbb->buf_ptr >= sbb->buf_end ) {
276 sbb->buf_ptr = sbb->buf_end = 0;
283 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
288 assert( sbiod != NULL );
289 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
291 to_go = buf_out->buf_end - buf_out->buf_ptr;
295 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
296 buf_out->buf_ptr, to_go );
298 if ((ret<0) && (errno==EINTR)) continue;
303 if ( ret <= 0 ) return ret;
305 buf_out->buf_ptr += ret;
306 if (buf_out->buf_ptr == buf_out->buf_end) {
307 buf_out->buf_end = buf_out->buf_ptr = 0;
310 if ( (ber_len_t)ret < to_go ) {
311 /* not enough data, so pretend no data was sent. */
319 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
322 int flags = fcntl( sd, F_GETFL);
326 flags &= ~O_NONBLOCK;
328 return fcntl( sd, F_SETFL, flags );
330 #elif defined( FIONBIO )
331 ioctl_t status = nb ? 1 : 0;
332 return ioctl( sd, FIONBIO, &status );
337 ber_int_sb_init( Sockbuf *sb )
341 sb->sb_valid=LBER_VALID_SOCKBUF;
343 sb->sb_debug = ber_int_debug;
344 sb->sb_fd = AC_SOCKET_INVALID;
346 sb->sb_trans_needs_read = 0;
347 sb->sb_trans_needs_write = 0;
349 assert( SOCKBUF_VALID( sb ) );
354 ber_int_sb_close( Sockbuf *sb )
362 if ( p->sbiod_io->sbi_close &&
363 p->sbiod_io->sbi_close( p ) < 0 )
370 sb->sb_fd = AC_SOCKET_INVALID;
376 ber_int_sb_destroy( Sockbuf *sb )
381 assert( SOCKBUF_VALID( sb ) );
383 while ( sb->sb_iod ) {
384 p = sb->sb_iod->sbiod_next;
385 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
386 sb->sb_iod->sbiod_level );
390 return ber_int_sb_init( sb );
394 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
398 assert( buf != NULL );
400 assert( sb->sb_iod != NULL );
401 assert( SOCKBUF_VALID( sb ) );
404 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
407 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
416 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
420 assert( buf != NULL );
422 assert( sb->sb_iod != NULL );
423 assert( SOCKBUF_VALID( sb ) );
426 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
429 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
442 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
444 assert( sbiod != NULL);
445 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
449 * MacTCP/OpenTransport
451 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
454 #elif defined( HAVE_PCNFS ) || \
455 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
460 * Windows Socket API (under DOS/Windows 3.x)
463 * 32-bit Windows Socket API (under Windows NT or Windows 95)
468 rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
474 err = WSAGetLastError();
482 #elif defined( HAVE_NCSA )
484 * NCSA Telnet TCP/IP stack (under DOS)
486 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
489 return read( sbiod->sbiod_sb->sb_fd, buf, len );
494 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
496 assert( sbiod != NULL);
497 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
501 * MacTCP/OpenTransport
503 #define MAX_WRITE 65535
504 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
505 (len<MAX_WRITE) ? len : MAX_WRITE );
507 #elif defined( HAVE_PCNFS) \
508 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
513 * Windows Socket API (under DOS/Windows 3.x)
516 * 32-bit Windows Socket API (under Windows NT or Windows 95)
519 int rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
524 err = WSAGetLastError();
531 #elif defined(HAVE_NCSA)
532 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
536 * VMS -- each write must be 64K or smaller
538 #define MAX_WRITE 65535
539 return write( sbiod->sbiod_sb->sb_fd, buf,
540 (len<MAX_WRITE) ? len : MAX_WRITE);
542 return write( sbiod->sbiod_sb->sb_fd, buf, len );
547 sb_stream_close( Sockbuf_IO_Desc *sbiod )
549 assert( sbiod != NULL );
550 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
551 tcp_close( sbiod->sbiod_sb->sb_fd );
555 /* The argument is a pointer to the socket descriptor */
557 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
558 assert( sbiod != NULL );
561 sbiod->sbiod_sb->sb_fd = *((int *)arg);
567 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
568 /* This is an end IO descriptor */
572 Sockbuf_IO ber_sockbuf_io_tcp = {
573 sb_stream_setup, /* sbi_setup */
574 NULL, /* sbi_remove */
575 sb_stream_ctrl, /* sbi_ctrl */
576 sb_stream_read, /* sbi_read */
577 sb_stream_write, /* sbi_write */
578 sb_stream_close /* sbi_close */
583 * Support for readahead (UDP needs it)
587 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
591 assert( sbiod != NULL );
593 p = LBER_MALLOC( sizeof( *p ) );
594 if ( p == NULL ) return -1;
596 ber_pvt_sb_buf_init( p );
599 ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
601 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
604 sbiod->sbiod_pvt = p;
609 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
613 assert( sbiod != NULL );
615 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
617 if ( p->buf_ptr != p->buf_end ) return -1;
619 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
620 LBER_FREE( sbiod->sbiod_pvt );
621 sbiod->sbiod_pvt = NULL;
627 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
630 ber_slen_t bufptr = 0, ret, max;
632 assert( sbiod != NULL );
633 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
634 assert( sbiod->sbiod_next != NULL );
636 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
638 assert( p->buf_size > 0 );
640 /* Are there anything left in the buffer? */
641 ret = ber_pvt_sb_copy_out( p, buf, len );
645 if ( len == 0 ) return bufptr;
647 max = p->buf_size - p->buf_end;
650 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
653 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
659 return ( bufptr ? bufptr : ret );
663 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
668 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
670 assert( sbiod != NULL );
671 assert( sbiod->sbiod_next != NULL );
673 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
677 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
679 assert( sbiod != NULL );
681 /* Just erase the buffer */
682 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
687 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
691 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
693 if ( opt == LBER_SB_OPT_DATA_READY ) {
694 if ( p->buf_ptr != p->buf_end ) {
698 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
699 if ( p->buf_size >= *((ber_len_t *)arg) ) {
702 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
706 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
709 Sockbuf_IO ber_sockbuf_io_readahead = {
710 sb_rdahead_setup, /* sbi_setup */
711 sb_rdahead_remove, /* sbi_remove */
712 sb_rdahead_ctrl, /* sbi_ctrl */
713 sb_rdahead_read, /* sbi_read */
714 sb_rdahead_write, /* sbi_write */
715 sb_rdahead_close /* sbi_close */
719 * Support for simple file IO
723 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
725 assert( sbiod != NULL);
726 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
728 return read( sbiod->sbiod_sb->sb_fd, buf, len );
732 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
734 assert( sbiod != NULL);
735 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
737 return write( sbiod->sbiod_sb->sb_fd, buf, len );
741 sb_fd_close( Sockbuf_IO_Desc *sbiod )
743 assert( sbiod != NULL );
744 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
746 close( sbiod->sbiod_sb->sb_fd );
750 /* The argument is a pointer to the file descriptor */
752 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
753 assert( sbiod != NULL );
756 sbiod->sbiod_sb->sb_fd = *((int *)arg);
761 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
762 /* This is an end IO descriptor */
766 Sockbuf_IO ber_sockbuf_io_fd = {
767 sb_fd_setup, /* sbi_setup */
768 NULL, /* sbi_remove */
769 sb_fd_ctrl, /* sbi_ctrl */
770 sb_fd_read, /* sbi_read */
771 sb_fd_write, /* sbi_write */
772 sb_fd_close /* sbi_close */
780 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
782 assert( sbiod != NULL );
784 if ( arg == NULL ) arg = "sockbuf_";
786 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
787 if ( sbiod->sbiod_pvt == NULL ) return -1;
789 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
794 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
796 assert( sbiod != NULL );
797 assert( sbiod->sbiod_pvt != NULL );
799 LBER_FREE( sbiod->sbiod_pvt );
800 sbiod->sbiod_pvt = NULL;
805 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
807 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
811 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
815 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
817 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
818 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
819 (long)len, STRERROR( errno ) );
822 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
823 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
824 (long)len, (long)ret );
825 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
826 (const char *)buf, ret );
832 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
836 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
838 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
839 "%swrite: want=%ld error=%s\n",
840 (char *)sbiod->sbiod_pvt, (long)len,
844 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
845 "%swrite: want=%ld, written=%ld\n",
846 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
847 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
848 (const char *)buf, ret );
854 Sockbuf_IO ber_sockbuf_io_debug = {
855 sb_debug_setup, /* sbi_setup */
856 sb_debug_remove, /* sbi_remove */
857 sb_debug_ctrl, /* sbi_ctrl */
858 sb_debug_read, /* sbi_read */
859 sb_debug_write, /* sbi_write */