summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bastien-Filiatrault <joe@x2a.org>2010-09-08 18:34:47 -0400
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-09-09 08:35:07 +0200
commit3774e819df961ce146526d9c9e688ff0f62e0987 (patch)
tree9f34ab0eeb6211520946e5edf3f5e7a72e03d1a0
parent0410e1330971d8230c915b92f8e4a2f96426506d (diff)
downloadgnutls-3774e819df961ce146526d9c9e688ff0f62e0987.tar.gz
Fully mbufferize _gnutls_read and _gnutls_read_buffered.
Signed-off-by: Jonathan Bastien-Filiatrault <joe@x2a.org> Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
-rw-r--r--lib/gnutls_buffers.c77
1 files changed, 37 insertions, 40 deletions
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index c44765f52d..be84e90fc2 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -269,23 +269,36 @@ inline static int get_errno(gnutls_session_t session)
* Flags are only used if the default recv() function is being used.
*/
static ssize_t
-_gnutls_read (gnutls_session_t session, void *iptr,
- size_t sizeOfPtr, gnutls_pull_func pull_func)
+_gnutls_read (gnutls_session_t session, mbuffer_st **bufel,
+ size_t size, gnutls_pull_func pull_func)
{
size_t left;
ssize_t i = 0;
- char *ptr = iptr;
+ char *ptr;
gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
+ if (!bufel)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ *bufel = _mbuffer_alloc (0, size);
+ if (!*bufel)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ ptr = (*bufel)->msg.data;
+
session->internals.direction = 0;
- left = sizeOfPtr;
+ left = size;
while (left > 0)
{
-
reset_errno(session);
- i = pull_func (fd, &ptr[sizeOfPtr - left], left);
+ i = pull_func (fd, &ptr[size - left], left);
if (i < 0)
{
@@ -296,11 +309,11 @@ _gnutls_read (gnutls_session_t session, void *iptr,
if (err == EAGAIN || err == EINTR)
{
- if (sizeOfPtr - left > 0)
+ if (size - left > 0)
{
_gnutls_read_log ("READ: returning %d bytes from %p\n",
- (int) (sizeOfPtr - left), fd);
+ (int) (size - left), fd);
goto finish;
}
@@ -325,7 +338,7 @@ _gnutls_read (gnutls_session_t session, void *iptr,
}
left -= i;
-
+ (*bufel)->msg.size += i;
}
finish:
@@ -333,11 +346,11 @@ finish:
if (_gnutls_log_level >= 7)
{
_gnutls_read_log ("READ: read %d bytes from %p\n",
- (int) (sizeOfPtr - left), fd);
+ (int) (size - left), fd);
}
- return (sizeOfPtr - left);
+ return (size - left);
}
@@ -408,32 +421,24 @@ _gnutls_debug_log("errno: %d\n", err);
int
_gnutls_io_clear_peeked_data (gnutls_session_t session)
{
- char *peekdata;
+ mbuffer_st *peekdata;
int ret, sum;
if (session->internals.have_peeked_data == 0 || RCVLOWAT == 0)
return 0;
- peekdata = gnutls_malloc (RCVLOWAT);
- if (peekdata == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
/* this was already read by using MSG_PEEK - so it shouldn't fail */
sum = 0;
do
{ /* we need this to finish now */
- ret = _gnutls_read (session, peekdata, RCVLOWAT - sum, session->internals.pull_func);
+ ret = _gnutls_read (session, &peekdata, RCVLOWAT - sum, session->internals.pull_func);
if (ret > 0)
sum += ret;
+ _mbuffer_xfree (&peekdata);
}
while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN
|| sum < RCVLOWAT);
- gnutls_free (peekdata);
-
if (ret < 0)
{
gnutls_assert ();
@@ -460,8 +465,7 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
{
ssize_t ret = 0, ret2 = 0;
size_t min;
- opaque buf[MAX_RECV_SIZE];
- mbuffer_st *bufel;
+ mbuffer_st *bufel=NULL;
size_t recvlowat, recvdata, readsize;
if (total > MAX_RECV_SIZE || total == 0)
@@ -533,13 +537,14 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
*/
if (readsize > 0)
{
- ret = _gnutls_read (session, buf, readsize, session->internals.pull_func);
+ ret = _gnutls_read (session, &bufel, readsize, session->internals.pull_func);
/* return immediately if we got an interrupt or eagain
* error.
*/
if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
{
+ _mbuffer_xfree(&bufel);
return ret;
}
}
@@ -553,15 +558,11 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
(int) session->internals.record_recv_buffer.byte_length, (int) ret);
_gnutls_read_log ("RB: Requested %d bytes\n", (int) total);
- bufel = _mbuffer_alloc (0, ret);
- if (!bufel)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
- _mbuffer_append_data (bufel, buf, ret);
_mbuffer_enqueue (&session->internals.record_recv_buffer, bufel);
}
+ else
+ _mbuffer_xfree(&bufel);
+
/* This is hack in order for select to work. Just leave recvlowat data,
* into the kernel buffer (using a read with MSG_PEEK), thus making
@@ -570,10 +571,11 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
*/
if (ret == readsize && recvlowat > 0)
{
- ret2 = _gnutls_read (session, buf, recvlowat, system_read_peek);
+ ret2 = _gnutls_read (session, &bufel, recvlowat, system_read_peek);
if (ret2 < 0 && gnutls_error_is_fatal (ret2) == 0)
{
+ _mbuffer_xfree(&bufel);
return ret2;
}
@@ -586,15 +588,10 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
(int) session->internals.record_recv_buffer.byte_length, (int) ret2,
(int) total);
session->internals.have_peeked_data = 1;
- bufel = _mbuffer_alloc (0, ret2);
- if (!bufel)
- {
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
- _mbuffer_append_data (bufel, buf, ret2);
_mbuffer_enqueue (&session->internals.record_recv_buffer, bufel);
}
+ else
+ _mbuffer_xfree(&bufel);
}
if (ret < 0 || ret2 < 0)