return 0;
}
-
-void
-_gnutls_io_clear_read_buffer (gnutls_session_t session)
-{
- session->internals.record_recv_buffer.length = 0;
-}
-
/* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
* It does return gnutls_errno instead.
* This function reads data from the socket and keeps them in a buffer, of up to
* MAX_RECV_SIZE.
*
* This is not a general purpose function. It returns EXACTLY the data requested,
- * which are stored in a local (in the session) buffer. A pointer (iptr) to this buffer is returned.
+ * which are stored in a local (in the session) buffer.
*
*/
ssize_t
-_gnutls_io_read_buffered (gnutls_session_t session, opaque ** iptr,
- size_t sizeOfPtr, content_type_t recv_type)
+_gnutls_io_read_buffered (gnutls_session_t session, size_t total,
+ content_type_t recv_type)
{
ssize_t ret = 0, ret2 = 0;
size_t min;
- int buf_pos;
- opaque *buf;
- int recvlowat;
- int recvdata;
+ opaque buf[MAX_RECV_SIZE];
+ mbuffer_st *bufel;
+ size_t recvlowat, recvdata, readsize;
- *iptr = session->internals.record_recv_buffer.data;
-
- if (sizeOfPtr > MAX_RECV_SIZE || sizeOfPtr == 0)
+ if (total > MAX_RECV_SIZE || total == 0)
{
gnutls_assert (); /* internal error */
return GNUTLS_E_INVALID_REQUEST;
/* calculate the actual size, ie. get the minimum of the
* buffered data and the requested data.
*/
- min = MIN (session->internals.record_recv_buffer.length, sizeOfPtr);
+ min = MIN (session->internals.record_recv_buffer.byte_length, total);
if (min > 0)
{
/* if we have enough buffered data
* then just return them.
*/
- if (min == sizeOfPtr)
+ if (min == total)
{
return min;
}
/* min is over zero. recvdata is the data we must
* receive in order to return the requested data.
*/
- recvdata = sizeOfPtr - min;
+ recvdata = total - min;
+ readsize = recvdata - recvlowat;
/* Check if the previously read data plus the new data to
* receive are longer than the maximum receive buffer size.
*/
- if ((session->internals.record_recv_buffer.length + recvdata) >
+ if ((session->internals.record_recv_buffer.byte_length + recvdata) >
MAX_RECV_SIZE)
{
gnutls_assert (); /* internal error */
return GNUTLS_E_INVALID_REQUEST;
}
- /* Allocate the data required to store the new packet.
- */
- ret = _gnutls_buffer_resize (&session->internals.record_recv_buffer,
- recvdata +
- session->internals.record_recv_buffer.length);
-
if (ret < 0)
{
gnutls_assert ();
return ret;
}
- buf_pos = session->internals.record_recv_buffer.length;
- buf = session->internals.record_recv_buffer.data;
- *iptr = buf;
-
/* READ DATA - but leave RCVLOWAT bytes in the kernel buffer.
*/
- if (recvdata - recvlowat > 0)
+ if (readsize > 0)
{
- ret = _gnutls_read (session, &buf[buf_pos], recvdata - recvlowat, session->internals.pull_func);
+ ret = _gnutls_read (session, buf, readsize, session->internals.pull_func);
/* return immediately if we got an interrupt or eagain
* error.
{
_gnutls_read_log
("RB: Have %d bytes into buffer. Adding %d bytes.\n",
- (int) session->internals.record_recv_buffer.length, (int) ret);
- _gnutls_read_log ("RB: Requested %d bytes\n", (int) sizeOfPtr);
- session->internals.record_recv_buffer.length += ret;
- }
+ (int) session->internals.record_recv_buffer.byte_length, (int) ret);
+ _gnutls_read_log ("RB: Requested %d bytes\n", (int) total);
- buf_pos = session->internals.record_recv_buffer.length;
+ 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);
+ }
/* 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
* select think, that the socket is ready for reading.
* MSG_PEEK is only used with berkeley style sockets.
*/
- if (ret == (recvdata - recvlowat) && recvlowat > 0)
+ if (ret == readsize && recvlowat > 0)
{
- ret2 = _gnutls_read (session, &buf[buf_pos], recvlowat, system_read_peek);
+ ret2 = _gnutls_read (session, buf, recvlowat, system_read_peek);
if (ret2 < 0 && gnutls_error_is_fatal (ret2) == 0)
{
(int) ret2);
_gnutls_read_log
("RB-PEEK: Have %d bytes into buffer. Adding %d bytes.\nRB: Requested %d bytes\n",
- (int) session->internals.record_recv_buffer.length, (int) ret2,
- (int) sizeOfPtr);
+ (int) session->internals.record_recv_buffer.byte_length, (int) ret2,
+ (int) total);
session->internals.have_peeked_data = 1;
- session->internals.record_recv_buffer.length += ret2;
-
+ 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);
}
}
return 0;
}
- ret = session->internals.record_recv_buffer.length;
+ ret = session->internals.record_recv_buffer.byte_length;
- if ((ret > 0) && ((size_t) ret < sizeOfPtr))
+ if ((ret > 0) && ((size_t) ret < total))
{
/* Short Read */
gnutls_assert ();
gnutls_handshake_description_t htype, opaque * data,
size_t sizeofdata)
{
- gnutls_datum_t tmp;
int decrypted_length;
opaque version[2];
- uint8_t *headers;
content_type_t recv_type;
uint16_t length;
uint8_t *ciphertext;
- uint8_t *recv_data;
int ret, ret2;
uint16_t header_size;
int empty_packet = 0;
+ gnutls_datum_t data_enc, tmp;
if (type != GNUTLS_ALERT && (sizeofdata == 0 || data == NULL))
{
header_size = RECORD_HEADER_SIZE;
if ((ret =
- _gnutls_io_read_buffered (session, &headers, header_size,
+ _gnutls_io_read_buffered (session, header_size,
-1)) != header_size)
{
if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
+ ret = _mbuffer_linearize (&session->internals.record_recv_buffer);
+ if (ret != 0) {
+ gnutls_assert ();
+ return ret;
+ }
+
+ _mbuffer_get_first (&session->internals.record_recv_buffer, &data_enc);
+
if ((ret =
- record_check_headers (session, headers, type, htype, &recv_type,
+ record_check_headers (session, data_enc.data, type, htype, &recv_type,
version, &length, &header_size)) < 0)
{
gnutls_assert ();
/* check if we have that data into buffer.
*/
if ((ret =
- _gnutls_io_read_buffered (session, &recv_data,
- header_size + length,
+ _gnutls_io_read_buffered (session, header_size + length,
recv_type)) != header_size + length)
{
if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
/* ok now we are sure that we can read all the data - so
* move on !
*/
- _gnutls_io_clear_read_buffer (session);
- ciphertext = &recv_data[header_size];
+
+ ret = _mbuffer_linearize (&session->internals.record_recv_buffer);
+ if (ret != 0) {
+ gnutls_assert ();
+ return ret;
+ }
+ _mbuffer_get_first (&session->internals.record_recv_buffer, &data_enc);
+ ciphertext = &data_enc.data[header_size];
ret = get_temp_recv_buffer (session, &tmp);
if (ret < 0)
gnutls_assert ();
return ret;
}
+ _mbuffer_remove_bytes (&session->internals.record_recv_buffer, header_size + length);
decrypted_length = ret;
/* Check if this is a CHANGE_CIPHER_SPEC
_gnutls_buffer_init (&(*session)->internals.ia_data_buffer);
_mbuffer_init (&(*session)->internals.record_send_buffer);
- _gnutls_buffer_init (&(*session)->internals.record_recv_buffer);
+ _mbuffer_init (&(*session)->internals.record_recv_buffer);
_mbuffer_init (&(*session)->internals.handshake_send_buffer);
_gnutls_buffer_init (&(*session)->internals.handshake_recv_buffer);
(*session)->key = gnutls_calloc (1, sizeof (struct gnutls_key_st));
if ((*session)->key == NULL)
{
- cleanup_session:
gnutls_free (*session);
*session = NULL;
return GNUTLS_E_MEMORY_ERROR;
gnutls_handshake_set_max_packet_length ((*session),
MAX_HANDSHAKE_PACKET_SIZE);
- /* Allocate a minimum size for recv_data
- * This is allocated in order to avoid small messages, making
- * the receive procedure slow.
- */
- if (_gnutls_buffer_resize (&(*session)->internals.record_recv_buffer,
- INITIAL_RECV_BUFFER_SIZE))
- {
- gnutls_free ((*session)->key);
- goto cleanup_session;
- }
-
/* set the socket pointers to -1;
*/
(*session)->internals.transport_recv_ptr = (gnutls_transport_ptr_t) - 1;
_gnutls_buffer_clear (&session->internals.handshake_hash_buffer);
_gnutls_buffer_clear (&session->internals.handshake_data_buffer);
_gnutls_buffer_clear (&session->internals.application_data_buffer);
- _gnutls_buffer_clear (&session->internals.record_recv_buffer);
+ _mbuffer_clear (&session->internals.record_recv_buffer);
_mbuffer_clear (&session->internals.record_send_buffer);
gnutls_credentials_clear (session);