2 * Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include <gnutls_int.h>
22 #include <gnutls_errors.h>
23 #include <gnutls_num.h>
24 #include <gnutls_record.h>
25 #include <gnutls_buffers.h>
26 #include <gnutls_datum.h>
28 /* This is the only file that uses the berkeley sockets API.
30 * Also holds all the buffering code used in gnutls.
31 * The buffering code works as:
34 * 1. uses a buffer to hold data (application/handshake),
35 * we got but they were not requested, yet.
36 * (see gnutls_record_buffer_put(), gnutls_record_buffer_get_size() etc.)
38 * 2. uses a buffer to hold data that were incomplete (ie the read/write
40 * (see _gnutls_io_read_buffered(), _gnutls_io_write_buffered() etc.)
43 * 1. Uses a buffer to hold data that was not sent or received
44 * complete. (Ie. sent 10 bytes of a handshake packet that is 20 bytes
46 * (see _gnutls_handshake_send_int(), _gnutls_handshake_recv_int())
48 * 2. Uses buffer to hold the last received handshake message.
49 * (see _gnutls_handshake_buffer_put() etc.)
58 # define EAGAIN EWOULDBLOCK
62 static int RET( int err
) {
63 if (err
==EAGAIN
) return GNUTLS_E_AGAIN
;
64 return GNUTLS_E_INTERRUPTED
;
68 # include <io_debug.h>
71 /* Buffers received packets of type APPLICATION DATA and
74 int _gnutls_record_buffer_put(ContentType type
, GNUTLS_STATE state
, char *data
, int length
)
76 if (length
==0) return 0;
78 case GNUTLS_APPLICATION_DATA
:
80 if ( gnutls_datum_append( &state
->gnutls_internals
.application_data_buffer
,
83 return GNUTLS_E_MEMORY_ERROR
;
85 _gnutls_buffers_log( "BUF[REC]: Inserted %d bytes of Data(%d)\n", length
, type
);
88 case GNUTLS_HANDSHAKE
:
89 if ( gnutls_datum_append( &state
->gnutls_internals
.handshake_data_buffer
,
92 return GNUTLS_E_MEMORY_ERROR
;
95 _gnutls_buffers_log( "BUF[HSK]: Inserted %d bytes of Data(%d)\n", length
, type
);
101 return GNUTLS_E_INVALID_PARAMETERS
;
108 int _gnutls_record_buffer_get_size(ContentType type
, GNUTLS_STATE state
)
111 case GNUTLS_APPLICATION_DATA
:
112 return state
->gnutls_internals
.application_data_buffer
.size
;
114 case GNUTLS_HANDSHAKE
:
115 return state
->gnutls_internals
.handshake_data_buffer
.size
;
118 return GNUTLS_E_INVALID_PARAMETERS
;
124 * gnutls_record_check_pending - checks if there are any data to receive in gnutls buffers.
125 * @state: is a &GNUTLS_STATE structure.
127 * This function checks if there are any data to receive
128 * in the gnutls buffers. Returns the size of that data or 0.
129 * Notice that you may also use select() to check for data in
130 * the TCP connection, instead of this function.
131 * (gnutls leaves some data in the tcp buffer in order for select
134 size_t gnutls_record_check_pending(GNUTLS_STATE state
) {
135 return _gnutls_record_buffer_get_size(GNUTLS_APPLICATION_DATA
, state
);
138 int _gnutls_record_buffer_get(ContentType type
, GNUTLS_STATE state
, char *data
, int length
)
140 if (length
< 0 || data
==NULL
) {
142 return GNUTLS_E_INVALID_PARAMETERS
;
146 case GNUTLS_APPLICATION_DATA
:
148 if (length
> state
->gnutls_internals
.application_data_buffer
.size
) {
149 length
= state
->gnutls_internals
.application_data_buffer
.size
;
152 _gnutls_buffers_log( "BUFFER[REC][AD]: Read %d bytes of Data(%d)\n", length
, type
);
154 state
->gnutls_internals
.application_data_buffer
.size
-= length
;
155 memcpy(data
, state
->gnutls_internals
.application_data_buffer
.data
, length
);
157 /* overwrite buffer */
158 memmove(state
->gnutls_internals
.application_data_buffer
.data
,
159 &state
->gnutls_internals
.application_data_buffer
.data
[length
],
160 state
->gnutls_internals
.application_data_buffer
.size
);
161 /* this does not fail */
162 state
->gnutls_internals
.application_data_buffer
.data
=
163 gnutls_realloc_fast(state
->gnutls_internals
.application_data_buffer
.data
,
164 state
->gnutls_internals
.application_data_buffer
.size
);
167 case GNUTLS_HANDSHAKE
:
168 if (length
> state
->gnutls_internals
.handshake_data_buffer
.size
) {
169 length
= state
->gnutls_internals
.handshake_data_buffer
.size
;
172 _gnutls_buffers_log( "BUF[REC][HD]: Read %d bytes of Data(%d)\n", length
, type
);
174 state
->gnutls_internals
.handshake_data_buffer
.size
-= length
;
175 memcpy(data
, state
->gnutls_internals
.handshake_data_buffer
.data
, length
);
177 /* overwrite buffer */
178 memmove(state
->gnutls_internals
.handshake_data_buffer
.data
,
179 &state
->gnutls_internals
.handshake_data_buffer
.data
[length
],
180 state
->gnutls_internals
.handshake_data_buffer
.size
);
183 state
->gnutls_internals
.handshake_data_buffer
.data
=
184 gnutls_realloc_fast(state
->gnutls_internals
.handshake_data_buffer
.data
,
185 state
->gnutls_internals
.handshake_data_buffer
.size
);
189 return GNUTLS_E_INVALID_PARAMETERS
;
197 /* This function is like read. But it does not return -1 on error.
198 * It does return gnutls_errno instead.
200 * Flags are only used if the default recv() function is being used.
202 static ssize_t
_gnutls_read( GNUTLS_STATE state
, void *iptr
, size_t sizeOfPtr
, int flags
)
210 GNUTLS_TRANSPORT_PTR fd
= state
->gnutls_internals
.transport_ptr
;
215 if (state
->gnutls_internals
._gnutls_pull_func
==NULL
)
216 i
= recv(fd
, &ptr
[sizeOfPtr
-left
], left
, flags
);
218 i
= state
->gnutls_internals
._gnutls_pull_func(fd
, &ptr
[sizeOfPtr
-left
], left
);
221 _gnutls_read_log( "READ: %d returned from %d, errno=%d\n", i
, fd
, errno
);
223 if (errno
== EAGAIN
|| errno
== EINTR
) {
224 if (sizeOfPtr
-left
> 0) {
226 _gnutls_read_log( "READ: returning %d bytes from %d\n", sizeOfPtr
-left
, fd
);
235 return GNUTLS_E_PULL_ERROR
;
239 _gnutls_read_log( "READ: Got %d bytes from %d\n", i
, fd
);
252 _gnutls_read_log( "READ: read %d bytes from %d\n", (sizeOfPtr
-left
), fd
);
253 for (x
=0;x
<((sizeOfPtr
-left
)/16)+1;x
++) {
254 _gnutls_read_log( "%.4x - ",x
);
256 if (sum
<(sizeOfPtr
-left
)) {
257 _gnutls_read_log( "%.2x ", ((unsigned char*)ptr
)[sum
++]);
260 _gnutls_read_log( "\n");
266 return (sizeOfPtr
- left
);
270 #define RCVLOWAT state->gnutls_internals.lowat
272 /* This function is only used with berkeley style sockets.
273 * Clears the peeked data (read with MSG_PEEK).
275 int _gnutls_io_clear_peeked_data( GNUTLS_STATE state
) {
281 if (state
->gnutls_internals
.have_peeked_data
==0 || RCVLOWAT
==0)
284 if (RCVLOWAT
> sizeof(peekdata1
)) {
285 peekdata2
= gnutls_malloc( RCVLOWAT
);
286 if (peekdata2
==NULL
) {
288 return GNUTLS_E_MEMORY_ERROR
;
297 /* this was already read by using MSG_PEEK - so it shouldn't fail */
299 do { /* we need this to finish now */
300 ret
= _gnutls_read( state
, peek
, RCVLOWAT
-sum
, 0);
301 if (ret
> 0) sum
+=ret
;
302 } while( ret
==GNUTLS_E_INTERRUPTED
|| ret
==GNUTLS_E_AGAIN
|| sum
< RCVLOWAT
);
304 if (peek
==peekdata2
) {
305 gnutls_free(peekdata2
);
313 state
->gnutls_internals
.have_peeked_data
=0;
319 void _gnutls_io_clear_read_buffer( GNUTLS_STATE state
) {
320 state
->gnutls_internals
.record_recv_buffer
.size
= 0;
323 /* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
324 * It does return gnutls_errno instead.
325 * This function reads data from the socket and keeps them in a buffer, of up to
328 * sizeOfPtr should be unsigned.
330 * This is not a general purpose function. It returns EXACTLY the data requested.
333 ssize_t
_gnutls_io_read_buffered( GNUTLS_STATE state
, opaque
**iptr
, size_t sizeOfPtr
, ContentType recv_type
)
335 ssize_t ret
=0, ret2
=0;
338 int recvlowat
= RCVLOWAT
;
341 *iptr
= state
->gnutls_internals
.record_recv_buffer
.data
;
343 if ( sizeOfPtr
> MAX_RECV_SIZE
|| sizeOfPtr
== 0
344 || (state
->gnutls_internals
.record_recv_buffer
.size
+sizeOfPtr
) > MAX_RECV_SIZE
) {
345 gnutls_assert(); /* internal error */
346 return GNUTLS_E_INVALID_PARAMETERS
;
349 /* leave peeked data to the kernel space only if application data
350 * is received and we don't have any peeked
351 * data in gnutls state.
353 if ( recv_type
!= GNUTLS_APPLICATION_DATA
354 && state
->gnutls_internals
.have_peeked_data
==0)
358 /* calculate the actual size, ie. get the minimum of the
359 * buffered data and the requested data.
361 min
= GMIN( state
->gnutls_internals
.record_recv_buffer
.size
, sizeOfPtr
);
363 /* if we have enough buffered data
364 * then just return them.
366 if ( min
== sizeOfPtr
) {
371 /* min is over zero. recvdata is the data we must
372 * receive in order to return the requested data.
374 recvdata
= sizeOfPtr
- min
;
376 /* Allocate the data required to store the new packet.
378 state
->gnutls_internals
.record_recv_buffer
.data
= gnutls_realloc_fast(
379 state
->gnutls_internals
.record_recv_buffer
.data
, recvdata
+state
->gnutls_internals
.record_recv_buffer
.size
);
380 if ( state
->gnutls_internals
.record_recv_buffer
.data
==NULL
) {
382 return GNUTLS_E_MEMORY_ERROR
;
385 buf_pos
= state
->gnutls_internals
.record_recv_buffer
.size
;
386 buf
= state
->gnutls_internals
.record_recv_buffer
.data
;
389 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer.
391 if ( recvdata
- recvlowat
> 0) {
392 ret
= _gnutls_read( state
, &buf
[buf_pos
], recvdata
- recvlowat
, 0);
394 /* return immediately if we got an interrupt or eagain
397 if (ret
< 0 && gnutls_error_is_fatal(ret
)==0) {
402 /* copy fresh data to our buffer.
405 _gnutls_read_log("RB: Have %d bytes into buffer. Adding %d bytes.\nRB: Requested %d bytes\n", state
->gnutls_internals
.record_recv_buffer
.size
, ret
, sizeOfPtr
);
406 state
->gnutls_internals
.record_recv_buffer
.size
+= ret
;
409 buf_pos
= state
->gnutls_internals
.record_recv_buffer
.size
;
411 /* This is hack in order for select to work. Just leave recvlowat data,
412 * into the kernel buffer (using a read with MSG_PEEK), thus making
413 * select think, that the socket is ready for reading.
414 * MSG_PEEK is only used with berkeley style sockets.
416 if (ret
== (recvdata
- recvlowat
) && recvlowat
> 0) {
417 ret2
= _gnutls_read( state
, &buf
[buf_pos
], recvlowat
, MSG_PEEK
);
419 if (ret2
< 0 && gnutls_error_is_fatal(ret2
)==0) {
424 _gnutls_read_log("RB-PEEK: Read %d bytes in PEEK MODE.\n", ret2
);
425 _gnutls_read_log("RB-PEEK: Have %d bytes into buffer. Adding %d bytes.\nRB: Requested %d bytes\n", state
->gnutls_internals
.record_recv_buffer
.size
, ret2
, sizeOfPtr
);
426 state
->gnutls_internals
.have_peeked_data
= 1;
427 state
->gnutls_internals
.record_recv_buffer
.size
+= ret2
;
432 if (ret
< 0 || ret2
< 0) {
434 /* that's because they are initilized to 0 */
435 return GMIN(ret
, ret2
);
440 if (ret
> 0 && ret
< recvlowat
) {
442 return GNUTLS_E_AGAIN
;
445 if (ret
==0) { /* EOF */
450 ret
= state
->gnutls_internals
.record_recv_buffer
.size
;
452 if ((ret
> 0) && (ret
< sizeOfPtr
)) {
455 return GNUTLS_E_AGAIN
;
462 /* These two functions are used to insert data to the send buffer of the handshake or
463 * record protocol. The send buffer is kept if a send is interrupted and we need to keep
464 * the data left to sent, in order to send them later.
467 #define MEMSUB(x,y) (x-y)
470 static int _gnutls_buffer_insert( gnutls_datum
* buffer
, const opaque
* _data
, int data_size
) {
472 if ( ( MEMSUB(_data
, buffer
->data
) >= 0) && (MEMSUB(_data
, buffer
->data
) < buffer
->size
) ) {
473 /* the given _data is part of the buffer.
475 if (data_size
> buffer
->size
) {
477 /* this shouldn't have happened */
478 return GNUTLS_E_UNKNOWN_ERROR
;
481 if (_data
==buffer
->data
) { /* then don't even memmove */
482 buffer
->size
= data_size
;
486 memmove( buffer
->data
, _data
, data_size
);
487 buffer
->size
= data_size
;
493 buffer
->data
= gnutls_realloc_fast( buffer
->data
, data_size
);
494 buffer
->size
= data_size
;
496 if (buffer
->data
== NULL
) {
498 return GNUTLS_E_MEMORY_ERROR
;
501 memcpy( buffer
->data
, _data
, data_size
);
507 static int _gnutls_buffer_get( gnutls_datum
* buffer
, const opaque
** ptr
, size_t *ptr_size
) {
508 *ptr_size
= buffer
->size
;
515 /* This function is like write. But it does not return -1 on error.
516 * It does return gnutls_errno instead.
518 * In case of E_AGAIN and E_INTERRUPTED errors, you must call gnutls_write_flush(),
519 * until it returns ok (0).
521 * We need to push exactly the data in n, since we cannot send less
522 * data. In TLS the peer must receive the whole packet in order
523 * to decrypt and verify the integrity.
526 ssize_t
_gnutls_io_write_buffered( GNUTLS_STATE state
, const void *iptr
, size_t n
)
535 GNUTLS_TRANSPORT_PTR fd
= state
->gnutls_internals
.transport_ptr
;
539 /* In case the previous write was interrupted, check if the
540 * iptr != NULL and we have data in the buffer.
541 * If this is true then return an error.
543 if (state
->gnutls_internals
.record_send_buffer
.size
> 0 && iptr
!= NULL
) {
545 return GNUTLS_E_INVALID_PARAMETERS
;
548 /* If data in the buffer exist
551 /* checking is handled above */
552 ret
= _gnutls_buffer_get( &state
->gnutls_internals
.record_send_buffer
, &ptr
, &n
);
558 _gnutls_write_log( "WRITE: Restoring old write. (%d bytes to send)\n", n
);
561 _gnutls_write_log( "WRITE: Will write %d bytes to %d.\n", n
, fd
);
567 if (state
->gnutls_internals
._gnutls_push_func
==NULL
)
568 i
= send(fd
, &ptr
[n
-left
], left
, 0);
570 i
= state
->gnutls_internals
._gnutls_push_func(fd
, &ptr
[n
-left
], left
);
573 if (errno
== EAGAIN
|| errno
== EINTR
) {
574 state
->gnutls_internals
.record_send_buffer_prev_size
+= n
- left
;
576 retval
= _gnutls_buffer_insert( &state
->gnutls_internals
.record_send_buffer
, &ptr
[n
-left
], left
);
582 _gnutls_write_log( "WRITE: Interrupted. Stored %d bytes to buffer. Already sent %d bytes.\n", left
, n
-left
);
589 return GNUTLS_E_PUSH_ERROR
;
595 _gnutls_write_log( "WRITE: wrote %d bytes to %d. Left %d bytes. Total %d bytes.\n", i
, fd
, left
, n
);
596 for (x
=0;x
<((i
)/16)+1;x
++) {
600 _gnutls_write_log( "%.4x - ",x
);
603 _gnutls_write_log( "%.2x ", ((unsigned char*)ptr
)[sum
++]);
606 _gnutls_write_log( "\n");
608 _gnutls_write_log( "\n");
613 retval
= n
+ state
->gnutls_internals
.record_send_buffer_prev_size
;
615 state
->gnutls_internals
.record_send_buffer
.size
= 0;
616 state
->gnutls_internals
.record_send_buffer_prev_size
= 0;
622 /* This is exactly like write_buffered, but will use two buffers to read
625 ssize_t
_gnutls_io_write_buffered2( GNUTLS_STATE state
, const void *iptr
, size_t n
, const void* iptr2
, size_t n2
)
629 return _gnutls_io_write_buffered( state
, iptr2
, n2
);
634 sptr
= gnutls_malloc( n
+n2
);
637 return GNUTLS_E_MEMORY_ERROR
;
640 memcpy( sptr
, iptr
, n
);
641 memcpy( &sptr
[n
], iptr2
, n2
);
643 ret
= _gnutls_io_write_buffered( state
, sptr
, n
+n2
);
651 /* This function writes the data that are left in the
652 * TLS write buffer (ie. because the previous write was
655 ssize_t
_gnutls_io_write_flush( GNUTLS_STATE state
)
659 if (state
->gnutls_internals
.record_send_buffer
.size
== 0)
662 ret
= _gnutls_io_write_buffered( state
, NULL
, 0);
663 _gnutls_write_log("WRITE FLUSH: %d [buffer: %d]\n", ret
, state
->gnutls_internals
.record_send_buffer
.size
);
668 /* This function writes the data that are left in the
669 * Handshake write buffer (ie. because the previous write was
672 ssize_t
_gnutls_handshake_io_write_flush( GNUTLS_STATE state
)
675 ret
= _gnutls_handshake_io_send_int( state
, 0, 0, NULL
, 0);
681 _gnutls_write_log("HANDSHAKE_FLUSH: written[1] %d bytes\n", ret
);
683 if (state
->gnutls_internals
.handshake_send_buffer
.size
== 0) {
684 ret
= state
->gnutls_internals
.handshake_send_buffer_prev_size
; /* done */
685 state
->gnutls_internals
.handshake_send_buffer_prev_size
= 0;
686 state
->gnutls_internals
.handshake_send_buffer
.size
= 0;
695 /* This is a send function for the gnutls handshake
696 * protocol. Just makes sure that all data have been sent.
698 ssize_t
_gnutls_handshake_io_send_int( GNUTLS_STATE state
, ContentType type
, HandshakeType htype
, const void *iptr
, size_t n
)
701 ssize_t i
= 0, ret
=0;
707 if (state
->gnutls_internals
.handshake_send_buffer
.size
> 0 && ptr
==NULL
&& n
== 0) {
708 /* resuming previously interrupted write
711 ret
= _gnutls_buffer_get( &state
->gnutls_internals
.handshake_send_buffer
, &ptr
, &n
);
717 type
= state
->gnutls_internals
.handshake_send_buffer_type
;
718 htype
= state
->gnutls_internals
.handshake_send_buffer_htype
;
720 } else if (state
->gnutls_internals
.handshake_send_buffer
.size
> 0) {
722 return GNUTLS_E_UNKNOWN_ERROR
;
727 _gnutls_write_log( "HWRITE: will write %d bytes to %d.\n", n
, gnutls_transport_get_ptr(state
));
728 for (x
=0;x
<((n
)/16)+1;x
++) {
732 _gnutls_write_log( "%.4x - ",x
);
735 _gnutls_write_log( "%.2x ", ((unsigned char*)ptr
)[sum
++]);
738 _gnutls_write_log( "\n");
740 _gnutls_write_log( "\n");
746 if (n
==0) { /* if we have no data to send */
749 } else if (ptr
==NULL
) {
751 return GNUTLS_E_UNKNOWN_ERROR
;
757 ret
= gnutls_send_int( state
, type
, htype
, &ptr
[n
-left
], left
);
762 ret
= GNUTLS_E_UNKNOWN_ERROR
;
765 if ( left
> 0 && (ret
==GNUTLS_E_INTERRUPTED
|| ret
==GNUTLS_E_AGAIN
)) {
768 retval
= _gnutls_buffer_insert( &state
->gnutls_internals
.handshake_send_buffer
, &ptr
[n
-left
], left
);
774 state
->gnutls_internals
.handshake_send_buffer_prev_size
+= n
-left
;
776 state
->gnutls_internals
.handshake_send_buffer_type
= type
;
777 state
->gnutls_internals
.handshake_send_buffer_htype
= htype
;
780 state
->gnutls_internals
.handshake_send_buffer_prev_size
= 0;
781 state
->gnutls_internals
.handshake_send_buffer
.size
= 0;
791 retval
= n
+ state
->gnutls_internals
.handshake_send_buffer_prev_size
;
793 state
->gnutls_internals
.handshake_send_buffer
.size
= 0;
794 state
->gnutls_internals
.handshake_send_buffer_prev_size
= 0;
800 /* This is a receive function for the gnutls handshake
801 * protocol. Makes sure that we have received all data.
803 ssize_t
_gnutls_handshake_io_recv_int( GNUTLS_STATE state
, ContentType type
, HandshakeType htype
, void *iptr
, size_t sizeOfPtr
)
813 if (sizeOfPtr
== 0 || iptr
== NULL
) {
815 return GNUTLS_E_INVALID_PARAMETERS
;
818 if (state
->gnutls_internals
.handshake_recv_buffer
.size
> 0) {
819 /* if we have already received some data */
820 if (sizeOfPtr
<= state
->gnutls_internals
.handshake_recv_buffer
.size
) {
821 /* if requested less data then return it.
824 memcpy( iptr
, state
->gnutls_internals
.handshake_recv_buffer
.data
, sizeOfPtr
);
826 state
->gnutls_internals
.handshake_recv_buffer
.size
-= sizeOfPtr
;
828 memmove( state
->gnutls_internals
.handshake_recv_buffer
.data
,
829 &state
->gnutls_internals
.handshake_recv_buffer
.data
[sizeOfPtr
],
830 state
->gnutls_internals
.handshake_recv_buffer
.size
);
835 memcpy( iptr
, state
->gnutls_internals
.handshake_recv_buffer
.data
, state
->gnutls_internals
.handshake_recv_buffer
.size
);
837 htype
= state
->gnutls_internals
.handshake_recv_buffer_htype
;
838 type
= state
->gnutls_internals
.handshake_recv_buffer_type
;
840 left
-= state
->gnutls_internals
.handshake_recv_buffer
.size
;
842 state
->gnutls_internals
.handshake_recv_buffer
.size
= 0;
846 dsize
= sizeOfPtr
- left
;
847 i
= gnutls_recv_int( state
, type
, htype
, &ptr
[dsize
], left
);
850 if (dsize
> 0 && (i
==GNUTLS_E_INTERRUPTED
|| i
==GNUTLS_E_AGAIN
)) {
853 state
->gnutls_internals
.handshake_recv_buffer
.data
= gnutls_realloc_fast(
854 state
->gnutls_internals
.handshake_recv_buffer
.data
, dsize
);
855 if (state
->gnutls_internals
.handshake_recv_buffer
.data
==NULL
) {
857 return GNUTLS_E_MEMORY_ERROR
;
860 memcpy( state
->gnutls_internals
.handshake_recv_buffer
.data
, iptr
, dsize
);
862 state
->gnutls_internals
.handshake_recv_buffer_htype
= htype
;
863 state
->gnutls_internals
.handshake_recv_buffer_type
= type
;
865 state
->gnutls_internals
.handshake_recv_buffer
.size
= dsize
;
867 state
->gnutls_internals
.handshake_recv_buffer
.size
= 0;
881 state
->gnutls_internals
.handshake_recv_buffer
.size
= 0;
883 return sizeOfPtr
- left
;
886 /* Buffer for handshake packets. Keeps the packets in order
887 * for finished messages to use them. Used in HMAC calculation
888 * and finished messages.
890 int _gnutls_handshake_buffer_put( GNUTLS_STATE state
, char *data
, int length
)
893 if (length
==0) return 0;
895 if ( (state
->gnutls_internals
.max_handshake_data_buffer_size
> 0) &&
896 ((length
+state
->gnutls_internals
.handshake_hash_buffer
.size
) >
897 state
->gnutls_internals
.max_handshake_data_buffer_size
)) {
899 return GNUTLS_E_MEMORY_ERROR
;
902 _gnutls_buffers_log( "BUF[HSK]: Inserted %d bytes of Data\n", length
);
904 if ( gnutls_datum_append( &state
->gnutls_internals
.handshake_hash_buffer
,
907 return GNUTLS_E_MEMORY_ERROR
;
913 int _gnutls_handshake_buffer_get_size( GNUTLS_STATE state
)
916 return state
->gnutls_internals
.handshake_hash_buffer
.size
;
919 /* this function does not touch the buffer
920 * and returns data from it (peek mode!)
922 int _gnutls_handshake_buffer_peek( GNUTLS_STATE state
, char *data
, int length
)
924 if (length
> state
->gnutls_internals
.handshake_hash_buffer
.size
) {
925 length
= state
->gnutls_internals
.handshake_hash_buffer
.size
;
928 _gnutls_buffers_log( "BUF[HSK]: Peeked %d bytes of Data\n", length
);
930 memcpy(data
, state
->gnutls_internals
.handshake_hash_buffer
.data
, length
);
934 /* this function does not touch the buffer
935 * and returns data from it (peek mode!)
937 int _gnutls_handshake_buffer_get_ptr( GNUTLS_STATE state
, char **data_ptr
, int *length
)
940 *length
= state
->gnutls_internals
.handshake_hash_buffer
.size
;
942 _gnutls_buffers_log( "BUF[HSK]: Peeded %d bytes of Data\n", length
);
945 *data_ptr
= state
->gnutls_internals
.handshake_hash_buffer
.data
;
950 /* Does not free the buffer
952 int _gnutls_handshake_buffer_empty( GNUTLS_STATE state
)
955 _gnutls_buffers_log( "BUF[HSK]: Emptied buffer\n");
957 state
->gnutls_internals
.handshake_hash_buffer
.size
= 0;
963 int _gnutls_handshake_buffer_clear( GNUTLS_STATE state
)
966 _gnutls_buffers_log( "BUF[HSK]: Cleared Data from buffer\n");
968 state
->gnutls_internals
.handshake_hash_buffer
.size
= 0;
969 if (state
->gnutls_internals
.handshake_hash_buffer
.data
!=NULL
)
970 gnutls_free(state
->gnutls_internals
.handshake_hash_buffer
.data
);
971 state
->gnutls_internals
.handshake_hash_buffer
.data
= NULL
;