]> git.sur5r.net Git - openldap/blobdiff - libraries/liblber/sockbuf.c
Merge remote-tracking branch 'origin/mdb.master' into OPENLDAP_REL_ENG_2_4
[openldap] / libraries / liblber / sockbuf.c
index 27ed84e46653db056e80cc0e8dc2ecaa86bc1fb6..d997e92910954b943e5b3fe7139ff4caaeaf49bf 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2013 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -150,6 +150,20 @@ ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
                        ret = 1;
                        break;
 
+               case LBER_SB_OPT_UNGET_BUF:
+#ifdef LDAP_PF_LOCAL_SENDMSG
+                       sb->sb_ungetlen = ((struct berval *)arg)->bv_len;
+                       if ( sb->sb_ungetlen <= sizeof( sb->sb_ungetbuf )) {
+                               AC_MEMCPY( sb->sb_ungetbuf, ((struct berval *)arg)->bv_val,
+                                       sb->sb_ungetlen );
+                               ret = 1;
+                       } else {
+                               sb->sb_ungetlen = 0;
+                               ret = -1;
+                       }
+#endif
+                       break;
+
                default:
                        ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
                        break;
@@ -325,7 +339,7 @@ ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
 int
 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
 {
-#if HAVE_FCNTL
+#ifdef HAVE_FCNTL
        int flags = fcntl( sd, F_GETFL);
        if( nb ) {
                flags |= O_NONBLOCK;
@@ -527,7 +541,8 @@ sb_stream_close( Sockbuf_IO_Desc *sbiod )
 {
        assert( sbiod != NULL );
        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-       tcp_close( sbiod->sbiod_sb->sb_fd );
+       if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
+               tcp_close( sbiod->sbiod_sb->sb_fd );
    return 0;
 }
 
@@ -704,6 +719,24 @@ sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
        assert( sbiod != NULL);
        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
 
+#ifdef LDAP_PF_LOCAL_SENDMSG
+       if ( sbiod->sbiod_sb->sb_ungetlen ) {
+               ber_len_t blen = sbiod->sbiod_sb->sb_ungetlen;
+               if ( blen > len )
+                       blen = len;
+               AC_MEMCPY( buf, sbiod->sbiod_sb->sb_ungetbuf, blen );
+               buf = (char *) buf + blen;
+               len -= blen;
+               sbiod->sbiod_sb->sb_ungetlen -= blen;
+               if ( sbiod->sbiod_sb->sb_ungetlen ) {
+                       AC_MEMCPY( sbiod->sbiod_sb->sb_ungetbuf,
+                               sbiod->sbiod_sb->sb_ungetbuf+blen,
+                               sbiod->sbiod_sb->sb_ungetlen );
+               }
+               if ( len == 0 )
+                       return blen;
+       }
+#endif
        return read( sbiod->sbiod_sb->sb_fd, buf, len );
 }
 
@@ -722,7 +755,8 @@ sb_fd_close( Sockbuf_IO_Desc *sbiod )
        assert( sbiod != NULL );
        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
 
-       close( sbiod->sbiod_sb->sb_fd );
+       if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
+               close( sbiod->sbiod_sb->sb_fd );
        return 0;
 }
 
@@ -873,7 +907,7 @@ static ber_slen_t
 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
 {
        ber_slen_t rc;
-       socklen_t  addrlen;
+       ber_socklen_t addrlen;
        struct sockaddr *src;
    
        assert( sbiod != NULL );
@@ -882,7 +916,7 @@ sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
 
        addrlen = sizeof( struct sockaddr );
        src = buf;
-       buf += addrlen;
+       buf = (char *) buf + addrlen;
        len -= addrlen;
        rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
 
@@ -900,7 +934,7 @@ sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
        assert( buf != NULL );
 
        dst = buf;
-       buf += sizeof( struct sockaddr );
+       buf = (char *) buf + sizeof( struct sockaddr );
        len -= sizeof( struct sockaddr );
    
        rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
@@ -924,8 +958,9 @@ sb_dgram_close( Sockbuf_IO_Desc *sbiod )
 {
        assert( sbiod != NULL );
        assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
-
-       tcp_close( sbiod->sbiod_sb->sb_fd );
+  
+       if ( sbiod->sbiod_sb->sb_fd != AC_SOCKET_INVALID )
+               tcp_close( sbiod->sbiod_sb->sb_fd );
        return 0;
 }