Changeset 607

Show
Ignore:
Timestamp:
08/22/2005 10:43:26 AM (3 years ago)
Author:
jan
Message:

we can't use mmap() with SSL_write as we don't have guarantee that
after a SSL_ERROR_WANT_WRITE we get the same mmap()ed address as
start pointer. On OpenBSD the start-address is completly random.

Using a local sendbuffer solves this problem.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • branches/lighttpd-merge-1.4.x/src/network_openssl.c

    r502 r607  
    1717#include <string.h> 
    1818#include <stdlib.h> 
     19#include <assert.h> 
    1920 
    2021#include "network.h" 
     
    3031        chunk *c; 
    3132        size_t chunks_written = 0; 
    32          
     33 
     34        /* this is a 64k sendbuffer 
     35         * 
     36         * it has to stay at the same location all the time to satisfy the needs  
     37         * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE 
     38         * 
     39         * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown 
     40         * -> we expect a 64k block to 'leak' in valgrind 
     41         * 
     42         * 
     43         * In reality we would like to use mmap() but we don't have a guarantee that 
     44         * we get the same mmap() address for each call. On openbsd the mmap() address 
     45         * even randomized. 
     46         *   That means either we keep the mmap() open or we do a read() into a  
     47         * constant buffer  
     48         * */ 
     49#define LOCAL_SEND_BUFSIZE (64 * 1024) 
     50        static char *local_send_buffer = NULL; 
     51 
    3352        for(c = cq->first; c; c = c->next) { 
    3453                int chunk_finished = 0; 
     
    103122                        off_t offset; 
    104123                        size_t toSend; 
    105                         char *p; 
    106124                        stat_cache_entry *sce = NULL; 
    107125                        int ifd; 
     
    112130                                return -1; 
    113131                        } 
    114                          
    115                         offset = c->data.file.offset + c->offset; 
    116                         toSend = c->data.file.length - c->offset; 
    117                          
    118                         if (-1 == (ifd = open(c->data.file.name->ptr, O_RDONLY))) { 
    119                                 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); 
     132 
     133                        if (NULL == local_send_buffer) { 
     134                                local_send_buffer = malloc(LOCAL_SEND_BUFSIZE); 
     135                                assert(local_send_buffer); 
     136                        } 
     137 
     138                        do { 
     139                         
     140                                offset = c->data.file.offset + c->offset; 
     141                                toSend = c->data.file.length - c->offset; 
     142 
     143                                if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE; 
     144                         
     145                                if (-1 == (ifd = open(c->data.file.name->ptr, O_RDONLY))) { 
     146                                        log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); 
    120147                                 
    121                                 return -1; 
    122                         } 
    123  
    124                          
    125                         if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) { 
    126                                 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno)); 
    127  
     148                                        return -1; 
     149                                } 
     150 
     151 
     152                                lseek(ifd, offset, SEEK_SET); 
     153                                if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) { 
     154                                        log_error_write(srv, __FILE__, __LINE__, "ss", "read failed: ", strerror(errno)); 
     155                                        return -1; 
     156                                } 
     157 
     158                                s = local_send_buffer; 
     159                         
    128160                                close(ifd); 
    129                                  
    130                                 return -1; 
    131                         } 
    132                          
    133                         close(ifd); 
    134  
    135                         s = p + offset; 
    136                          
    137                         if ((r = SSL_write(con->ssl, s, toSend)) <= 0) { 
    138                                 switch ((ssl_r = SSL_get_error(con->ssl, r))) { 
    139                                 case SSL_ERROR_WANT_WRITE: 
    140                                         break; 
    141                                 case SSL_ERROR_SYSCALL: 
    142                                         switch(errno) { 
    143                                         case EPIPE: 
    144                                                 return -2; 
     161                         
     162                                if ((r = SSL_write(con->ssl, s, toSend)) <= 0) { 
     163                                        switch ((ssl_r = SSL_get_error(con->ssl, r))) { 
     164                                        case SSL_ERROR_WANT_WRITE: 
     165                                                break; 
     166                                        case SSL_ERROR_SYSCALL: 
     167                                                switch(errno) { 
     168                                                case EPIPE: 
     169                                                        return -2; 
     170                                                default: 
     171                                                        log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",  
     172                                                                        ssl_r, r, errno, 
     173                                                                        strerror(errno)); 
     174                                                        break; 
     175                                                } 
     176                                         
     177                                                return  -1; 
     178                                        case SSL_ERROR_ZERO_RETURN: 
     179                                                /* clean shutdown on the remote side */ 
     180                                         
     181                                                if (r == 0)  return -2; 
     182                                         
     183                                                /* fall thourgh */ 
    145184                                        default: 
    146                                                 log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",  
    147                                                                 ssl_r, r, errno, 
    148                                                                 strerror(errno)); 
    149                                                 break; 
     185                                                log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",  
     186                                                                ssl_r, r,  
     187                                                                ERR_error_string(ERR_get_error(), NULL)); 
     188                                         
     189                                                return -1; 
    150190                                        } 
    151                                          
    152                                         return  -1; 
    153                                 case SSL_ERROR_ZERO_RETURN: 
    154                                         /* clean shutdown on the remote side */ 
    155                                          
    156                                         if (r == 0) { 
    157                                                 munmap(p, c->data.file.length); 
    158                                                 return -2; 
    159                                         } 
    160                                          
    161                                         /* fall thourgh */ 
    162                                 default: 
    163                                         log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",  
    164                                                         ssl_r, r,  
    165                                                         ERR_error_string(ERR_get_error(), NULL)); 
    166                                          
    167                                         munmap(p, c->data.file.length); 
    168                                         return -1; 
    169                                 } 
    170                         } else { 
    171                                 c->offset += r; 
    172                                 con->bytes_written += r; 
    173                         } 
    174                          
    175                         munmap(p, c->data.file.length); 
    176                          
    177                         if (c->offset == c->data.file.length) { 
    178                                 chunk_finished = 1; 
    179                         } 
     191                                } else { 
     192                                        c->offset += r; 
     193                                        con->bytes_written += r; 
     194                                } 
     195                         
     196                                if (c->offset == c->data.file.length) { 
     197                                        chunk_finished = 1; 
     198                                } 
     199                        } while(!chunk_finished); 
    180200                         
    181201                        break;