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