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_SYS_FILIO_H )
25 #include <sys/filio.h>
26 #elif defined( HAVE_SYS_IOCTL_H )
27 #include <sys/ioctl.h>
32 #define MIN_BUFF_SIZE 4096
33 #define MAX_BUFF_SIZE 65536
34 #define DEFAULT_READAHEAD 16384
37 ber_sockbuf_alloc( void )
41 ber_int_options.lbo_valid = LBER_INITIALIZED;
43 sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
45 if( sb == NULL ) return NULL;
47 ber_int_sb_init( sb );
52 ber_sockbuf_free( Sockbuf *sb )
55 assert( SOCKBUF_VALID( sb ) );
57 ber_int_sb_close( sb );
58 ber_int_sb_destroy( sb );
62 /* Return values: -1: error, 0: no operation performed or the answer is false,
63 * 1: successful operation or the answer is true
66 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
74 case LBER_SB_OPT_HAS_IO:
76 while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
85 case LBER_SB_OPT_GET_FD:
87 *((int *)arg) = sb->sb_fd;
89 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
92 case LBER_SB_OPT_SET_FD:
93 sb->sb_fd = *((int *)arg);
97 case LBER_SB_OPT_SET_NONBLOCK:
98 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
102 case LBER_SB_OPT_DRAIN: {
103 /* Drain the data source to enable possible errors (e.g.
104 * TLS) to be propagated to the upper layers
106 char buf[MIN_BUFF_SIZE];
109 ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
110 } while ( ret == sizeof( buf ) );
115 case LBER_SB_OPT_NEEDS_READ:
116 ret = ( sb->sb_trans_needs_read ? 1 : 0 );
119 case LBER_SB_OPT_NEEDS_WRITE:
120 ret = ( sb->sb_trans_needs_write ? 1 : 0 );
124 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
133 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
135 Sockbuf_IO_Desc *d, *p, **q;
137 assert( sb != NULL );
138 assert( SOCKBUF_VALID( sb ) );
140 if ( sbio == NULL ) {
146 while ( p && p->sbiod_level > layer ) {
151 d = LBER_MALLOC( sizeof( *d ) );
156 d->sbiod_level = layer;
159 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
163 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
171 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
173 Sockbuf_IO_Desc *p, **q;
175 assert( sb != NULL );
176 assert( SOCKBUF_VALID( sb ) );
178 if ( sb->sb_iod == NULL ) {
183 while ( *q != NULL ) {
185 if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
186 if ( p->sbiod_io->sbi_remove != NULL &&
187 p->sbiod_io->sbi_remove( p ) < 0 )
202 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
204 buf->buf_base = NULL;
211 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
213 assert( buf != NULL);
216 LBER_FREE( buf->buf_base );
218 ber_pvt_sb_buf_init( buf );
222 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
227 assert( buf != NULL );
229 for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
230 if (pw > MAX_BUFF_SIZE) return -1;
233 if ( buf->buf_size < pw ) {
234 p = LBER_REALLOC( buf->buf_base, pw );
235 if ( p == NULL ) return -1;
243 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
247 assert( buf != NULL );
248 assert( sbb != NULL );
250 assert( sbb->buf_size > 0 );
253 max = sbb->buf_end - sbb->buf_ptr;
254 max = ( max < len) ? max : len;
256 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
258 if ( sbb->buf_ptr >= sbb->buf_end ) {
259 sbb->buf_ptr = sbb->buf_end = 0;
266 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
271 assert( sbiod != NULL );
272 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
274 to_go = buf_out->buf_end - buf_out->buf_ptr;
278 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
279 buf_out->buf_ptr, to_go );
281 if ((ret<0) && (errno==EINTR)) continue;
286 if ( ret <= 0 ) return ret;
288 buf_out->buf_ptr += ret;
289 if (buf_out->buf_ptr == buf_out->buf_end) {
290 buf_out->buf_end = buf_out->buf_ptr = 0;
293 if ( (ber_len_t)ret < to_go ) {
294 /* not enough data, so pretend no data was sent. */
302 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
305 int flags = fcntl( sd, F_GETFL);
309 flags &= ~O_NONBLOCK;
311 return fcntl( sd, F_SETFL, flags );
313 #elif defined( FIONBIO )
314 ioctl_t status = nb ? 1 : 0;
315 return ioctl( sd, FIONBIO, &status );
320 ber_int_sb_init( Sockbuf *sb )
324 sb->sb_valid=LBER_VALID_SOCKBUF;
326 sb->sb_debug = ber_int_debug;
327 sb->sb_fd = AC_SOCKET_INVALID;
329 sb->sb_trans_needs_read = 0;
330 sb->sb_trans_needs_write = 0;
332 assert( SOCKBUF_VALID( sb ) );
337 ber_int_sb_close( Sockbuf *sb )
345 if ( p->sbiod_io->sbi_close &&
346 p->sbiod_io->sbi_close( p ) < 0 )
353 sb->sb_fd = AC_SOCKET_INVALID;
359 ber_int_sb_destroy( Sockbuf *sb )
364 assert( SOCKBUF_VALID( sb ) );
366 while ( sb->sb_iod ) {
367 p = sb->sb_iod->sbiod_next;
368 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
369 sb->sb_iod->sbiod_level );
373 return ber_int_sb_init( sb );
377 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
381 assert( buf != NULL );
383 assert( sb->sb_iod != NULL );
384 assert( SOCKBUF_VALID( sb ) );
387 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
390 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
399 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
403 assert( buf != NULL );
405 assert( sb->sb_iod != NULL );
406 assert( SOCKBUF_VALID( sb ) );
409 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
412 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
425 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
427 assert( sbiod != NULL);
428 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
432 * MacTCP/OpenTransport
434 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
437 #elif defined( HAVE_PCNFS ) || \
438 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
443 * Windows Socket API (under DOS/Windows 3.x)
446 * 32-bit Windows Socket API (under Windows NT or Windows 95)
451 rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
457 err = WSAGetLastError();
465 #elif defined( HAVE_NCSA )
467 * NCSA Telnet TCP/IP stack (under DOS)
469 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
472 return read( sbiod->sbiod_sb->sb_fd, buf, len );
477 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
479 assert( sbiod != NULL);
480 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
484 * MacTCP/OpenTransport
486 #define MAX_WRITE 65535
487 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
488 (len<MAX_WRITE) ? len : MAX_WRITE );
490 #elif defined( HAVE_PCNFS) \
491 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
496 * Windows Socket API (under DOS/Windows 3.x)
499 * 32-bit Windows Socket API (under Windows NT or Windows 95)
502 int rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
507 err = WSAGetLastError();
514 #elif defined(HAVE_NCSA)
515 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
519 * VMS -- each write must be 64K or smaller
521 #define MAX_WRITE 65535
522 return write( sbiod->sbiod_sb->sb_fd, buf,
523 (len<MAX_WRITE) ? len : MAX_WRITE);
525 return write( sbiod->sbiod_sb->sb_fd, buf, len );
530 sb_stream_close( Sockbuf_IO_Desc *sbiod )
532 assert( sbiod != NULL );
533 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
534 tcp_close( sbiod->sbiod_sb->sb_fd );
538 /* The argument is a pointer to the socket descriptor */
540 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
541 assert( sbiod != NULL );
544 sbiod->sbiod_sb->sb_fd = *((int *)arg);
550 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
551 /* This is an end IO descriptor */
555 Sockbuf_IO ber_sockbuf_io_tcp = {
556 sb_stream_setup, /* sbi_setup */
557 NULL, /* sbi_remove */
558 sb_stream_ctrl, /* sbi_ctrl */
559 sb_stream_read, /* sbi_read */
560 sb_stream_write, /* sbi_write */
561 sb_stream_close /* sbi_close */
566 * Support for readahead (UDP needs it)
570 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
574 assert( sbiod != NULL );
576 p = LBER_MALLOC( sizeof( *p ) );
577 if ( p == NULL ) return -1;
579 ber_pvt_sb_buf_init( p );
582 ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
584 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
587 sbiod->sbiod_pvt = p;
592 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
596 assert( sbiod != NULL );
598 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
600 if ( p->buf_ptr != p->buf_end ) return -1;
602 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
603 LBER_FREE( sbiod->sbiod_pvt );
604 sbiod->sbiod_pvt = NULL;
610 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
613 ber_slen_t bufptr = 0, ret, max;
615 assert( sbiod != NULL );
616 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
617 assert( sbiod->sbiod_next != NULL );
619 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
621 assert( p->buf_size > 0 );
623 /* Are there anything left in the buffer? */
624 ret = ber_pvt_sb_copy_out( p, buf, len );
628 if ( len == 0 ) return bufptr;
630 max = p->buf_size - p->buf_end;
633 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
636 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
642 return ( bufptr ? bufptr : ret );
646 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
651 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
653 assert( sbiod != NULL );
654 assert( sbiod->sbiod_next != NULL );
656 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
660 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
662 assert( sbiod != NULL );
664 /* Just erase the buffer */
665 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
670 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
674 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
676 if ( opt == LBER_SB_OPT_DATA_READY ) {
677 if ( p->buf_ptr != p->buf_end ) {
681 } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
682 if ( p->buf_size >= *((ber_len_t *)arg) ) {
685 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
689 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
692 Sockbuf_IO ber_sockbuf_io_readahead = {
693 sb_rdahead_setup, /* sbi_setup */
694 sb_rdahead_remove, /* sbi_remove */
695 sb_rdahead_ctrl, /* sbi_ctrl */
696 sb_rdahead_read, /* sbi_read */
697 sb_rdahead_write, /* sbi_write */
698 sb_rdahead_close /* sbi_close */
702 * Support for simple file IO
706 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
708 assert( sbiod != NULL);
709 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
711 return read( sbiod->sbiod_sb->sb_fd, buf, len );
715 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
717 assert( sbiod != NULL);
718 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
720 return write( sbiod->sbiod_sb->sb_fd, buf, len );
724 sb_fd_close( Sockbuf_IO_Desc *sbiod )
726 assert( sbiod != NULL );
727 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
729 close( sbiod->sbiod_sb->sb_fd );
733 /* The argument is a pointer to the file descriptor */
735 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
736 assert( sbiod != NULL );
739 sbiod->sbiod_sb->sb_fd = *((int *)arg);
744 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
745 /* This is an end IO descriptor */
749 Sockbuf_IO ber_sockbuf_io_fd = {
750 sb_fd_setup, /* sbi_setup */
751 NULL, /* sbi_remove */
752 sb_fd_ctrl, /* sbi_ctrl */
753 sb_fd_read, /* sbi_read */
754 sb_fd_write, /* sbi_write */
755 sb_fd_close /* sbi_close */
763 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
765 assert( sbiod != NULL );
767 if ( arg == NULL ) arg = "sockbuf_";
769 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
770 if ( sbiod->sbiod_pvt == NULL ) return -1;
772 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
777 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
779 assert( sbiod != NULL );
780 assert( sbiod->sbiod_pvt != NULL );
782 LBER_FREE( sbiod->sbiod_pvt );
783 sbiod->sbiod_pvt = NULL;
788 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
790 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
794 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
798 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
800 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
801 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
802 (long)len, STRERROR( errno ) );
805 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
806 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
807 (long)len, (long)ret );
808 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
809 (const char *)buf, ret );
815 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
819 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
821 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
822 "%swrite: want=%ld error=%s\n",
823 (char *)sbiod->sbiod_pvt, (long)len,
827 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
828 "%swrite: want=%ld, written=%ld\n",
829 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
830 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
831 (const char *)buf, ret );
837 Sockbuf_IO ber_sockbuf_io_debug = {
838 sb_debug_setup, /* sbi_setup */
839 sb_debug_remove, /* sbi_remove */
840 sb_debug_ctrl, /* sbi_ctrl */
841 sb_debug_read, /* sbi_read */
842 sb_debug_write, /* sbi_write */