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 )
76 case LBER_SB_OPT_HAS_IO:
79 while ( p && p->sbiod_io != (Sockbuf_IO *)arg )
85 case LBER_SB_OPT_GET_FD:
87 *((int *)arg) = sb->sb_fd;
88 ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
90 case LBER_SB_OPT_SET_FD:
91 sb->sb_fd = *((int *)arg);
94 case LBER_SB_OPT_SET_NONBLOCK:
95 ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
98 case LBER_SB_OPT_DRAIN:
99 /* Drain the data source to enable possible errors (e.g.
100 * TLS) to be propagated to the upper layers
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 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 */
546 * Support for UDP (CLDAP)
556 sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
558 struct dgram_data *p;
560 assert( sbiod != NULL);
561 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
563 p = LBER_MALLOC( sizeof( *p ) );
566 memset( p, '\0', sizeof( *p ) );
567 sbiod->sbiod_pvt = (void *)p;
569 sbiod->sbiod_sb->sb_fd = *((int *)arg);
574 sb_dgram_release( Sockbuf_IO_Desc *sbiod )
576 assert( sbiod != NULL);
577 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
579 LBER_FREE( sbiod->sbiod_pvt );
580 sbiod->sbiod_pvt = NULL;
585 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
587 #ifdef LDAP_CONNECTIONLESS
590 struct dgram_data *p;
592 assert( sbiod != NULL );
593 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
594 assert( buf != NULL );
596 p = (struct dgram_data *)sbiod->sbiod_pvt;
598 addrlen = sizeof( struct sockaddr );
599 rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->src,
603 # else /* LDAP_CONNECTIONLESS */
605 # endif /* LDAP_CONNECTIONLESS */
609 sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
611 #ifdef LDAP_CONNECTIONLESS
613 struct dgram_data *p;
615 assert( sbiod != NULL );
616 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
617 assert( buf != NULL );
619 p = (struct dgram_data *)sbiod->sbiod_pvt;
621 rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, &p->dst,
622 sizeof( struct sockaddr ) );
627 /* fake error if write was not atomic */
641 sb_dgram_close( Sockbuf_IO_Desc *sbiod )
643 assert( sbiod != NULL );
644 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
646 tcp_close( sbiod->sbiod_sb->sb_fd );
651 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
653 struct dgram_data *p;
655 assert( sbiod != NULL );
656 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
658 p = (struct dgram_data *)sbiod->sbiod_pvt;
660 if ( opt == LBER_SB_OPT_UDP_SET_DST ) {
661 memcpy( &p->dst, arg, sizeof( struct sockaddr ) );
664 else if ( opt == LBER_SB_OPT_UDP_GET_SRC ) {
665 *(( struct sockaddr **)arg) = &p->src;
668 /* This is an end IO descriptor */
672 Sockbuf_IO ber_sockbuf_io_udp =
674 sb_dgram_setup, /* sbi_setup */
675 sb_dgram_release, /* sbi_release */
676 sb_dgram_ctrl, /* sbi_ctrl */
677 sb_dgram_read, /* sbi_read */
678 sb_dgram_write, /* sbi_write */
679 sb_dgram_close /* sbi_close */
683 * Support for readahead (UDP needs it)
687 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
691 assert( sbiod != NULL );
693 p = LBER_MALLOC( sizeof( *p ) );
696 ber_pvt_sb_buf_init( p );
698 ber_pvt_sb_grow_buffer( p, DEFAULT_READAHEAD );
700 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
701 sbiod->sbiod_pvt = p;
706 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
710 assert( sbiod != NULL );
712 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
714 if ( p->buf_ptr != p->buf_end )
717 ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
718 LBER_FREE( sbiod->sbiod_pvt );
719 sbiod->sbiod_pvt = NULL;
725 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
728 ber_slen_t bufptr = 0, ret, max;
730 assert( sbiod != NULL );
731 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
732 assert( sbiod->sbiod_next != NULL );
734 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
736 assert( p->buf_size > 0 );
738 /* Are there anything left in the buffer? */
739 ret = ber_pvt_sb_copy_out( p, buf, len );
746 max = p->buf_size - p->buf_end;
749 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
752 if ( ( ret < 0 ) && ( errno == EINTR ) )
759 return ( bufptr ? bufptr : ret );
762 bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
767 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
769 assert( sbiod != NULL );
770 assert( sbiod->sbiod_next != NULL );
772 return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
776 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
778 assert( sbiod != NULL );
780 /* Just erase the buffer */
781 ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
786 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
790 p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
792 if ( opt == LBER_SB_OPT_DATA_READY ) {
793 if ( p->buf_ptr != p->buf_end )
796 else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
797 if ( p->buf_size >= *((ber_len_t *)arg) )
799 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
803 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
806 Sockbuf_IO ber_sockbuf_io_readahead =
808 sb_rdahead_setup, /* sbi_setup */
809 sb_rdahead_remove, /* sbi_remove */
810 sb_rdahead_ctrl, /* sbi_ctrl */
811 sb_rdahead_read, /* sbi_read */
812 sb_rdahead_write, /* sbi_write */
813 sb_rdahead_close /* sbi_close */
817 * Support for simple file IO
821 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
823 assert( sbiod != NULL);
824 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
826 return read( sbiod->sbiod_sb->sb_fd, buf, len );
830 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
832 assert( sbiod != NULL);
833 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
835 return write( sbiod->sbiod_sb->sb_fd, buf, len );
839 sb_fd_close( Sockbuf_IO_Desc *sbiod )
841 assert( sbiod != NULL );
842 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
844 close( sbiod->sbiod_sb->sb_fd );
848 /* The argument is a pointer to the file descriptor */
850 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
851 assert( sbiod != NULL );
854 sbiod->sbiod_sb->sb_fd = *((int *)arg);
859 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
860 /* This is an end IO descriptor */
864 Sockbuf_IO ber_sockbuf_io_fd =
866 sb_fd_setup, /* sbi_setup */
867 NULL, /* sbi_remove */
868 sb_fd_ctrl, /* sbi_ctrl */
869 sb_fd_read, /* sbi_read */
870 sb_fd_write, /* sbi_write */
871 sb_fd_close /* sbi_close */
879 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
881 assert( sbiod != NULL );
886 sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
887 if ( sbiod->sbiod_pvt == NULL )
889 strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
894 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
896 assert( sbiod != NULL );
897 assert( sbiod->sbiod_pvt != NULL );
899 LBER_FREE( sbiod->sbiod_pvt );
900 sbiod->sbiod_pvt = NULL;
905 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
907 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
911 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
915 ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
917 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
918 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
919 (long)len, STRERROR( errno ) );
922 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
923 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
924 (long)len, (long)ret );
925 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
926 (const char *)buf, ret );
932 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
936 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
938 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
939 "%swrite: want=%ld error=%s\n",
940 (char *)sbiod->sbiod_pvt, (long)len,
944 ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
945 "%swrite: want=%ld, written=%ld\n",
946 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
947 ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
948 (const char *)buf, ret );
953 Sockbuf_IO ber_sockbuf_io_debug =
955 sb_debug_setup, /* sbi_setup */
956 sb_debug_remove, /* sbi_remove */
957 sb_debug_ctrl, /* sbi_ctrl */
958 sb_debug_read, /* sbi_read */
959 sb_debug_write, /* sbi_write */