]> git.sur5r.net Git - openldap/blob - libraries/liblber/sockbuf.c
ITS#4046 fix from HEAD
[openldap] / libraries / liblber / sockbuf.c
1 /* sockbuf.c - i/o routines with support for adding i/o layers. */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/stdlib.h>
22
23 #include <ac/ctype.h>
24 #include <ac/errno.h>
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/unistd.h>
28
29 #ifdef HAVE_IO_H
30 #include <io.h>
31 #endif /* HAVE_IO_H */
32
33 #if defined( HAVE_FCNTL_H )
34 #include <fcntl.h>
35 #endif
36
37 #if defined( HAVE_SYS_FILIO_H )
38 #include <sys/filio.h>
39 #elif defined( HAVE_SYS_IOCTL_H )
40 #include <sys/ioctl.h>
41 #endif
42
43 #include "lber-int.h"
44
45 #ifndef LBER_MIN_BUFF_SIZE
46 #define LBER_MIN_BUFF_SIZE              4096
47 #endif
48 #ifndef LBER_MAX_BUFF_SIZE
49 #define LBER_MAX_BUFF_SIZE              65536
50 #endif
51 #ifndef LBER_DEFAULT_READAHEAD
52 #define LBER_DEFAULT_READAHEAD  16384
53 #endif
54
55 Sockbuf *
56 ber_sockbuf_alloc( void )
57 {
58         Sockbuf                 *sb;
59
60         ber_int_options.lbo_valid = LBER_INITIALIZED;
61
62         sb = LBER_CALLOC( 1, sizeof( Sockbuf ) );
63
64         if( sb == NULL ) return NULL;
65
66         ber_int_sb_init( sb );
67         return sb;
68 }
69
70 void
71 ber_sockbuf_free( Sockbuf *sb )
72 {
73         assert( sb != NULL );
74         assert( SOCKBUF_VALID( sb ) );
75
76         ber_int_sb_close( sb );
77         ber_int_sb_destroy( sb );
78         LBER_FREE( sb );
79 }
80
81 /* Return values: -1: error, 0: no operation performed or the answer is false,
82  * 1: successful operation or the answer is true
83  */
84 int
85 ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
86 {
87         Sockbuf_IO_Desc         *p;
88         int                     ret = 0;
89
90         assert( sb != NULL );
91         assert( SOCKBUF_VALID( sb ) );
92
93         switch ( opt ) {
94                 case LBER_SB_OPT_HAS_IO:
95                         p = sb->sb_iod;
96                         while ( p && p->sbiod_io != (Sockbuf_IO *)arg ) {
97                                 p = p->sbiod_next;
98                         }
99    
100                         if ( p ) {
101                                 ret = 1;
102                         }
103                         break;
104
105                 case LBER_SB_OPT_GET_FD:
106                         if ( arg != NULL ) {
107                                 *((int *)arg) = sb->sb_fd;
108                         }
109                         ret = ( sb->sb_fd == AC_SOCKET_INVALID ? -1 : 1);
110                         break;
111
112                 case LBER_SB_OPT_SET_FD:
113                         sb->sb_fd = *((int *)arg);
114                         ret = 1;
115                         break;
116
117                 case LBER_SB_OPT_SET_NONBLOCK:
118                         ret = ber_pvt_socket_set_nonblock( sb->sb_fd, arg != NULL)
119                                 ? -1 : 1;
120                         break;
121
122                 case LBER_SB_OPT_DRAIN: {
123                                 /* Drain the data source to enable possible errors (e.g.
124                                  * TLS) to be propagated to the upper layers
125                                  */
126                                 char buf[LBER_MIN_BUFF_SIZE];
127
128                                 do {
129                                         ret = ber_int_sb_read( sb, buf, sizeof( buf ) );
130                                 } while ( ret == sizeof( buf ) );
131
132                                 ret = 1;
133                         } break;
134
135                 case LBER_SB_OPT_NEEDS_READ:
136                         ret = ( sb->sb_trans_needs_read ? 1 : 0 );
137                         break;
138
139                 case LBER_SB_OPT_NEEDS_WRITE:
140                         ret = ( sb->sb_trans_needs_write ? 1 : 0 );
141                         break;
142
143                 case LBER_SB_OPT_GET_MAX_INCOMING:
144                         if ( arg != NULL ) {
145                                 *((ber_len_t *)arg) = sb->sb_max_incoming;
146                         }
147                         ret = 1;
148                         break;
149
150                 case LBER_SB_OPT_SET_MAX_INCOMING:
151                         sb->sb_max_incoming = *((ber_len_t *)arg);
152                         ret = 1;
153                         break;
154
155                 default:
156                         ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod, opt, arg );
157                         break;
158    }
159
160         return ret;
161 }
162
163 int
164 ber_sockbuf_add_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer, void *arg )
165 {
166         Sockbuf_IO_Desc         *d, *p, **q;
167    
168         assert( sb != NULL );
169         assert( SOCKBUF_VALID( sb ) );
170    
171         if ( sbio == NULL ) {
172                 return -1;
173         }
174    
175         q = &sb->sb_iod;
176         p = *q;
177         while ( p && p->sbiod_level > layer ) {
178                 q = &p->sbiod_next;
179                 p = *q;
180         }
181    
182         d = LBER_MALLOC( sizeof( *d ) );
183         if ( d == NULL ) {
184                 return -1;
185         }
186    
187         d->sbiod_level = layer;
188         d->sbiod_sb = sb;
189         d->sbiod_io = sbio;
190         memset( &d->sbiod_pvt, '\0', sizeof( d->sbiod_pvt ) );
191         d->sbiod_next = p;
192         *q = d;
193
194         if ( sbio->sbi_setup != NULL && ( sbio->sbi_setup( d, arg ) < 0 ) ) {
195                 return -1;
196         }
197
198         return 0;
199 }
200    
201 int
202 ber_sockbuf_remove_io( Sockbuf *sb, Sockbuf_IO *sbio, int layer )
203 {
204         Sockbuf_IO_Desc         *p, **q;
205
206         assert( sb != NULL );
207         assert( SOCKBUF_VALID( sb ) );
208    
209         if ( sb->sb_iod == NULL ) {
210                 return -1;
211         }
212    
213         q = &sb->sb_iod;
214         while ( *q != NULL ) {
215                 p = *q;
216                 if ( layer == p->sbiod_level && p->sbiod_io == sbio ) {
217                         if ( p->sbiod_io->sbi_remove != NULL &&
218                                 p->sbiod_io->sbi_remove( p ) < 0 )
219                         {
220                                 return -1;
221                         }
222                         *q = p->sbiod_next;
223                         LBER_FREE( p );
224                 break;
225                 }
226                 q = &p->sbiod_next;
227         }
228
229         return 0;
230 }
231
232 void
233 ber_pvt_sb_buf_init( Sockbuf_Buf *buf )
234 {
235         buf->buf_base = NULL;
236         buf->buf_ptr = 0;
237         buf->buf_end = 0;
238         buf->buf_size = 0;
239 }
240
241 void
242 ber_pvt_sb_buf_destroy( Sockbuf_Buf *buf )
243 {
244         assert( buf != NULL);
245
246         if (buf->buf_base) {
247                 LBER_FREE( buf->buf_base );
248         }
249         ber_pvt_sb_buf_init( buf );
250 }
251
252 int
253 ber_pvt_sb_grow_buffer( Sockbuf_Buf *buf, ber_len_t minsize )
254 {
255         ber_len_t               pw;
256         char                    *p;
257    
258         assert( buf != NULL );
259
260         for ( pw = LBER_MIN_BUFF_SIZE; pw < minsize; pw <<= 1 ) {
261                 if (pw > LBER_MAX_BUFF_SIZE) return -1;
262         }
263
264         if ( buf->buf_size < pw ) {
265                 p = LBER_REALLOC( buf->buf_base, pw );
266                 if ( p == NULL ) return -1;
267                 buf->buf_base = p;
268                 buf->buf_size = pw;
269         }
270         return 0;
271 }
272
273 ber_len_t
274 ber_pvt_sb_copy_out( Sockbuf_Buf *sbb, char *buf, ber_len_t len )
275 {
276         ber_len_t               max;
277
278         assert( buf != NULL );
279         assert( sbb != NULL );
280 #if 0
281         assert( sbb->buf_size > 0 );
282 #endif
283
284         max = sbb->buf_end - sbb->buf_ptr;
285         max = ( max < len) ? max : len;
286         if ( max ) {
287                 AC_MEMCPY( buf, sbb->buf_base + sbb->buf_ptr, max );
288                 sbb->buf_ptr += max;
289                 if ( sbb->buf_ptr >= sbb->buf_end ) {
290                         sbb->buf_ptr = sbb->buf_end = 0;
291                 }
292    }
293         return max;
294 }
295
296 ber_slen_t
297 ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out )
298 {
299         ber_len_t               to_go;
300         ber_slen_t ret;
301
302         assert( sbiod != NULL );
303         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
304
305         to_go = buf_out->buf_end - buf_out->buf_ptr;
306         assert( to_go > 0 );
307    
308         for(;;) {
309                 ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf_out->buf_base +
310                         buf_out->buf_ptr, to_go );
311 #ifdef EINTR
312                 if ((ret<0) && (errno==EINTR)) continue;
313 #endif
314                 break;
315         }
316
317         if ( ret <= 0 ) return ret;
318    
319         buf_out->buf_ptr += ret;
320         if (buf_out->buf_ptr == buf_out->buf_end) {
321                 buf_out->buf_end = buf_out->buf_ptr = 0;
322         }
323
324         return ret;
325 }
326
327 int
328 ber_pvt_socket_set_nonblock( ber_socket_t sd, int nb )
329 {
330 #if HAVE_FCNTL
331         int flags = fcntl( sd, F_GETFL);
332         if( nb ) {
333                 flags |= O_NONBLOCK;
334         } else {
335                 flags &= ~O_NONBLOCK;
336         }
337         return fcntl( sd, F_SETFL, flags );
338                 
339 #elif defined( FIONBIO )
340         ioctl_t status = nb ? 1 : 0;
341         return ioctl( sd, FIONBIO, &status );
342 #endif
343 }
344
345 int
346 ber_int_sb_init( Sockbuf *sb )
347 {
348         assert( sb != NULL);
349
350         sb->sb_valid=LBER_VALID_SOCKBUF;
351         sb->sb_options = 0;
352         sb->sb_debug = ber_int_debug;
353         sb->sb_fd = AC_SOCKET_INVALID;
354         sb->sb_iod = NULL;
355         sb->sb_trans_needs_read = 0;
356         sb->sb_trans_needs_write = 0;
357    
358         assert( SOCKBUF_VALID( sb ) );
359         return 0;
360 }
361    
362 int
363 ber_int_sb_close( Sockbuf *sb )
364 {
365         Sockbuf_IO_Desc         *p;
366
367         assert( sb != NULL);
368    
369         p = sb->sb_iod;
370         while ( p ) {
371                 if ( p->sbiod_io->sbi_close && p->sbiod_io->sbi_close( p ) < 0 ) {
372                         return -1;
373                 }
374                 p = p->sbiod_next;
375         }
376    
377         sb->sb_fd = AC_SOCKET_INVALID;
378    
379         return 0;
380 }
381
382 int
383 ber_int_sb_destroy( Sockbuf *sb )
384 {
385         Sockbuf_IO_Desc         *p;
386
387         assert( sb != NULL);
388         assert( SOCKBUF_VALID( sb ) );
389    
390         while ( sb->sb_iod ) {
391                 p = sb->sb_iod->sbiod_next;
392                 ber_sockbuf_remove_io( sb, sb->sb_iod->sbiod_io,
393                         sb->sb_iod->sbiod_level );
394                 sb->sb_iod = p;
395         }
396
397         return ber_int_sb_init( sb );
398 }
399
400 ber_slen_t
401 ber_int_sb_read( Sockbuf *sb, void *buf, ber_len_t len )
402 {
403         ber_slen_t              ret;
404
405         assert( buf != NULL );
406         assert( sb != NULL);
407         assert( sb->sb_iod != NULL );
408         assert( SOCKBUF_VALID( sb ) );
409
410         for (;;) {
411                 ret = sb->sb_iod->sbiod_io->sbi_read( sb->sb_iod, buf, len );
412
413 #ifdef EINTR    
414                 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
415 #endif
416                 break;
417         }
418
419         return ret;
420 }
421
422 ber_slen_t
423 ber_int_sb_write( Sockbuf *sb, void *buf, ber_len_t len )
424 {
425         ber_slen_t              ret;
426
427         assert( buf != NULL );
428         assert( sb != NULL);
429         assert( sb->sb_iod != NULL );
430         assert( SOCKBUF_VALID( sb ) );
431
432         for (;;) {
433                 ret = sb->sb_iod->sbiod_io->sbi_write( sb->sb_iod, buf, len );
434
435 #ifdef EINTR    
436                 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
437 #endif
438                 break;
439         }
440
441         return ret;
442 }
443
444 /*
445  * Support for TCP
446  */
447
448 static ber_slen_t
449 sb_stream_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
450 {
451         assert( sbiod != NULL);
452         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
453
454 #if defined(MACOS)
455 /*
456  * MacTCP/OpenTransport
457  */
458         return tcpread( sbiod->sbiod_sb->sb_fd, 0, (unsigned char *)buf,
459                 len, NULL );
460
461 #elif defined( HAVE_PCNFS ) || \
462    defined( HAVE_WINSOCK ) || defined ( __BEOS__ )
463 /*
464  * PCNFS (under DOS)
465  */
466 /*
467  * Windows Socket API (under DOS/Windows 3.x)
468  */
469 /*
470  * 32-bit Windows Socket API (under Windows NT or Windows 95)
471  */
472         {
473                 int rc;
474
475                 rc = recv( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
476
477 #ifdef HAVE_WINSOCK
478                 if ( rc < 0 ) {
479                         int err;
480
481                         err = WSAGetLastError();
482                         errno = err;
483                 }
484 #endif
485
486                 return rc;
487         }
488
489 #elif defined( HAVE_NCSA )
490 /*
491  * NCSA Telnet TCP/IP stack (under DOS)
492  */
493         return nread( sbiod->sbiod_sb->sb_fd, buf, len );
494
495 #else
496         return read( sbiod->sbiod_sb->sb_fd, buf, len );
497 #endif
498 }
499
500 static ber_slen_t
501 sb_stream_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
502 {
503         assert( sbiod != NULL);
504         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
505
506 #if defined(MACOS) 
507 /*
508  * MacTCP/OpenTransport
509  */
510 #define MAX_WRITE       65535
511         return tcpwrite( sbiod->sbiod_sb->sb_fd, (unsigned char *)buf,
512                 (len<MAX_WRITE) ? len : MAX_WRITE );
513
514 #elif defined( HAVE_PCNFS) \
515         || defined( HAVE_WINSOCK) || defined ( __BEOS__ )
516 /*
517  * PCNFS (under DOS)
518  */
519 /*
520  * Windows Socket API (under DOS/Windows 3.x)
521  */
522 /*
523  * 32-bit Windows Socket API (under Windows NT or Windows 95)
524  */
525         {
526                 int rc = send( sbiod->sbiod_sb->sb_fd, buf, len, 0 );
527
528 #ifdef HAVE_WINSOCK
529                 if ( rc < 0 ) {
530                         int err;
531                         err = WSAGetLastError();
532                         errno = err;
533                 }
534 #endif
535                 return rc;
536         }
537
538 #elif defined(HAVE_NCSA)
539         return netwrite( sbiod->sbiod_sb->sb_fd, buf, len );
540
541 #elif defined(VMS)
542 /*
543  * VMS -- each write must be 64K or smaller
544  */
545 #define MAX_WRITE 65535
546         return write( sbiod->sbiod_sb->sb_fd, buf,
547                 (len<MAX_WRITE) ? len : MAX_WRITE);
548 #else
549         return write( sbiod->sbiod_sb->sb_fd, buf, len );
550 #endif   
551 }   
552    
553 static int 
554 sb_stream_close( Sockbuf_IO_Desc *sbiod )
555 {
556         assert( sbiod != NULL );
557         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
558         tcp_close( sbiod->sbiod_sb->sb_fd );
559    return 0;
560 }
561
562 /* The argument is a pointer to the socket descriptor */
563 static int
564 sb_stream_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
565         assert( sbiod != NULL );
566
567         if ( arg != NULL ) {
568                 sbiod->sbiod_sb->sb_fd = *((int *)arg);
569         }
570         return 0;
571 }
572
573 static int
574 sb_stream_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
575         /* This is an end IO descriptor */
576         return 0;
577 }
578
579 Sockbuf_IO ber_sockbuf_io_tcp = {
580         sb_stream_setup,        /* sbi_setup */
581         NULL,                           /* sbi_remove */
582         sb_stream_ctrl,         /* sbi_ctrl */
583         sb_stream_read,         /* sbi_read */
584         sb_stream_write,        /* sbi_write */
585         sb_stream_close         /* sbi_close */
586 };
587
588
589 /*
590  * Support for readahead (UDP needs it)
591  */
592
593 static int
594 sb_rdahead_setup( Sockbuf_IO_Desc *sbiod, void *arg )
595 {
596         Sockbuf_Buf             *p;
597
598         assert( sbiod != NULL );
599
600         p = LBER_MALLOC( sizeof( *p ) );
601         if ( p == NULL ) return -1;
602
603         ber_pvt_sb_buf_init( p );
604
605         if ( arg == NULL ) {
606                 ber_pvt_sb_grow_buffer( p, LBER_DEFAULT_READAHEAD );
607         } else {
608                 ber_pvt_sb_grow_buffer( p, *((int *)arg) );
609         }
610
611         sbiod->sbiod_pvt = p;
612         return 0;
613 }
614
615 static int
616 sb_rdahead_remove( Sockbuf_IO_Desc *sbiod )
617 {
618         Sockbuf_Buf             *p;
619
620         assert( sbiod != NULL );
621
622         p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
623
624         if ( p->buf_ptr != p->buf_end ) return -1;
625
626         ber_pvt_sb_buf_destroy( (Sockbuf_Buf *)(sbiod->sbiod_pvt) );
627         LBER_FREE( sbiod->sbiod_pvt );
628         sbiod->sbiod_pvt = NULL;
629
630         return 0;
631 }
632
633 static ber_slen_t
634 sb_rdahead_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
635 {
636         Sockbuf_Buf             *p;
637         ber_slen_t              bufptr = 0, ret, max;
638
639         assert( sbiod != NULL );
640         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
641         assert( sbiod->sbiod_next != NULL );
642
643         p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
644
645         assert( p->buf_size > 0 );
646
647         /* Are there anything left in the buffer? */
648         ret = ber_pvt_sb_copy_out( p, buf, len );
649         bufptr += ret;
650         len -= ret;
651
652         if ( len == 0 ) return bufptr;
653
654         max = p->buf_size - p->buf_end;
655         ret = 0;
656         while ( max > 0 ) {
657                 ret = LBER_SBIOD_READ_NEXT( sbiod, p->buf_base + p->buf_end,
658                         max );
659 #ifdef EINTR    
660                 if ( ( ret < 0 ) && ( errno == EINTR ) ) continue;
661 #endif
662                 break;
663         }
664
665         if ( ret < 0 ) {
666                 return ( bufptr ? bufptr : ret );
667         }
668
669         p->buf_end += ret;
670         bufptr += ber_pvt_sb_copy_out( p, (char *) buf + bufptr, len );
671         return bufptr;
672 }
673
674 static ber_slen_t
675 sb_rdahead_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
676 {
677         assert( sbiod != NULL );
678         assert( sbiod->sbiod_next != NULL );
679
680         return LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
681 }
682
683 static int
684 sb_rdahead_close( Sockbuf_IO_Desc *sbiod )
685 {
686         assert( sbiod != NULL );
687
688         /* Just erase the buffer */
689         ber_pvt_sb_buf_destroy((Sockbuf_Buf *)sbiod->sbiod_pvt);
690         return 0;
691 }
692
693 static int
694 sb_rdahead_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
695 {
696         Sockbuf_Buf             *p;
697
698         p = (Sockbuf_Buf *)sbiod->sbiod_pvt;
699
700         if ( opt == LBER_SB_OPT_DATA_READY ) {
701                 if ( p->buf_ptr != p->buf_end ) {
702                         return 1;
703                 }
704
705         } else if ( opt == LBER_SB_OPT_SET_READAHEAD ) {
706                 if ( p->buf_size >= *((ber_len_t *)arg) ) {
707                         return 0;
708                 }
709                 return ( ber_pvt_sb_grow_buffer( p, *((int *)arg) ) ?
710                         -1 : 1 );
711         }
712
713         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
714 }
715
716 Sockbuf_IO ber_sockbuf_io_readahead = {
717         sb_rdahead_setup,       /* sbi_setup */
718         sb_rdahead_remove,      /* sbi_remove */
719         sb_rdahead_ctrl,        /* sbi_ctrl */
720         sb_rdahead_read,        /* sbi_read */
721         sb_rdahead_write,       /* sbi_write */
722         sb_rdahead_close        /* sbi_close */
723 };
724
725 /*
726  * Support for simple file IO
727  */
728
729 static ber_slen_t
730 sb_fd_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
731 {
732         assert( sbiod != NULL);
733         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
734
735         return read( sbiod->sbiod_sb->sb_fd, buf, len );
736 }
737
738 static ber_slen_t
739 sb_fd_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
740 {
741         assert( sbiod != NULL);
742         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
743
744         return write( sbiod->sbiod_sb->sb_fd, buf, len );
745 }
746
747 static int 
748 sb_fd_close( Sockbuf_IO_Desc *sbiod )
749 {   
750         assert( sbiod != NULL );
751         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
752
753         close( sbiod->sbiod_sb->sb_fd );
754         return 0;
755 }
756
757 /* The argument is a pointer to the file descriptor */
758 static int
759 sb_fd_setup( Sockbuf_IO_Desc *sbiod, void *arg ) {
760         assert( sbiod != NULL );
761
762         if ( arg != NULL )
763                 sbiod->sbiod_sb->sb_fd = *((int *)arg);
764         return 0;
765 }
766
767 static int
768 sb_fd_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) {
769         /* This is an end IO descriptor */
770         return 0;
771 }
772
773 Sockbuf_IO ber_sockbuf_io_fd = {
774         sb_fd_setup,    /* sbi_setup */
775         NULL,                   /* sbi_remove */
776         sb_fd_ctrl,             /* sbi_ctrl */
777         sb_fd_read,             /* sbi_read */
778         sb_fd_write,            /* sbi_write */
779         sb_fd_close             /* sbi_close */
780 };
781
782 /*
783  * Debugging layer
784  */
785
786 static int
787 sb_debug_setup( Sockbuf_IO_Desc *sbiod, void *arg )
788 {
789         assert( sbiod != NULL );
790         
791         if ( arg == NULL ) arg = "sockbuf_";
792
793         sbiod->sbiod_pvt = LBER_MALLOC( strlen( arg ) + 1 );
794         if ( sbiod->sbiod_pvt == NULL ) return -1;
795
796         strcpy( (char *)sbiod->sbiod_pvt, (char *)arg );
797         return 0;
798 }
799
800 static int
801 sb_debug_remove( Sockbuf_IO_Desc *sbiod )
802 {
803         assert( sbiod != NULL );
804         assert( sbiod->sbiod_pvt != NULL );
805
806         LBER_FREE( sbiod->sbiod_pvt );
807         sbiod->sbiod_pvt = NULL;
808         return 0;
809 }
810
811 static int
812 sb_debug_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
813 {
814         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
815 }
816
817 static ber_slen_t
818 sb_debug_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
819 {
820         ber_slen_t              ret;
821
822         ret = LBER_SBIOD_READ_NEXT( sbiod, buf, len );
823         if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
824                 int err = errno;
825                 if ( ret < 0 ) {
826                         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
827                                 "%sread: want=%ld error=%s\n", (char *)sbiod->sbiod_pvt,
828                                 (long)len, STRERROR( errno ) );
829                 } else {
830                         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
831                                 "%sread: want=%ld, got=%ld\n", (char *)sbiod->sbiod_pvt,
832                                 (long)len, (long)ret );
833                         ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
834                                 (const char *)buf, ret );
835                 }
836                 errno = err;
837         }
838         return ret;
839 }
840
841 static ber_slen_t
842 sb_debug_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
843 {
844         ber_slen_t              ret;
845
846         ret = LBER_SBIOD_WRITE_NEXT( sbiod, buf, len );
847         if (sbiod->sbiod_sb->sb_debug & LDAP_DEBUG_PACKETS) {
848                 int err = errno;
849                 if ( ret < 0 ) {
850                         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
851                                 "%swrite: want=%ld error=%s\n",
852                                 (char *)sbiod->sbiod_pvt, (long)len,
853                                 STRERROR( errno ) );
854                 } else {
855                         ber_log_printf( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
856                                 "%swrite: want=%ld, written=%ld\n",
857                                 (char *)sbiod->sbiod_pvt, (long)len, (long)ret );
858                         ber_log_bprint( LDAP_DEBUG_PACKETS, sbiod->sbiod_sb->sb_debug,
859                                 (const char *)buf, ret );
860                 }
861                 errno = err;
862         }
863
864         return ret;
865 }
866
867 Sockbuf_IO ber_sockbuf_io_debug = {
868         sb_debug_setup,         /* sbi_setup */
869         sb_debug_remove,        /* sbi_remove */
870         sb_debug_ctrl,          /* sbi_ctrl */
871         sb_debug_read,          /* sbi_read */
872         sb_debug_write,         /* sbi_write */
873         NULL                            /* sbi_close */
874 };
875
876 #ifdef LDAP_CONNECTIONLESS
877
878 /*
879  * Support for UDP (CLDAP)
880  *
881  * All I/O at this level must be atomic. For ease of use, the sb_readahead
882  * must be used above this module. All data reads and writes are prefixed
883  * with a sockaddr containing the address of the remote entity. Upper levels
884  * must read and write this sockaddr before doing the usual ber_printf/scanf
885  * operations on LDAP messages.
886  */
887
888 static int 
889 sb_dgram_setup( Sockbuf_IO_Desc *sbiod, void *arg )
890 {
891         assert( sbiod != NULL);
892         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
893
894         if ( arg != NULL ) sbiod->sbiod_sb->sb_fd = *((int *)arg);
895         return 0;
896 }
897
898 static ber_slen_t
899 sb_dgram_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
900 {
901         ber_slen_t rc;
902         socklen_t  addrlen;
903         struct sockaddr *src;
904    
905         assert( sbiod != NULL );
906         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
907         assert( buf != NULL );
908
909         addrlen = sizeof( struct sockaddr );
910         src = buf;
911         buf += addrlen;
912         len -= addrlen;
913         rc = recvfrom( sbiod->sbiod_sb->sb_fd, buf, len, 0, src, &addrlen );
914
915         return rc > 0 ? rc+sizeof(struct sockaddr) : rc;
916 }
917
918 static ber_slen_t 
919 sb_dgram_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len )
920 {
921         ber_slen_t rc;
922         struct sockaddr *dst;
923    
924         assert( sbiod != NULL );
925         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
926         assert( buf != NULL );
927
928         dst = buf;
929         buf += sizeof( struct sockaddr );
930         len -= sizeof( struct sockaddr );
931    
932         rc = sendto( sbiod->sbiod_sb->sb_fd, buf, len, 0, dst,
933                 sizeof( struct sockaddr ) );
934
935         if ( rc < 0 ) return -1;
936    
937         /* fake error if write was not atomic */
938         if (rc < len) {
939 # ifdef EMSGSIZE
940                 errno = EMSGSIZE;
941 # endif
942                 return -1;
943         }
944         rc = len + sizeof(struct sockaddr);
945         return rc;
946 }
947
948 static int 
949 sb_dgram_close( Sockbuf_IO_Desc *sbiod )
950 {
951         assert( sbiod != NULL );
952         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
953
954         tcp_close( sbiod->sbiod_sb->sb_fd );
955         return 0;
956 }
957
958 static int
959 sb_dgram_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
960 {
961         /* This is an end IO descriptor */
962         return 0;
963 }
964
965 Sockbuf_IO ber_sockbuf_io_udp =
966 {
967         sb_dgram_setup,         /* sbi_setup */
968         NULL,                   /* sbi_remove */
969         sb_dgram_ctrl,          /* sbi_ctrl */
970         sb_dgram_read,          /* sbi_read */
971         sb_dgram_write,         /* sbi_write */
972         sb_dgram_close          /* sbi_close */
973 };
974
975 #endif  /* LDAP_CONNECTIONLESS */