Changeset 08f5bd75ad170e6b8177b93e98f40d0f8a51b9d2

Show
Ignore:
Timestamp:
08/14/10 20:42:42 (22 months ago)
Author:
Antti-Juhani Kaijanaho <antti-juhani@…>
Children:
994811461679afe70ab81e079fd87191d609be9d
Parents:
61975465b66e572def6105480f10917981b1ef0d
git-committer:
Antti-Juhani Kaijanaho <antti-juhani@…> (08/14/10 20:42:42)
Message:

[tls::session] Use ring buffers instead of dynamically growing buffers

This way enbuffering cannot throw bad_alloc.

Closes #69.

Signed-off-by: Antti-Juhani Kaijanaho <antti-juhani@…>

Location:
tls
Files:
2 added
2 modified

Legend:

Unmodified
Added
Removed
  • tls/session.hh

    r8d4f7f7 r08f5bd7  
    2121#define GUARD_TLS_SESSION_HH 
    2222 
     23#include "ringbuf.hh" 
    2324#include "error_category.hh" 
    2425#include "init.hh" 
     
    4041                public boost::enable_shared_from_this<session_impl<Stream> > 
    4142        { 
     43                enum { ringbufsize = 4096 }; 
    4244        public: 
    4345                typedef boost::shared_ptr<session_impl<Stream> > ptr; 
     
    4951                        , stream(si) 
    5052                        , strand(stream.get_io_service()) 
    51                         , ins_low(0) 
    52                         , ins_high(0) 
     53                        , ins(ringbufsize) 
    5354                        , read_active(false) 
    54                         , outs_low(0) 
     55                        , outs(ringbufsize) 
    5556                        , write_active(false) 
    5657                        { init(tls_init, ce); } 
     
    6162                        , stream(si) 
    6263                        , strand(stream.get_io_service()) 
    63                         , ins_low(0) 
    64                         , ins_high(0) 
     64                        , ins(ringbufsize) 
    6565                        , read_active(false) 
    66                         , outs_low(0) 
     66                        , outs(ringbufsize) 
    6767                        , write_active(false) 
    6868                        { init(tls_init, ce); } 
     
    102102                gnutls_session_t gs; 
    103103 
    104                 /* the stuff that has been read but not yet passed on 
    105                  * is between ins_low and ins_high */ 
    106                 std::vector<unsigned char> ins; 
    107                 size_t ins_low, ins_high; 
     104                ringbuf ins; 
    108105                bool read_active; 
    109106                 
    110                 /* the stuff that has been buffered for sending but 
    111                  * not yet sent is between outs_low and the end of 
    112                  * outs */ 
    113                 std::vector<unsigned char> outs; 
    114                 size_t outs_low; 
     107                ringbuf outs; 
    115108                bool write_active; 
    116109 
  • tls/session_impl.hh

    rae733bf r08f5bd7  
    6666        ssize_t session_impl<Stream>::push(const void *b, size_t n) 
    6767        { 
    68                 const unsigned char *cs = static_cast<const unsigned char *>(b); 
    69                 for (size_t i = 0; i < n; i++) 
    70                 { 
    71                         outs.push_back(cs[i]); 
    72                 } 
    73                 return n; 
     68                if (outs.full()) 
     69                { 
     70                        errno = EAGAIN; 
     71                        return -1; 
     72                } 
     73                return outs.put(static_cast<const unsigned char *>(b), n); 
    7474        } 
    7575 
    7676        /* never call directly!  (called by gnutls) */ 
    7777        template <typename Stream> 
    78         ssize_t session_impl<Stream>::pull(void *b, size_t n_wanted) 
    79         { 
    80                 unsigned char *cs = static_cast<unsigned char *>(b); 
    81                 if (ins_high - ins_low > 0) 
    82                 { 
    83                         size_t n = ins_high - ins_low < n_wanted  
    84                                 ?  ins_high - ins_low  
    85                                 :  n_wanted; 
    86                         for (size_t i = 0; i < n; i++) 
    87                         { 
    88                                 cs[i] = ins[ins_low+i]; 
    89                         } 
    90                         ins_low += n; 
    91                         return n; 
    92                 } 
    93                 errno = EAGAIN; 
    94                 return -1; 
     78        ssize_t session_impl<Stream>::pull(void *b, size_t n) 
     79        { 
     80                if (ins.empty()) 
     81                { 
     82                        errno = EAGAIN; 
     83                        return -1; 
     84                } 
     85                return ins.get(static_cast<unsigned char *>(b), n); 
    9586        } 
    9687 
     
    9990        { 
    10091                if (write_active) return; 
    101                 if (outs_low > 0 && outs_low == outs.size()) 
    102                 { 
    103                         outs.clear(); 
    104                         outs_low = 0; 
    105                 } 
    106                 else if (outs_low > 4096) 
    107                 { 
    108                         outs.erase(outs.begin(), outs.begin() + outs_low); 
    109                         outs_low = 0; 
    110                 } 
    111                 if (outs_low < outs.size()) 
     92                if (!outs.empty()) 
    11293                { 
    11394                        stream.async_write_some 
    114                                 (boost::asio::buffer(outs.data()+outs_low, 
    115                                                      outs.size()-outs_low), 
     95                                (outs.read_area(), 
    11696                                 strand.wrap(boost::bind 
    11797                                             (&sent_some, 
     
    126106        { 
    127107                if (read_active) return; 
    128                 if (ins_low > 0 && ins_low == ins.size()) 
    129                 { 
    130                         ins.clear(); 
    131                         ins_low = 0; 
    132                         ins_high = 0; 
    133                 } 
    134                 else if (ins_low > 4096) 
    135                 { 
    136                         ins.erase(ins.begin(), ins.begin() + ins_low); 
    137                         ins_high -= ins_low; 
    138                         ins_low = 0; 
    139                 } 
    140  
    141                 if (ins_high + 4096 >= ins.size()) ins.resize(ins_high + 4096); 
    142108                stream.async_read_some 
    143                         (boost::asio::buffer(ins.data()+ins_high, 
    144                                              ins.size()-ins_high), 
     109                        (ins.write_area(), 
    145110                         strand.wrap(boost::bind 
    146111                                     (&received_some, this->shared_from_this(), 
     
    171136                self->read_active = false; 
    172137                if (ec == boost::asio::error::operation_aborted) return; 
    173                 if (ec) self->pending_error = ec; else self->ins_high += n; 
     138                if (ec) self->pending_error = ec; else self->ins.written(n); 
    174139                self->post_pending_actions(); 
    175140        } 
     
    183148                if (ec == boost::asio::error::operation_aborted) return; 
    184149                if (ec) { self->pending_error = ec; return; } 
    185                 self->outs_low += n; 
     150                self->outs.read(n); 
    186151                self->post_pending_actions(); 
    187152        }