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)
218 if ( buf->buf_size < pw ) {
219 p = LBER_REALLOC( buf->buf_base, pw );
229 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
233 assert( buf != NULL );
234 assert( sbb != NULL );
236 assert( sbb->buf_size > 0 );
239 max = sbb->buf_end - sbb->buf_ptr;
240 max = ( max < len) ? max : len;
242 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
244 if ( sbb->buf_ptr >= sbb->buf_end )
245 sbb->buf_ptr = sbb->buf_end = 0;
251 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
256 assert( sbiod != NULL );
257 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
259 to_go = buf_out->buf_end - buf_out->buf_ptr;
263 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
264 buf_out->buf_ptr, to_go );
266 if ((ret<0) && (errno==EINTR))
275 buf_out->buf_ptr += ret;
276 if (buf_out->buf_ptr == buf_out->buf_end)
277 buf_out->buf_end = buf_out->buf_ptr = 0;
278 if ( (ber_len_t)ret < to_go )
279 /* not enough data, so pretend no data was sent. */
285 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
288 int flags = fcntl( sd, F_GETFL);
292 flags &= ~O_NONBLOCK;
293 return fcntl( sd, F_SETFL, flags );
295 #elif defined( FIONBIO )
296 ioctl_t status = nb ? 1 : 0;
297 return ioctl( sd, FIONBIO, &status );
302 ber_int_sb_init( Sockbuf *sb )
306 sb->sb_valid=LBER_VALID_SOCKBUF;
308 sb->sb_debug = ber_int_debug;
309 sb->sb_fd = AC_SOCKET_INVALID;
311 sb->sb_trans_needs_read = 0;
312 sb->sb_trans_needs_write = 0;
314 assert( SOCKBUF_VALID( sb ) );
319 ber_int_sb_close( Sockbuf *sb )
327 if ( p->sbiod_io->sbi_close &&
328 p->sbiod_io->sbi_close( p ) < 0 )
333 sb->sb_fd = AC_SOCKET_INVALID;
339 ber_int_sb_destroy( Sockbuf *sb )
344 assert( SOCKBUF_VALID( sb ) );
346 while ( sb->sb_iod ) {
347 p = sb->sb_iod->sbiod_next;
348 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
349 sb->sb_iod->sbiod_level );
352 return ber_int_sb_init( sb );
356 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
360 assert( buf != NULL );
362 assert( sb->sb_iod != NULL );
363 assert( SOCKBUF_VALID( sb ) );
366 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
368 if ( ( ret < 0 ) && ( errno == EINTR ) )
377 ber_int_sb_write( 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_write( sb->sb_iod, buf, len );
389 if ( ( ret < 0 ) && ( errno == EINTR ) )
402 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
404 assert( sbiod != NULL);
405 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
409 * MacTCP/OpenTransport
411 return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
414 #elif defined( HAVE_PCNFS ) || \
415 defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
420 * Windows Socket API (under DOS/Windows 3.x)
423 * 32-bit Windows Socket API (under Windows NT or Windows 95)
428 rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
435 err = WSAGetLastError();
442 #elif defined( HAVE_NCSA )
444 * NCSA Telnet TCP/IP stack (under DOS)
446 return nread( sbiod->sbiod_sb->sb_fd, buf, len );
449 return read( sbiod->sbiod_sb->sb_fd, buf, len );
454 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
456 assert( sbiod != NULL);
457 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
461 * MacTCP/OpenTransport
463 #define MAX_WRITE 65535
464 return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
465 (len<MAX_WRITE)? len : MAX_WRITE );
467 #elif defined( HAVE_PCNFS) \
468 || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
473 * Windows Socket API (under DOS/Windows 3.x)
476 * 32-bit Windows Socket API (under Windows NT or Windows 95)
482 rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
488 err = WSAGetLastError();
495 #elif defined(HAVE_NCSA)
496 return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
500 * VMS -- each write must be 64K or smaller
502 #define MAX_WRITE 65535
503 return write( sbiod->sbiod_sb->sb_fd, buf,
504 (len<MAX_WRITE)? len : MAX_WRITE);
506 return write( sbiod->sbiod_sb->sb_fd, buf, len );
511 sb_stream_close( Sockbuf_IO_Desc *sbiod )
513 assert( sbiod != NULL );
514 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
515 tcp_close( sbiod->sbiod_sb->sb_fd );
519 /* The argument is a pointer to the socket descriptor */
521 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
522 assert( sbiod != NULL );
525 sbiod->sbiod_sb->sb_fd = *((int *)arg);
530 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
531 /* This is an end IO descriptor */
535 Sockbuf_IO ber_sockbuf_io_tcp =
537 sb_stream_setup, /* sbi_setup */
538 NULL, /* sbi_remove */
539 sb_stream_ctrl, /* sbi_ctrl */
540 sb_stream_read, /* sbi_read */
541 sb_stream_write, /* sbi_write */
542 sb_stream_close /* sbi_close */
547 * Support for readahead (UDP needs it)
551 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
555 assert( sbiod != NULL );
557 p = LBER_MALLOC( sizeof( *p ) );
560 ber_pvt_sb_buf_init( p );
562 ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
564 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
565 sbiod->sbiod_pvt = p;
570 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
574 assert( sbiod != NULL );
576 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
578 if ( p->buf_ptr != p->buf_end )
581 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
582 LBER_FREE( sbiod->sbiod_pvt );
583 sbiod->sbiod_pvt = NULL;
589 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
592 ber_slen_t bufptr = 0, ret, max;
594 assert( sbiod != NULL );
595 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
596 assert( sbiod->sbiod_next != NULL );
598 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
600 assert( p->buf_size > 0 );
602 /* Are there anything left in the buffer? */
603 ret = ber_pvt_sb_copy_out( p, buf, len );
610 max = p->buf_size - p->buf_end;
613 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
616 if ( ( ret < 0 ) && ( errno == EINTR ) )
623 return ( bufptr ? bufptr : ret );
626 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
631 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
633 assert( sbiod != NULL );
634 assert( sbiod->sbiod_next != NULL );
636 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
640 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
642 assert( sbiod != NULL );
644 /* Just erase the buffer */
645 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
650 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
654 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
656 if ( opt == LBER_SB_OPT_DATA_READY ) {
657 if ( p->buf_ptr != p->buf_end )
660 else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
661 if ( p->buf_size >= *((ber_len_t *)arg) )
663 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
667 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
670 Sockbuf_IO ber_sockbuf_io_readahead =
672 sb_rdahead_setup, /* sbi_setup */
673 sb_rdahead_remove, /* sbi_remove */
674 sb_rdahead_ctrl, /* sbi_ctrl */
675 sb_rdahead_read, /* sbi_read */
676 sb_rdahead_write, /* sbi_write */
677 sb_rdahead_close /* sbi_close */
681 * Support for simple file IO
685 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
687 assert( sbiod != NULL);
688 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
690 return read( sbiod->sbiod_sb->sb_fd, buf, len );
694 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
696 assert( sbiod != NULL);
697 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
699 return write( sbiod->sbiod_sb->sb_fd, buf, len );
703 sb_fd_close( Sockbuf_IO_Desc *sbiod )
705 assert( sbiod != NULL );
706 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
708 close( sbiod->sbiod_sb->sb_fd );
712 /* The argument is a pointer to the file descriptor */
714 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
715 assert( sbiod != NULL );
718 sbiod->sbiod_sb->sb_fd = *((int *)arg);
723 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
724 /* This is an end IO descriptor */
728 Sockbuf_IO ber_sockbuf_io_fd =
730 sb_fd_setup, /* sbi_setup */
731 NULL, /* sbi_remove */
732 sb_fd_ctrl, /* sbi_ctrl */
733 sb_fd_read, /* sbi_read */
734 sb_fd_write, /* sbi_write */
735 sb_fd_close /* sbi_close */
743 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
745 assert( sbiod != NULL );
750 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
751 if ( sbiod->sbiod_pvt == NULL )
753 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
758 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
760 assert( sbiod != NULL );
761 assert( sbiod->sbiod_pvt != NULL );
763 LBER_FREE( sbiod->sbiod_pvt );
764 sbiod->sbiod_pvt = NULL;
769 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
771 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
775 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
779 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
781 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
782 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
783 (long)len, STRERROR( errno ) );
786 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
787 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
788 (long)len, (long)ret );
789 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
790 (const char *)buf, ret );
796 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
800 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
802 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
803 "%swrite: want=%ld error=%s\n",
804 (char *)sbiod->sbiod_pvt, (long)len,
808 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
809 "%swrite: want=%ld, written=%ld\n",
810 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
811 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
812 (const char *)buf, ret );
817 Sockbuf_IO ber_sockbuf_io_debug =
819 sb_debug_setup, /* sbi_setup */
820 sb_debug_remove, /* sbi_remove */
821 sb_debug_ctrl, /* sbi_ctrl */
822 sb_debug_read, /* sbi_read */
823 sb_debug_write, /* sbi_write */