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 ) );
48 ber_int_sb_init( sb );
53 ber_sockbuf_free( Sockbuf *sb )
56 assert( SOCKBUF_VALID( sb ) );
58 ber_int_sb_close( sb );
59 ber_int_sb_destroy( sb );
63 /* Return values: -1: error, 0: no operation performed or the answer is false,
64 * 1: successful operation or the answer is true
67 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
75 case LBER_SB_OPT_HAS_IO:
78 while ( p && p->sbiod_io != (Sockbuf_IO *)arg )
84 case LBER_SB_OPT_GET_FD:
86 *((int *)arg) = sb->sb_fd;
87 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
89 case LBER_SB_OPT_SET_FD:
90 sb->sb_fd = *((int *)arg);
93 case LBER_SB_OPT_SET_NONBLOCK:
94 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
97 case LBER_SB_OPT_DRAIN: {
98 /* Drain the data source to enable possible errors (e.g.
99 * TLS) to be propagated to the upper layers
101 char buf[MIN_BUFF_SIZE];
103 ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
104 } while ( ret == sizeof( buf ) );
108 case LBER_SB_OPT_NEEDS_READ:
109 ret = ( sb->sb_trans_needs_read ? 1 : 0 );
111 case LBER_SB_OPT_NEEDS_WRITE:
112 ret = ( sb->sb_trans_needs_write ? 1 : 0 );
115 ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
124 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
126 Sockbuf_IO_Desc *d, *p, **q;
128 assert( sb != NULL );
129 assert( SOCKBUF_VALID( sb ) );
136 while ( p && p->sbiod_level > layer ) {
141 d = LBER_MALLOC( sizeof( *d ) );
145 d->sbiod_level = layer;
148 memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
152 if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) )
159 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
161 Sockbuf_IO_Desc *p, **q;
163 assert( sb != NULL );
164 assert( SOCKBUF_VALID( sb ) );
166 if ( sb->sb_iod == NULL )
170 while ( *q != NULL ) {
172 if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
173 if ( p->sbiod_io->sbi_remove != NULL &&
174 p->sbiod_io->sbi_remove( p ) < 0 )
187 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
189 buf->buf_base = NULL;
196 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
198 assert( buf != NULL);
201 LBER_FREE( buf->buf_base );
202 ber_pvt_sb_buf_init( buf );
206 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
211 assert( buf != NULL );
213 for ( pw = MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
214 if (pw > MAX_BUFF_SIZE) return -1;
217 if ( buf->buf_size < pw ) {
218 p = LBER_REALLOC( buf->buf_base, pw );
219 if ( p == NULL ) return -1;
227 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
231 assert( buf != NULL );
232 assert( sbb != NULL );
234 assert( sbb->buf_size > 0 );
237 max = sbb->buf_end - sbb->buf_ptr;
238 max = ( max < len) ? max : len;
240 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
242 if ( sbb->buf_ptr >= sbb->buf_end )
243 sbb->buf_ptr = sbb->buf_end = 0;
249 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
254 assert( sbiod != NULL );
255 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
257 to_go = buf_out->buf_end - buf_out->buf_ptr;
261 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
262 buf_out->buf_ptr, to_go );
264 if ((ret<0) && (errno==EINTR))
273 buf_out->buf_ptr += ret;
274 if (buf_out->buf_ptr == buf_out->buf_end)
275 buf_out->buf_end = buf_out->buf_ptr = 0;
276 if ( (ber_len_t)ret < to_go )
277 /* not enough data, so pretend no data was sent. */
283 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
286 int flags = fcntl( sd, F_GETFL);
290 flags &= ~O_NONBLOCK;
291 return fcntl( sd, F_SETFL, flags );
293 #elif defined( FIONBIO )
294 ioctl_t status = nb ? 1 : 0;
295 return ioctl( sd, FIONBIO, &status );
300 ber_int_sb_init( Sockbuf *sb )
304 sb->sb_valid=LBER_VALID_SOCKBUF;
306 sb->sb_debug = ber_int_debug;
307 sb->sb_fd = AC_SOCKET_INVALID;
309 sb->sb_trans_needs_read = 0;
310 sb->sb_trans_needs_write = 0;
312 assert( SOCKBUF_VALID( sb ) );
317 ber_int_sb_close( Sockbuf *sb )
325 if ( p->sbiod_io->sbi_close &&
326 p->sbiod_io->sbi_close( p ) < 0 )
331 sb->sb_fd = AC_SOCKET_INVALID;
337 ber_int_sb_destroy( Sockbuf *sb )
342 assert( SOCKBUF_VALID( sb ) );
344 while ( sb->sb_iod ) {
345 p = sb->sb_iod->sbiod_next;
346 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
347 sb->sb_iod->sbiod_level );
350 return ber_int_sb_init( sb );
354 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
358 assert( buf != NULL );
360 assert( sb->sb_iod != NULL );
361 assert( SOCKBUF_VALID( sb ) );
364 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
366 if ( ( ret < 0 ) && ( errno == EINTR ) )
375 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
379 assert( buf != NULL );
381 assert( sb->sb_iod != NULL );
382 assert( SOCKBUF_VALID( sb ) );
385 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
387 if ( ( ret < 0 ) && ( errno == EINTR ) )
400 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
402 assert( sbiod != NULL);
403 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
407 * MacTCP/OpenTransport
409 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
412 #elif defined( HAVE_PCNFS ) || \
413 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
418 * Windows Socket API (under DOS/Windows 3.x)
421 * 32-bit Windows Socket API (under Windows NT or Windows 95)
426 rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
433 err = WSAGetLastError();
440 #elif defined( HAVE_NCSA )
442 * NCSA Telnet TCP/IP stack (under DOS)
444 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
447 return read( sbiod->sbiod_sb->sb_fd, buf, len );
452 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
454 assert( sbiod != NULL);
455 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
459 * MacTCP/OpenTransport
461 #define MAX_WRITE 65535
462 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
463 (len<MAX_WRITE)? len : MAX_WRITE );
465 #elif defined( HAVE_PCNFS) \
466 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
471 * Windows Socket API (under DOS/Windows 3.x)
474 * 32-bit Windows Socket API (under Windows NT or Windows 95)
480 rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
486 err = WSAGetLastError();
493 #elif defined(HAVE_NCSA)
494 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
498 * VMS -- each write must be 64K or smaller
500 #define MAX_WRITE 65535
501 return write( sbiod->sbiod_sb->sb_fd, buf,
502 (len<MAX_WRITE)? len : MAX_WRITE);
504 return write( sbiod->sbiod_sb->sb_fd, buf, len );
509 sb_stream_close( Sockbuf_IO_Desc *sbiod )
511 assert( sbiod != NULL );
512 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
513 tcp_close( sbiod->sbiod_sb->sb_fd );
517 /* The argument is a pointer to the socket descriptor */
519 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
520 assert( sbiod != NULL );
523 sbiod->sbiod_sb->sb_fd = *((int *)arg);
528 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
529 /* This is an end IO descriptor */
533 Sockbuf_IO ber_sockbuf_io_tcp =
535 sb_stream_setup, /* sbi_setup */
536 NULL, /* sbi_remove */
537 sb_stream_ctrl, /* sbi_ctrl */
538 sb_stream_read, /* sbi_read */
539 sb_stream_write, /* sbi_write */
540 sb_stream_close /* sbi_close */
545 * Support for readahead (UDP needs it)
549 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
553 assert( sbiod != NULL );
555 p = LBER_MALLOC( sizeof( *p ) );
558 ber_pvt_sb_buf_init( p );
560 ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
562 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
563 sbiod->sbiod_pvt = p;
568 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
572 assert( sbiod != NULL );
574 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
576 if ( p->buf_ptr != p->buf_end )
579 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
580 LBER_FREE( sbiod->sbiod_pvt );
581 sbiod->sbiod_pvt = NULL;
587 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
590 ber_slen_t bufptr = 0, ret, max;
592 assert( sbiod != NULL );
593 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
594 assert( sbiod->sbiod_next != NULL );
596 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
598 assert( p->buf_size > 0 );
600 /* Are there anything left in the buffer? */
601 ret = ber_pvt_sb_copy_out( p, buf, len );
608 max = p->buf_size - p->buf_end;
611 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
614 if ( ( ret < 0 ) && ( errno == EINTR ) )
621 return ( bufptr ? bufptr : ret );
624 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
629 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
631 assert( sbiod != NULL );
632 assert( sbiod->sbiod_next != NULL );
634 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
638 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
640 assert( sbiod != NULL );
642 /* Just erase the buffer */
643 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
648 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
652 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
654 if ( opt == LBER_SB_OPT_DATA_READY ) {
655 if ( p->buf_ptr != p->buf_end )
658 else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
659 if ( p->buf_size >= *((ber_len_t *)arg) )
661 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
665 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
668 Sockbuf_IO ber_sockbuf_io_readahead =
670 sb_rdahead_setup, /* sbi_setup */
671 sb_rdahead_remove, /* sbi_remove */
672 sb_rdahead_ctrl, /* sbi_ctrl */
673 sb_rdahead_read, /* sbi_read */
674 sb_rdahead_write, /* sbi_write */
675 sb_rdahead_close /* sbi_close */
679 * Support for simple file IO
683 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
685 assert( sbiod != NULL);
686 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
688 return read( sbiod->sbiod_sb->sb_fd, buf, len );
692 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
694 assert( sbiod != NULL);
695 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
697 return write( sbiod->sbiod_sb->sb_fd, buf, len );
701 sb_fd_close( Sockbuf_IO_Desc *sbiod )
703 assert( sbiod != NULL );
704 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
706 close( sbiod->sbiod_sb->sb_fd );
710 /* The argument is a pointer to the file descriptor */
712 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
713 assert( sbiod != NULL );
716 sbiod->sbiod_sb->sb_fd = *((int *)arg);
721 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
722 /* This is an end IO descriptor */
726 Sockbuf_IO ber_sockbuf_io_fd =
728 sb_fd_setup, /* sbi_setup */
729 NULL, /* sbi_remove */
730 sb_fd_ctrl, /* sbi_ctrl */
731 sb_fd_read, /* sbi_read */
732 sb_fd_write, /* sbi_write */
733 sb_fd_close /* sbi_close */
741 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
743 assert( sbiod != NULL );
748 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
749 if ( sbiod->sbiod_pvt == NULL )
751 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
756 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
758 assert( sbiod != NULL );
759 assert( sbiod->sbiod_pvt != NULL );
761 LBER_FREE( sbiod->sbiod_pvt );
762 sbiod->sbiod_pvt = NULL;
767 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
769 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
773 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
777 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
779 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
780 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
781 (long)len, STRERROR( errno ) );
784 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
785 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
786 (long)len, (long)ret );
787 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
788 (const char *)buf, ret );
794 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
798 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
800 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
801 "%swrite: want=%ld error=%s\n",
802 (char *)sbiod->sbiod_pvt, (long)len,
806 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
807 "%swrite: want=%ld, written=%ld\n",
808 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
809 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
810 (const char *)buf, ret );
815 Sockbuf_IO ber_sockbuf_io_debug =
817 sb_debug_setup, /* sbi_setup */
818 sb_debug_remove, /* sbi_remove */
819 sb_debug_ctrl, /* sbi_ctrl */
820 sb_debug_read, /* sbi_read */
821 sb_debug_write, /* sbi_write */