2 * Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <gnutls_int.h>
23 #include <gnutls_errors.h>
24 #include <gnutls_num.h>
25 #include <gnutls_record.h>
26 #include <gnutls_buffers.h>
27 #include <gnutls_datum.h>
29 /* This is the only file that uses the berkeley sockets API.
31 * Also holds all the buffering code used in gnutls.
32 * The buffering code works as:
35 * 1. uses a buffer to hold data (application/handshake),
36 * we got but they were not requested, yet.
37 * (see gnutls_record_buffer_put(), gnutls_record_buffer_get_size() etc.)
39 * 2. uses a buffer to hold data that were incomplete (ie the read/write
41 * (see _gnutls_io_read_buffered(), _gnutls_io_write_buffered() etc.)
44 * 1. Uses a buffer to hold data that was not sent or received
45 * complete. (Ie. sent 10 bytes of a handshake packet that is 20 bytes
47 * (see _gnutls_handshake_send_int(), _gnutls_handshake_recv_int())
49 * 2. Uses buffer to hold the last received handshake message.
50 * (see _gnutls_handshake_buffer_put() etc.)
59 # define EAGAIN EWOULDBLOCK
63 static int RET( int err
) {
64 if (err
==EAGAIN
) return GNUTLS_E_AGAIN
;
65 return GNUTLS_E_INTERRUPTED
;
69 # include <io_debug.h>
72 /* Buffers received packets of type APPLICATION DATA and
75 int _gnutls_record_buffer_put(ContentType type
, GNUTLS_STATE state
, char *data
, int length
)
77 if (length
==0) return 0;
79 case GNUTLS_APPLICATION_DATA
:
81 if ( gnutls_datum_append( &state
->gnutls_internals
.application_data_buffer
,
84 return GNUTLS_E_MEMORY_ERROR
;
86 _gnutls_buffers_log( "BUF[REC]: Inserted %d bytes of Data(%d)\n", length
, type
);
89 case GNUTLS_HANDSHAKE
:
90 if ( gnutls_datum_append( &state
->gnutls_internals
.handshake_data_buffer
,
93 return GNUTLS_E_MEMORY_ERROR
;
96 _gnutls_buffers_log( "BUF[HSK]: Inserted %d bytes of Data(%d)\n", length
, type
);
102 return GNUTLS_E_INVALID_PARAMETERS
;
109 int _gnutls_record_buffer_get_size(ContentType type
, GNUTLS_STATE state
)
112 case GNUTLS_APPLICATION_DATA
:
113 return state
->gnutls_internals
.application_data_buffer
.size
;
115 case GNUTLS_HANDSHAKE
:
116 return state
->gnutls_internals
.handshake_data_buffer
.size
;
119 return GNUTLS_E_INVALID_PARAMETERS
;
125 * gnutls_record_check_pending - checks if there are any data to receive in gnutls buffers.
126 * @state: is a &GNUTLS_STATE structure.
128 * This function checks if there are any data to receive
129 * in the gnutls buffers. Returns the size of that data or 0.
130 * Notice that you may also use select() to check for data in
131 * the TCP connection, instead of this function.
132 * (gnutls leaves some data in the tcp buffer in order for select
135 size_t gnutls_record_check_pending(GNUTLS_STATE state
) {
136 return _gnutls_record_buffer_get_size(GNUTLS_APPLICATION_DATA
, state
);
139 int _gnutls_record_buffer_get(ContentType type
, GNUTLS_STATE state
, char *data
, int length
)
141 if (length
< 0 || data
==NULL
) {
143 return GNUTLS_E_INVALID_PARAMETERS
;
147 case GNUTLS_APPLICATION_DATA
:
149 if (length
> state
->gnutls_internals
.application_data_buffer
.size
) {
150 length
= state
->gnutls_internals
.application_data_buffer
.size
;
153 _gnutls_buffers_log( "BUFFER[REC][AD]: Read %d bytes of Data(%d)\n", length
, type
);
155 state
->gnutls_internals
.application_data_buffer
.size
-= length
;
156 memcpy(data
, state
->gnutls_internals
.application_data_buffer
.data
, length
);
158 /* overwrite buffer */
159 memmove(state
->gnutls_internals
.application_data_buffer
.data
,
160 &state
->gnutls_internals
.application_data_buffer
.data
[length
],
161 state
->gnutls_internals
.application_data_buffer
.size
);
163 /* this does not fail */
164 state
->gnutls_internals
.application_data_buffer
.data
=
165 gnutls_realloc_fast(state
->gnutls_internals
.application_data_buffer
.data
,
166 state
->gnutls_internals
.application_data_buffer
.size
);
169 case GNUTLS_HANDSHAKE
:
170 if (length
> state
->gnutls_internals
.handshake_data_buffer
.size
) {
171 length
= state
->gnutls_internals
.handshake_data_buffer
.size
;
174 _gnutls_buffers_log( "BUF[REC][HD]: Read %d bytes of Data(%d)\n", length
, type
);
176 state
->gnutls_internals
.handshake_data_buffer
.size
-= length
;
177 memcpy(data
, state
->gnutls_internals
.handshake_data_buffer
.data
, length
);
179 /* overwrite buffer */
180 memmove(state
->gnutls_internals
.handshake_data_buffer
.data
,
181 &state
->gnutls_internals
.handshake_data_buffer
.data
[length
],
182 state
->gnutls_internals
.handshake_data_buffer
.size
);
185 state
->gnutls_internals
.handshake_data_buffer
.data
=
186 gnutls_realloc_fast(state
->gnutls_internals
.handshake_data_buffer
.data
,
187 state
->gnutls_internals
.handshake_data_buffer
.size
);
191 return GNUTLS_E_INVALID_PARAMETERS
;
199 /* This function is like read. But it does not return -1 on error.
200 * It does return gnutls_errno instead.
202 * Flags are only used if the default recv() function is being used.
204 static ssize_t
_gnutls_read( GNUTLS_STATE state
, void *iptr
, size_t sizeOfPtr
, int flags
)
212 GNUTLS_TRANSPORT_PTR fd
= state
->gnutls_internals
.transport_ptr
;
217 if (state
->gnutls_internals
._gnutls_pull_func
==NULL
)
218 i
= recv(fd
, &ptr
[sizeOfPtr
-left
], left
, flags
);
220 i
= state
->gnutls_internals
._gnutls_pull_func(fd
, &ptr
[sizeOfPtr
-left
], left
);
223 _gnutls_read_log( "READ: %d returned from %d, errno=%d\n", i
, fd
, errno
);
225 if (errno
== EAGAIN
|| errno
== EINTR
) {
226 if (sizeOfPtr
-left
> 0) {
228 _gnutls_read_log( "READ: returning %d bytes from %d\n", sizeOfPtr
-left
, fd
);
237 return GNUTLS_E_PULL_ERROR
;
241 _gnutls_read_log( "READ: Got %d bytes from %d\n", i
, fd
);
254 _gnutls_read_log( "READ: read %d bytes from %d\n", (sizeOfPtr
-left
), fd
);
255 for (x
=0;x
<((sizeOfPtr
-left
)/16)+1;x
++) {
256 _gnutls_read_log( "%.4x - ",x
);
258 if (sum
<(sizeOfPtr
-left
)) {
259 _gnutls_read_log( "%.2x ", ((unsigned char*)ptr
)[sum
++]);
262 _gnutls_read_log( "\n");
268 return (sizeOfPtr
- left
);
272 #define RCVLOWAT state->gnutls_internals.lowat
274 /* This function is only used with berkeley style sockets.
275 * Clears the peeked data (read with MSG_PEEK).
277 int _gnutls_io_clear_peeked_data( GNUTLS_STATE state
) {
278 char *peekdata
= NULL
;
281 if (state
->gnutls_internals
.have_peeked_data
==0 || RCVLOWAT
==0)
284 peekdata
= gnutls_alloca( RCVLOWAT
);
285 if (peekdata
==NULL
) {
287 return GNUTLS_E_MEMORY_ERROR
;
290 /* this was already read by using MSG_PEEK - so it shouldn't fail */
292 do { /* we need this to finish now */
293 ret
= _gnutls_read( state
, peekdata
, RCVLOWAT
-sum
, 0);
294 if (ret
> 0) sum
+=ret
;
295 } while( ret
==GNUTLS_E_INTERRUPTED
|| ret
==GNUTLS_E_AGAIN
|| sum
< RCVLOWAT
);
297 gnutls_afree(peekdata
);
304 state
->gnutls_internals
.have_peeked_data
=0;
310 void _gnutls_io_clear_read_buffer( GNUTLS_STATE state
) {
311 state
->gnutls_internals
.record_recv_buffer
.size
= 0;
314 /* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
315 * It does return gnutls_errno instead.
316 * This function reads data from the socket and keeps them in a buffer, of up to
319 * sizeOfPtr should be unsigned.
321 * This is not a general purpose function. It returns EXACTLY the data requested,
322 * which are stored in a local (in the state) buffer. A pointer (iptr) to this buffer is returned.
325 ssize_t
_gnutls_io_read_buffered( GNUTLS_STATE state
, opaque
**iptr
, size_t sizeOfPtr
, ContentType recv_type
)
327 ssize_t ret
=0, ret2
=0;
330 int recvlowat
= RCVLOWAT
;
331 int recvdata
, alloc_size
;
333 *iptr
= state
->gnutls_internals
.record_recv_buffer
.data
;
335 if ( sizeOfPtr
> MAX_RECV_SIZE
|| sizeOfPtr
== 0
336 || (state
->gnutls_internals
.record_recv_buffer
.size
+sizeOfPtr
) > MAX_RECV_SIZE
) {
337 gnutls_assert(); /* internal error */
338 return GNUTLS_E_INVALID_PARAMETERS
;
341 /* leave peeked data to the kernel space only if application data
342 * is received and we don't have any peeked
343 * data in gnutls state.
345 if ( recv_type
!= GNUTLS_APPLICATION_DATA
346 && state
->gnutls_internals
.have_peeked_data
==0)
350 /* calculate the actual size, ie. get the minimum of the
351 * buffered data and the requested data.
353 min
= GMIN( state
->gnutls_internals
.record_recv_buffer
.size
, sizeOfPtr
);
355 /* if we have enough buffered data
356 * then just return them.
358 if ( min
== sizeOfPtr
) {
363 /* min is over zero. recvdata is the data we must
364 * receive in order to return the requested data.
366 recvdata
= sizeOfPtr
- min
;
368 /* Allocate the data required to store the new packet.
371 alloc_size
= recvdata
+state
->gnutls_internals
.record_recv_buffer
.size
;
372 state
->gnutls_internals
.record_recv_buffer
.data
= gnutls_realloc_fast(
373 state
->gnutls_internals
.record_recv_buffer
.data
, alloc_size
);
374 if ( state
->gnutls_internals
.record_recv_buffer
.data
==NULL
) {
376 return GNUTLS_E_MEMORY_ERROR
;
379 buf_pos
= state
->gnutls_internals
.record_recv_buffer
.size
;
380 buf
= state
->gnutls_internals
.record_recv_buffer
.data
;
383 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer.
385 if ( recvdata
- recvlowat
> 0) {
386 ret
= _gnutls_read( state
, &buf
[buf_pos
], recvdata
- recvlowat
, 0);
388 /* return immediately if we got an interrupt or eagain
391 if (ret
< 0 && gnutls_error_is_fatal(ret
)==0) {
396 /* copy fresh data to our buffer.
399 _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
);
400 state
->gnutls_internals
.record_recv_buffer
.size
+= ret
;
403 buf_pos
= state
->gnutls_internals
.record_recv_buffer
.size
;
405 /* This is hack in order for select to work. Just leave recvlowat data,
406 * into the kernel buffer (using a read with MSG_PEEK), thus making
407 * select think, that the socket is ready for reading.
408 * MSG_PEEK is only used with berkeley style sockets.
410 if (ret
== (recvdata
- recvlowat
) && recvlowat
> 0) {
411 ret2
= _gnutls_read( state
, &buf
[buf_pos
], recvlowat
, MSG_PEEK
);
413 if (ret2
< 0 && gnutls_error_is_fatal(ret2
)==0) {
418 _gnutls_read_log("RB-PEEK: Read %d bytes in PEEK MODE.\n", ret2
);
419 _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
);
420 state
->gnutls_internals
.have_peeked_data
= 1;
421 state
->gnutls_internals
.record_recv_buffer
.size
+= ret2
;
426 if (ret
< 0 || ret2
< 0) {
428 /* that's because they are initilized to 0 */
429 return GMIN(ret
, ret2
);
434 if (ret
> 0 && ret
< recvlowat
) {
436 return GNUTLS_E_AGAIN
;
439 if (ret
==0) { /* EOF */
444 ret
= state
->gnutls_internals
.record_recv_buffer
.size
;
446 if ((ret
> 0) && (ret
< sizeOfPtr
)) {
449 return GNUTLS_E_AGAIN
;
456 /* These two functions are used to insert data to the send buffer of the handshake or
457 * record protocol. The send buffer is kept if a send is interrupted and we need to keep
458 * the data left to sent, in order to send them later.
461 #define MEMSUB(x,y) (x-y)
464 static int _gnutls_buffer_insert( gnutls_datum
* buffer
, const opaque
* _data
, int data_size
) {
466 if ( ( MEMSUB(_data
, buffer
->data
) >= 0) && (MEMSUB(_data
, buffer
->data
) < buffer
->size
) ) {
467 /* the given _data is part of the buffer.
469 if (data_size
> buffer
->size
) {
471 /* this shouldn't have happened */
472 return GNUTLS_E_UNKNOWN_ERROR
;
475 if (_data
==buffer
->data
) { /* then don't even memmove */
476 buffer
->size
= data_size
;
480 memmove( buffer
->data
, _data
, data_size
);
481 buffer
->size
= data_size
;
487 buffer
->data
= gnutls_realloc_fast( buffer
->data
, data_size
);
488 buffer
->size
= data_size
;
490 if (buffer
->data
== NULL
) {
492 return GNUTLS_E_MEMORY_ERROR
;
495 memcpy( buffer
->data
, _data
, data_size
);
501 static int _gnutls_buffer_get( gnutls_datum
* buffer
, const opaque
** ptr
, size_t *ptr_size
) {
502 *ptr_size
= buffer
->size
;
509 /* This function is like write. But it does not return -1 on error.
510 * It does return gnutls_errno instead.
512 * In case of E_AGAIN and E_INTERRUPTED errors, you must call gnutls_write_flush(),
513 * until it returns ok (0).
515 * We need to push exactly the data in n, since we cannot send less
516 * data. In TLS the peer must receive the whole packet in order
517 * to decrypt and verify the integrity.
520 ssize_t
_gnutls_io_write_buffered( GNUTLS_STATE state
, const void *iptr
, size_t n
)
529 GNUTLS_TRANSPORT_PTR fd
= state
->gnutls_internals
.transport_ptr
;
533 /* In case the previous write was interrupted, check if the
534 * iptr != NULL and we have data in the buffer.
535 * If this is true then return an error.
537 if (state
->gnutls_internals
.record_send_buffer
.size
> 0 && iptr
!= NULL
) {
539 return GNUTLS_E_INVALID_PARAMETERS
;
542 /* If data in the buffer exist
545 /* checking is handled above */
546 ret
= _gnutls_buffer_get( &state
->gnutls_internals
.record_send_buffer
, &ptr
, &n
);
552 _gnutls_write_log( "WRITE: Restoring old write. (%d bytes to send)\n", n
);
555 _gnutls_write_log( "WRITE: Will write %d bytes to %d.\n", n
, fd
);
561 if (state
->gnutls_internals
._gnutls_push_func
==NULL
)
562 i
= send(fd
, &ptr
[n
-left
], left
, 0);
564 i
= state
->gnutls_internals
._gnutls_push_func(fd
, &ptr
[n
-left
], left
);
567 if (errno
== EAGAIN
|| errno
== EINTR
) {
568 state
->gnutls_internals
.record_send_buffer_prev_size
+= n
- left
;
570 retval
= _gnutls_buffer_insert( &state
->gnutls_internals
.record_send_buffer
, &ptr
[n
-left
], left
);
576 _gnutls_write_log( "WRITE: Interrupted. Stored %d bytes to buffer. Already sent %d bytes.\n", left
, n
-left
);
583 return GNUTLS_E_PUSH_ERROR
;
589 _gnutls_write_log( "WRITE: wrote %d bytes to %d. Left %d bytes. Total %d bytes.\n", i
, fd
, left
, n
);
590 for (x
=0;x
<((i
)/16)+1;x
++) {
594 _gnutls_write_log( "%.4x - ",x
);
597 _gnutls_write_log( "%.2x ", ((unsigned char*)ptr
)[sum
++]);
600 _gnutls_write_log( "\n");
602 _gnutls_write_log( "\n");
607 retval
= n
+ state
->gnutls_internals
.record_send_buffer_prev_size
;
609 state
->gnutls_internals
.record_send_buffer
.size
= 0;
610 state
->gnutls_internals
.record_send_buffer_prev_size
= 0;
616 /* This is exactly like write_buffered, but will use two buffers to read
619 ssize_t
_gnutls_io_write_buffered2( GNUTLS_STATE state
, const void *iptr
, size_t n
, const void* iptr2
, size_t n2
)
623 return _gnutls_io_write_buffered( state
, iptr2
, n2
);
628 sptr
= gnutls_alloca( n
+n2
);
631 return GNUTLS_E_MEMORY_ERROR
;
634 memcpy( sptr
, iptr
, n
);
635 memcpy( &sptr
[n
], iptr2
, n2
);
637 ret
= _gnutls_io_write_buffered( state
, sptr
, n
+n2
);
645 /* This function writes the data that are left in the
646 * TLS write buffer (ie. because the previous write was
649 ssize_t
_gnutls_io_write_flush( GNUTLS_STATE state
)
653 if (state
->gnutls_internals
.record_send_buffer
.size
== 0)
656 ret
= _gnutls_io_write_buffered( state
, NULL
, 0);
657 _gnutls_write_log("WRITE FLUSH: %d [buffer: %d]\n", ret
, state
->gnutls_internals
.record_send_buffer
.size
);
662 /* This function writes the data that are left in the
663 * Handshake write buffer (ie. because the previous write was
666 ssize_t
_gnutls_handshake_io_write_flush( GNUTLS_STATE state
)
669 ret
= _gnutls_handshake_io_send_int( state
, 0, 0, NULL
, 0);
675 _gnutls_write_log("HANDSHAKE_FLUSH: written[1] %d bytes\n", ret
);
677 if (state
->gnutls_internals
.handshake_send_buffer
.size
== 0) {
678 ret
= state
->gnutls_internals
.handshake_send_buffer_prev_size
; /* done */
679 state
->gnutls_internals
.handshake_send_buffer_prev_size
= 0;
680 state
->gnutls_internals
.handshake_send_buffer
.size
= 0;
689 /* This is a send function for the gnutls handshake
690 * protocol. Just makes sure that all data have been sent.
692 ssize_t
_gnutls_handshake_io_send_int( GNUTLS_STATE state
, ContentType type
, HandshakeType htype
, const void *iptr
, size_t n
)
695 ssize_t i
= 0, ret
=0;
701 if (state
->gnutls_internals
.handshake_send_buffer
.size
> 0 && ptr
==NULL
&& n
== 0) {
702 /* resuming previously interrupted write
705 ret
= _gnutls_buffer_get( &state
->gnutls_internals
.handshake_send_buffer
, &ptr
, &n
);
711 type
= state
->gnutls_internals
.handshake_send_buffer_type
;
712 htype
= state
->gnutls_internals
.handshake_send_buffer_htype
;
714 } else if (state
->gnutls_internals
.handshake_send_buffer
.size
> 0) {
716 return GNUTLS_E_UNKNOWN_ERROR
;
721 _gnutls_write_log( "HWRITE: will write %d bytes to %d.\n", n
, gnutls_transport_get_ptr(state
));
722 for (x
=0;x
<((n
)/16)+1;x
++) {
726 _gnutls_write_log( "%.4x - ",x
);
729 _gnutls_write_log( "%.2x ", ((unsigned char*)ptr
)[sum
++]);
732 _gnutls_write_log( "\n");
734 _gnutls_write_log( "\n");
740 if (n
==0) { /* if we have no data to send */
743 } else if (ptr
==NULL
) {
745 return GNUTLS_E_UNKNOWN_ERROR
;
751 ret
= gnutls_send_int( state
, type
, htype
, &ptr
[n
-left
], left
);
756 ret
= GNUTLS_E_UNKNOWN_ERROR
;
759 if ( left
> 0 && (ret
==GNUTLS_E_INTERRUPTED
|| ret
==GNUTLS_E_AGAIN
)) {
762 retval
= _gnutls_buffer_insert( &state
->gnutls_internals
.handshake_send_buffer
, &ptr
[n
-left
], left
);
768 state
->gnutls_internals
.handshake_send_buffer_prev_size
+= n
-left
;
770 state
->gnutls_internals
.handshake_send_buffer_type
= type
;
771 state
->gnutls_internals
.handshake_send_buffer_htype
= htype
;
774 state
->gnutls_internals
.handshake_send_buffer_prev_size
= 0;
775 state
->gnutls_internals
.handshake_send_buffer
.size
= 0;
785 retval
= n
+ state
->gnutls_internals
.handshake_send_buffer_prev_size
;
787 state
->gnutls_internals
.handshake_send_buffer
.size
= 0;
788 state
->gnutls_internals
.handshake_send_buffer_prev_size
= 0;
794 /* This is a receive function for the gnutls handshake
795 * protocol. Makes sure that we have received all data.
797 ssize_t
_gnutls_handshake_io_recv_int( GNUTLS_STATE state
, ContentType type
, HandshakeType htype
, void *iptr
, size_t sizeOfPtr
)
807 if (sizeOfPtr
== 0 || iptr
== NULL
) {
809 return GNUTLS_E_INVALID_PARAMETERS
;
812 if (state
->gnutls_internals
.handshake_recv_buffer
.size
> 0) {
813 /* if we have already received some data */
814 if (sizeOfPtr
<= state
->gnutls_internals
.handshake_recv_buffer
.size
) {
815 /* if requested less data then return it.
818 memcpy( iptr
, state
->gnutls_internals
.handshake_recv_buffer
.data
, sizeOfPtr
);
820 state
->gnutls_internals
.handshake_recv_buffer
.size
-= sizeOfPtr
;
822 memmove( state
->gnutls_internals
.handshake_recv_buffer
.data
,
823 &state
->gnutls_internals
.handshake_recv_buffer
.data
[sizeOfPtr
],
824 state
->gnutls_internals
.handshake_recv_buffer
.size
);
829 memcpy( iptr
, state
->gnutls_internals
.handshake_recv_buffer
.data
, state
->gnutls_internals
.handshake_recv_buffer
.size
);
831 htype
= state
->gnutls_internals
.handshake_recv_buffer_htype
;
832 type
= state
->gnutls_internals
.handshake_recv_buffer_type
;
834 left
-= state
->gnutls_internals
.handshake_recv_buffer
.size
;
836 state
->gnutls_internals
.handshake_recv_buffer
.size
= 0;
840 dsize
= sizeOfPtr
- left
;
841 i
= gnutls_recv_int( state
, type
, htype
, &ptr
[dsize
], left
);
844 if (dsize
> 0 && (i
==GNUTLS_E_INTERRUPTED
|| i
==GNUTLS_E_AGAIN
)) {
847 state
->gnutls_internals
.handshake_recv_buffer
.data
= gnutls_realloc_fast(
848 state
->gnutls_internals
.handshake_recv_buffer
.data
, dsize
);
849 if (state
->gnutls_internals
.handshake_recv_buffer
.data
==NULL
) {
851 return GNUTLS_E_MEMORY_ERROR
;
854 memcpy( state
->gnutls_internals
.handshake_recv_buffer
.data
, iptr
, dsize
);
856 state
->gnutls_internals
.handshake_recv_buffer_htype
= htype
;
857 state
->gnutls_internals
.handshake_recv_buffer_type
= type
;
859 state
->gnutls_internals
.handshake_recv_buffer
.size
= dsize
;
861 state
->gnutls_internals
.handshake_recv_buffer
.size
= 0;
875 state
->gnutls_internals
.handshake_recv_buffer
.size
= 0;
877 return sizeOfPtr
- left
;
880 /* Buffer for handshake packets. Keeps the packets in order
881 * for finished messages to use them. Used in HMAC calculation
882 * and finished messages.
884 int _gnutls_handshake_buffer_put( GNUTLS_STATE state
, char *data
, int length
)
887 if (length
==0) return 0;
889 if ( (state
->gnutls_internals
.max_handshake_data_buffer_size
> 0) &&
890 ((length
+state
->gnutls_internals
.handshake_hash_buffer
.size
) >
891 state
->gnutls_internals
.max_handshake_data_buffer_size
)) {
893 return GNUTLS_E_MEMORY_ERROR
;
896 _gnutls_buffers_log( "BUF[HSK]: Inserted %d bytes of Data\n", length
);
898 if ( gnutls_datum_append( &state
->gnutls_internals
.handshake_hash_buffer
,
901 return GNUTLS_E_MEMORY_ERROR
;
907 int _gnutls_handshake_buffer_get_size( GNUTLS_STATE state
)
910 return state
->gnutls_internals
.handshake_hash_buffer
.size
;
913 /* this function does not touch the buffer
914 * and returns data from it (peek mode!)
916 int _gnutls_handshake_buffer_peek( GNUTLS_STATE state
, char *data
, int length
)
918 if (length
> state
->gnutls_internals
.handshake_hash_buffer
.size
) {
919 length
= state
->gnutls_internals
.handshake_hash_buffer
.size
;
922 _gnutls_buffers_log( "BUF[HSK]: Peeked %d bytes of Data\n", length
);
924 memcpy(data
, state
->gnutls_internals
.handshake_hash_buffer
.data
, length
);
928 /* this function does not touch the buffer
929 * and returns data from it (peek mode!)
931 int _gnutls_handshake_buffer_get_ptr( GNUTLS_STATE state
, char **data_ptr
, int *length
)
934 *length
= state
->gnutls_internals
.handshake_hash_buffer
.size
;
936 _gnutls_buffers_log( "BUF[HSK]: Peeded %d bytes of Data\n", length
);
939 *data_ptr
= state
->gnutls_internals
.handshake_hash_buffer
.data
;
944 /* Does not free the buffer
946 int _gnutls_handshake_buffer_empty( GNUTLS_STATE state
)
949 _gnutls_buffers_log( "BUF[HSK]: Emptied buffer\n");
951 state
->gnutls_internals
.handshake_hash_buffer
.size
= 0;
957 int _gnutls_handshake_buffer_clear( GNUTLS_STATE state
)
960 _gnutls_buffers_log( "BUF[HSK]: Cleared Data from buffer\n");
962 state
->gnutls_internals
.handshake_hash_buffer
.size
= 0;
963 if (state
->gnutls_internals
.handshake_hash_buffer
.data
!=NULL
)
964 gnutls_free(state
->gnutls_internals
.handshake_hash_buffer
.data
);
965 state
->gnutls_internals
.handshake_hash_buffer
.data
= NULL
;