/* sockbuf.c - i/o routines with support for adding i/o layers. */
+/* $OpenLDAP$ */
/*
* Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
#include "portable.h"
#include <stdio.h>
-#include <stdlib.h>
+
+#include <ac/stdlib.h>
#include <ac/ctype.h>
#include <ac/errno.h>
#define sockbuf_io_read( sb, buf, len ) \
((sb)->sb_io->sbi_read( (sb), (buf), (len) ))
-static long have_no_read( Sockbuf *sb, void *buf, long len );
-static long have_no_write( Sockbuf *sb, void *buf, long len );
+static ber_slen_t have_no_read( Sockbuf *sb, void *buf, ber_len_t len );
+static ber_slen_t have_no_write( Sockbuf *sb, void *buf, ber_len_t len );
static int have_no_close( Sockbuf *sb );
static Sockbuf_IO sb_IO_None=
update_status( Sockbuf *sb )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
sb->sb_buf_ready = (sb->sb_buf.buf_ptr < sb->sb_buf.buf_end);
#ifdef USE_SASL
#endif
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
obr = sb->sb_buf_ready;
#ifdef USE_SASL
#endif
#ifdef USE_SASL
-static long
-packet_length( char *buf )
+static ber_len_t
+packet_length( Sockbuf *sb, const char *buf )
{
- long size;
+ ber_len_t size;
assert( buf != NULL );
- size = (((unsigned long)buf[0])<<24)|
- (((unsigned long)buf[1])<<16)|
- (((unsigned long)buf[2])<<8)|
- (((unsigned long)buf[3]));
+ size = (((ber_len_t)buf[0])<<24)|
+ (((ber_len_t)buf[1])<<16)|
+ (((ber_len_t)buf[2])<<8)|
+ (((ber_len_t)buf[3]));
- if ((size<0) || (size>MAX_BUF_SIZE)) {
+ if ( size > MAX_BUF_SIZE ) {
/* somebody is trying to mess me up. */
- lber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug,
- "SASL: received packet length of %d bytes\n",
- size );
+ ber_log_printf( LDAP_DEBUG_SASL, sb->sb_debug,
+ "SASL: received packet length of %lu bytes\n",
+ (unsigned long) size );
size = 16; /* this should lead to an error. */
}
#endif
static int
-grow_buffer( Sockbuf_Buf * buf, long minsize )
+grow_buffer( Sockbuf_Buf * buf, ber_len_t minsize )
{
- long pw;;
+ ber_len_t pw;;
assert( buf != NULL );
if ((buf->buf_base==NULL) || ((buf->buf_end==0) && (buf->buf_ptr==0))) {
/* empty buffer */
if (buf->buf_base!=NULL)
- free( buf->buf_base );
+ LBER_FREE( buf->buf_base );
assert( buf->buf_ptr==0 );
assert( buf->buf_end==0 );
- buf->buf_base = malloc( minsize );
+ buf->buf_base = LBER_MALLOC( minsize );
if (buf->buf_base==NULL)
return -1;
} else {
char *nb;
- nb = realloc( buf->buf_base, minsize );
+ nb = LBER_REALLOC( buf->buf_base, minsize );
if (nb==NULL)
return -1;
buf->buf_base = nb;
}
#ifdef USE_SASL
-static long
-sockbuf_sec_release( Sockbuf *sb, char *buf, long len )
+static ber_slen_t
+sockbuf_sec_release( Sockbuf *sb, char *buf, ber_len_t len )
{
/* when this is called:
* sb->sb_sec_buf_in.buf_base points to a packet.
assert( buf != NULL );
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( sb->sb_sec );
assert( sb->sb_sec->sbs_release );
ptr+=size;
if (ptr+4<=end)
- size = packet_length( ptr );
+ size = packet_length( sb, ptr );
/* size is always at least 4, so the loop condition is always OK !!*/
assert( size>=4 );
assert( buf != NULL );
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
assert( sb->sb_sec_out.buf_end == 0 );
assert( sb->sb_sec_out.buf_ptr == 0 );
}
#endif
-static long
-sockbuf_copy_out( Sockbuf *sb, char **buf, long len )
+static ber_len_t
+sockbuf_copy_out( Sockbuf *sb, char **buf, ber_len_t len )
{
- long blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr );
+ ber_len_t blen = (sb->sb_buf.buf_end - sb->sb_buf.buf_ptr );
assert( buf != NULL );
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( status_is_ok(sb) );
if (blen) {
- long rlen = (blen<len) ? blen : len;
+ ber_len_t rlen = (blen<len) ? blen : len;
memcpy( *buf, sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, rlen );
sb->sb_buf.buf_ptr+=rlen;
*buf+=rlen;
Sockbuf *ber_sockbuf_alloc( void )
{
- Sockbuf *sb = calloc(1, sizeof(Sockbuf));
+ Sockbuf *sb;
+
+ ber_int_options.lbo_valid = LBER_INITIALIZED;
+
+ sb = LBER_CALLOC(1, sizeof(Sockbuf));
if( sb == NULL ) return NULL;
return sb;
}
-Sockbuf *ber_sockbuf_alloc_fd( int fd )
+Sockbuf *ber_sockbuf_alloc_fd( ber_socket_t fd )
{
Sockbuf *sb = ber_sockbuf_alloc();
void ber_sockbuf_free( Sockbuf *sb )
{
assert(sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
ber_pvt_sb_destroy( sb );
- free(sb);
+ LBER_FREE(sb);
}
-long
-ber_pvt_sb_read( Sockbuf *sb, void *buf_arg, long len )
+ber_slen_t
+ber_pvt_sb_read( Sockbuf *sb, void *buf_arg, ber_len_t len )
{
char *buf;
- long ret;
+ ber_slen_t ret;
assert( buf_arg != NULL );
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( status_is_ok(sb) );
-#if 0
- /* breaks slapd :-< */
+
+ /* slapd might have problems with this */
assert( ber_pvt_sb_in_use( sb ) );
-#endif
#ifdef TEST_PARTIAL_READ
if ((rand() & 3)==1) { /* 1 out of 4 */
#ifdef USE_SASL
if (sb->sb_sec) {
- int max;
+ ber_slen_t max;
assert( sb->sb_sec->sbs_release );
assert( sb->sb_sec_buf_in.buf_base );
if (sb->sb_read_ahead) {
}
/* calculate the packet length. */
sb->sb_sec_buf_in.buf_end =
- packet_length(sb->sb_sec_buf_in.buf_base );
+ packet_length(sb, sb->sb_sec_buf_in.buf_base );
if ((sb->sb_sec_buf_in.buf_end > sb->sb_sec_buf_in.buf_size) &&
(grow_buffer( &(sb->sb_sec_buf_in), sb->sb_sec_buf_in.buf_end)<0)) {
/* buffer has to be to big. exit with error. */
ret = -1;
goto do_return;
}
- if (sb->sb_sec_buf_in.buf_ptr >= sb_sec_buf_in.buf_end) {
+ if (sb->sb_sec_buf_in.buf_ptr >= sb->sb_sec_buf_in.buf_end) {
/* finished packet. decode it. */
goto decode_packet;
}
} else {
#endif
if (sb->sb_read_ahead) {
- long max;
+ ber_slen_t max;
max = sb->sb_buf.buf_size - sb->sb_buf.buf_end;
- if (max>len) {
+ if (max> (ber_slen_t) len) {
for(;;) {
ret = sockbuf_io_read( sb,
sb->sb_buf.buf_base +
long sockbuf_do_write( Sockbuf *sb )
{
long to_go;
+ ber_slen_t ret;
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
to_go = sb->sb_sec_out.buf_end - sb->sb_sec_out.buf_ptr;
assert( to_go > 0 );
}
#endif
-long ber_pvt_sb_write( Sockbuf *sb, void *buf, long len_arg )
+ber_slen_t ber_pvt_sb_write( Sockbuf *sb, void *buf, ber_len_t len_arg )
{
- long ret;
- long len = len_arg;
+ ber_slen_t ret;
+ ber_len_t len = len_arg;
+
+ assert( buf != NULL );
+ assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( status_is_ok(sb) );
-#if 0
- /* unfortunately breaks slapd */
+
+ /* slapd might have problems with this */
assert( ber_pvt_sb_in_use( sb ) );
-#endif
+
#ifdef TEST_PARTIAL_WRITE
if ((rand() & 3)==1) { /* 1 out of 4 */
errno = EWOULDBLOCK;
int ret;
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( sb->sb_io );
assert( sb->sb_io->sbi_close );
assert( status_is_ok(sb) );
int ber_pvt_sb_set_readahead( Sockbuf *sb, int rh )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( status_is_ok(sb) );
sb->sb_read_ahead = (rh!=0);
return 0;
}
+int ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
+{
+#if HAVE_FCNTL
+ int flags = fcntl(ber_pvt_sb_get_desc(sb), F_GETFL);
+ if( nb ) {
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~O_NONBLOCK;
+ }
+ return fcntl( ber_pvt_sb_get_desc(sb), F_SETFL, flags );
+
+#elif defined( FIONBIO )
+ ioctl_t status = nb ? 1 : 0;
+ return ioctl( sd, FIONBIO, &status );
+#endif
+}
+
#define USE_NONBLOCK
#ifdef USE_NONBLOCK
int ber_pvt_sb_set_nonblock( Sockbuf *sb, int nb )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( status_is_ok(sb) );
if (nb) {
sb->sb_non_block = 1;
sb->sb_read_ahead = 0;
#endif
}
- if (ber_pvt_sb_in_use(sb)) {
-#if HAVE_FCNTL
- int flags = fcntl(ber_pvt_sb_get_desc(sb), F_GETFL);
- flags |= O_NONBLOCK;
- return fcntl(ber_pvt_sb_get_desc(sb), F_SETFL, flags);
-
-#elif defined( FIONBIO )
- /* WINSOCK requires the status to be a long */
- ioctl_t status = (nb!=0);
- return ioctl( ber_pvt_sb_get_desc(sb), FIONBIO, &status );
-#endif /* FIONBIO */
- }
- return 0;
+ if (ber_pvt_sb_in_use(sb)) {
+ return ber_pvt_socket_set_nonblock(
+ ber_pvt_sb_get_desc(sb), nb );
+ }
+ return 0;
}
#endif
assert( buf != NULL);
if (buf->buf_base)
- free( buf->buf_base );
+ LBER_FREE( buf->buf_base );
sockbuf_buf_init( buf );
return 0;
}
{
assert( sb != NULL);
- sb->sb_item_type=LBER_ITEM_SOCKBUF;
+ ber_int_options.lbo_valid = LBER_INITIALIZED;
+
+ sb->sb_valid=LBER_VALID_SOCKBUF;
sb->sb_options = 0;
sb->sb_debug = 0;
sb->sb_trans_ready = 0;
#ifdef USE_SASL
sb->sb_sec_ready = 0;
#endif
- sb->sb_read_ahead = 0;
+ sb->sb_read_ahead = 1; /* test */
sb->sb_non_block = 0;
+ sb->sb_trans_needs_read = 0;
+ sb->sb_trans_needs_write = 0;
sb->sb_fd = -1;
sb->sb_iodata = NULL;
sb->sb_io = &sb_IO_None;
sb->sb_sdata = NULL;
sb->sb_sec = NULL;
sb->sb_sec_prev_len = 0;
-#endif
+#endif
+
+ assert( SOCKBUF_VALID( sb ) );
return 0;
}
int ber_pvt_sb_destroy( Sockbuf *sb )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID(sb) );
#ifdef USE_SASL
ber_pvt_sb_clear_sec(sb);
sockbuf_buf_destroy( &(sb->sb_sec_buf_in) );
{
int len;
assert( sb != NULL);
+ assert( SOCKBUF_VALID( *sb ) );
if ((sb->sb_sec) || (sec==NULL))
return -1;
memcpy( sb->sb_sec_buf_in.buf_base,
sb->sb_buf.buf_base + sb->sb_buf.buf_ptr, len );
sb->sb_sec_buf_in.buf_ptr = len;
- sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb->sb_sec_buf_in ) : 0;
+ sb->sb_sec_buf_in.buf_end = (len>4) ? packet_length( sb, sb->sb_sec_buf_in ) : 0;
sb->sb_buf.buf_ptr = sb->sb_buf.buf_end = 0;
}
- update_status();
+ update_status( sb );
return 0;
}
int ber_pvt_sb_clear_sec( Sockbuf *sb )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
if (sb->sb_buf.buf_ptr!=0)
return -1;
int ber_pvt_sb_set_io( Sockbuf *sb, Sockbuf_IO *trans, void *arg )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
assert( sb->sb_io == &sb_IO_None );
if (trans==NULL)
int ber_pvt_sb_clear_io( Sockbuf *sb )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
+
if (sb->sb_io==&sb_IO_None)
return -1;
sb->sb_io = &sb_IO_None;
sb->sb_trans_ready = 0;
-
+ sb->sb_trans_needs_read = 0;
+ sb->sb_trans_needs_write = 0;
+
return 0;
}
* Support for TCP
*/
-static long
-stream_read( Sockbuf *sb, void *buf, long len )
+static ber_slen_t
+stream_read( Sockbuf *sb, void *buf, ber_len_t len )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
#if defined(MACOS)
/*
{
int rc;
rc = recv( ber_pvt_sb_get_desc(sb), buf, len, 0 );
+
#ifdef HAVE_WINSOCK
- if ( rc < 0 ) errno = WSAGetLastError();
+ if ( rc < 0 )
+ {
+ int err;
+
+ err = WSAGetLastError();
+ errno = err;
+ }
#endif
+
return rc;
}
#elif defined( HAVE_NCSA )
#endif
}
-static long
-stream_write( Sockbuf *sb, void *buf, long len )
+static ber_slen_t
+stream_write( Sockbuf *sb, void *buf, ber_len_t len )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
#if defined(MACOS)
/*
int rc;
rc = send( ber_pvt_sb_get_desc(sb), buf, len, 0 );
#ifdef HAVE_WINSOCK
- if ( rc < 0 ) errno = WSAGetLastError();
+ if ( rc < 0 )
+ {
+ int err;
+ err = WSAGetLastError();
+ errno = err;
+ }
#endif
return rc;
}
stream_close( Sockbuf *sb )
{
assert( sb != NULL);
+ assert( SOCKBUF_VALID( sb ) );
tcp_close( ber_pvt_sb_get_desc( sb ) );
return 0;
}
dgram_setup( Sockbuf *sb, void *arg )
{
assert( sb != NULL);
- sb->sb_iodata = malloc( sizeof( struct dgram_data ) );
+ assert( SOCKBUF_VALID( sb ) );
+
+ sb->sb_iodata = LBER_MALLOC( sizeof( struct dgram_data ) );
if (sb->sb_iodata==NULL)
return -1;
sb->sb_read_ahead = 1; /* important since udp is packet based. */
dgram_release( Sockbuf *sb )
{
assert( sb != NULL);
- free( sb->sb_iodata );
+ assert( SOCKBUF_VALID( sb ) );
+
+ LBER_FREE( sb->sb_iodata );
return 0;
}
-static long
-dgram_read( Sockbuf *sb, void *buf, long len )
+static ber_slen_t
+dgram_read( Sockbuf *sb, void *buf, ber_len_t len )
{
#ifdef LDAP_CONNECTIONLESS
- long rc;
- int addrlen;
+ ber_slen_t rc;
+ socklen_t addrlen;
struct dgram_data *dd;
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( buf != NULL );
dd = (struct dgram_data *)(sb->sb_iodata);
if ( sb->sb_debug ) {
ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
- "dgram_read udp_read %d bytes\n",
- rc );
+ "dgram_read udp_read %ld bytes\n",
+ (long) rc );
if ( rc > 0 )
ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug,
buf, rc );
# endif /* LDAP_CONNECTIONLESS */
}
-static long
-dgram_write( Sockbuf *sb, void *buf, long len )
+static ber_slen_t
+dgram_write( Sockbuf *sb, void *buf, ber_len_t len )
{
#ifdef LDAP_CONNECTIONLESS
- int rc;
+ ber_slen_t rc;
struct dgram_data *dd;
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( buf != NULL );
dd = (struct dgram_data *)(sb->sb_iodata);
dgram_close( Sockbuf *sb )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
tcp_close( ber_pvt_sb_get_desc(sb) );
return 0;
{
struct dgram_data *dd;
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( sb->sb_io == &ber_pvt_sb_io_udp );
dd = (struct dgram_data *) (sb->sb_iodata);
memcpy( &(dd->dst), addr, sizeof( struct sockaddr ) );
void *ber_pvt_sb_udp_get_src( Sockbuf *sb )
{
struct dgram_data *dd;
+
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
assert( sb->sb_io == &ber_pvt_sb_io_udp );
dd = (struct dgram_data *) (sb->sb_iodata);
return &(dd->src);
* break the servers.
*/
-static long
-have_no_read( Sockbuf *sb, void *buf, long len )
+static ber_slen_t
+have_no_read( Sockbuf *sb, void *buf, ber_len_t len )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
"warning: reading from uninitialized sockbuf\n");
errno = EBADF;
return -1;
}
-static long
-have_no_write( Sockbuf *sb, void *buf, long len )
+static ber_slen_t
+have_no_write( Sockbuf *sb, void *buf, ber_len_t len )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
ber_log_printf( LDAP_DEBUG_ANY, ber_int_debug,
"warning: writing to uninitialized sockbuf\n");
errno = EBADF;
have_no_close( Sockbuf *sb )
{
assert( sb != NULL );
+ assert( SOCKBUF_VALID( sb ) );
+
assert( 0 );
return -1;
}