2 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3 * 2009, 2010 Free Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* This is the only file that uses the berkeley sockets API.
28 * Also holds all the buffering code used in gnutls.
29 * The buffering code works as:
32 * 1. uses a buffer to hold data (application/handshake),
33 * we got but they were not requested, yet.
34 * (see gnutls_record_buffer_put(), gnutls_record_buffer_get_size() etc.)
36 * 2. uses a buffer to hold data that were incomplete (ie the read/write
38 * (see _gnutls_io_read_buffered(), _gnutls_io_write_buffered() etc.)
41 * 1. Uses a buffer to hold data that was not sent or received
42 * complete. (E.g. sent 10 bytes of a handshake packet that is 20 bytes
44 * (see _gnutls_handshake_send_int(), _gnutls_handshake_recv_int())
46 * 2. Uses buffer to hold the last received handshake message.
47 * (see _gnutls_handshake_buffer_put() etc.)
51 #include <gnutls_int.h>
52 #include <gnutls_errors.h>
53 #include <gnutls_num.h>
54 #include <gnutls_record.h>
55 #include <gnutls_buffers.h>
56 #include <gnutls_mbuffers.h>
57 #include <gnutls_state.h>
58 #include <gnutls_dtls.h>
60 #include <gnutls_constate.h> /* gnutls_epoch_get */
64 #define EAGAIN EWOULDBLOCK
67 /* this is the maximum number of messages allowed to queue.
71 /* Buffers received packets of type APPLICATION DATA and
75 _gnutls_record_buffer_put (content_type_t type
,
76 gnutls_session_t session
, opaque
* data
,
79 gnutls_buffer_st
*buf
;
86 case GNUTLS_APPLICATION_DATA
:
87 buf
= &session
->internals
.application_data_buffer
;
88 _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n",
89 (int) length
, (int) type
);
92 case GNUTLS_HANDSHAKE
:
93 buf
= &session
->internals
.handshake_data_buffer
;
94 _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data(%d)\n",
95 (int) length
, (int) type
);
98 case GNUTLS_INNER_APPLICATION
:
99 buf
= &session
->internals
.ia_data_buffer
;
100 _gnutls_buffers_log ("BUF[IA]: Inserted %d bytes of Data(%d)\n",
101 (int) length
, (int) type
);
106 return GNUTLS_E_INVALID_REQUEST
;
109 if (_gnutls_buffer_append_data (buf
, data
, length
) < 0)
112 return GNUTLS_E_MEMORY_ERROR
;
119 _gnutls_record_buffer_get_size (content_type_t type
, gnutls_session_t session
)
123 case GNUTLS_APPLICATION_DATA
:
124 return session
->internals
.application_data_buffer
.length
;
126 case GNUTLS_HANDSHAKE
:
127 return session
->internals
.handshake_data_buffer
.length
;
129 case GNUTLS_INNER_APPLICATION
:
130 return session
->internals
.ia_data_buffer
.length
;
133 return GNUTLS_E_INVALID_REQUEST
;
138 * gnutls_record_check_pending:
139 * @session: is a #gnutls_session_t structure.
141 * This function checks if there are any data to receive in the gnutls
144 * Note that you could also use select() to check for data in a TCP
145 * connection, instead of this function. GnuTLS leaves some data in
146 * the tcp buffer in order for select to work. However the select()
147 * alternative is not recommended and will be deprecated in later
150 * Returns: the size of that data or 0.
153 gnutls_record_check_pending (gnutls_session_t session
)
155 return _gnutls_record_buffer_get_size (GNUTLS_APPLICATION_DATA
, session
);
159 _gnutls_record_buffer_get (content_type_t type
,
160 gnutls_session_t session
, opaque
* data
,
163 if (length
== 0 || data
== NULL
)
166 return GNUTLS_E_INVALID_REQUEST
;
171 case GNUTLS_APPLICATION_DATA
:
172 _gnutls_buffer_pop_data (&session
->internals
.application_data_buffer
,
174 _gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n",
175 (int) length
, (int) type
);
178 case GNUTLS_HANDSHAKE
:
179 _gnutls_buffer_pop_data (&session
->internals
.handshake_data_buffer
,
181 _gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n",
182 (int) length
, (int) type
);
185 case GNUTLS_INNER_APPLICATION
:
187 _gnutls_buffer_pop_data (&session
->internals
.ia_data_buffer
, data
,
189 _gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n",
190 (int) length
, (int) type
);
195 return GNUTLS_E_INVALID_REQUEST
;
203 reset_errno (gnutls_session_t session
)
205 session
->internals
.errnum
= 0;
209 get_errno (gnutls_session_t session
)
211 if (session
->internals
.errnum
!= 0)
212 return session
->internals
.errnum
;
214 return session
->internals
.errno_func (session
->
215 internals
.transport_recv_ptr
);
220 _gnutls_dgram_read (gnutls_session_t session
, mbuffer_st
**bufel
,
221 gnutls_pull_func pull_func
)
225 gnutls_transport_ptr_t fd
= session
->internals
.transport_recv_ptr
;
230 return GNUTLS_E_INTERNAL_ERROR
;
233 ptr
= gnutls_malloc(MAX_RECV_SIZE(session
));
235 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
237 session
->internals
.direction
= 0;
239 reset_errno (session
);
241 i
= pull_func (fd
, ptr
, MAX_RECV_SIZE(session
));
245 int err
= get_errno (session
);
247 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
248 (int) i
, fd
, errno
, session
->internals
.errnum
);
252 ret
= GNUTLS_E_AGAIN
;
255 else if (err
== EINTR
)
257 ret
= GNUTLS_E_INTERRUPTED
;
263 ret
= GNUTLS_E_PULL_ERROR
;
269 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i
, fd
);
271 /* If we get here, we likely have a stream socket.
272 * FIXME: this probably breaks DCCP. */
274 ret
= GNUTLS_E_INTERNAL_ERROR
;
278 *bufel
= _mbuffer_alloc (0, i
);
282 ret
= GNUTLS_E_MEMORY_ERROR
;
286 _mbuffer_append_data (*bufel
, ptr
, i
);
289 _gnutls_read_log ("READ: read %d bytes from %p\n", (int) i
, fd
);
299 _gnutls_stream_read (gnutls_session_t session
, mbuffer_st
**bufel
,
300 size_t size
, gnutls_pull_func pull_func
)
305 gnutls_transport_ptr_t fd
= session
->internals
.transport_recv_ptr
;
310 return GNUTLS_E_INTERNAL_ERROR
;
313 *bufel
= _mbuffer_alloc (0, size
);
317 return GNUTLS_E_MEMORY_ERROR
;
319 ptr
= (*bufel
)->msg
.data
;
321 session
->internals
.direction
= 0;
326 reset_errno (session
);
328 i
= pull_func (fd
, &ptr
[size
- left
], left
);
332 int err
= get_errno (session
);
334 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
335 (int) i
, fd
, errno
, session
->internals
.errnum
);
337 if (err
== EAGAIN
|| err
== EINTR
)
342 _gnutls_read_log ("READ: returning %d bytes from %p\n",
343 (int) (size
- left
), fd
);
349 return GNUTLS_E_AGAIN
;
350 return GNUTLS_E_INTERRUPTED
;
355 return GNUTLS_E_PULL_ERROR
;
361 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i
, fd
);
368 (*bufel
)->msg
.size
+= i
;
373 _gnutls_read_log ("READ: read %d bytes from %p\n",
374 (int) (size
- left
), fd
);
376 return (size
- left
);
380 /* This function is like read. But it does not return -1 on error.
381 * It does return gnutls_errno instead.
383 * Flags are only used if the default recv() function is being used.
386 _gnutls_read (gnutls_session_t session
, mbuffer_st
**bufel
,
387 size_t size
, gnutls_pull_func pull_func
)
389 if (_gnutls_is_dtls (session
))
390 /* Size is not passed, since a whole datagram will be read. */
391 return _gnutls_dgram_read (session
, bufel
, pull_func
);
393 return _gnutls_stream_read (session
, bufel
, size
, pull_func
);
397 _gnutls_writev_emu (gnutls_session_t session
, const giovec_t
* giovec
,
401 gnutls_transport_ptr_t fd
= session
->internals
.transport_send_ptr
;
404 for (j
= 0; j
< giovec_cnt
; j
++)
406 ret
= session
->internals
.push_func (fd
, giovec
[j
].iov_base
, giovec
[j
].iov_len
);
421 _gnutls_writev (gnutls_session_t session
, const giovec_t
* giovec
,
425 gnutls_transport_ptr_t fd
= session
->internals
.transport_send_ptr
;
427 reset_errno (session
);
429 if (session
->internals
.push_func
!= NULL
)
430 i
= _gnutls_writev_emu (session
, giovec
, giovec_cnt
);
432 i
= session
->internals
.vec_push_func (fd
, giovec
, giovec_cnt
);
436 int err
= get_errno (session
);
437 _gnutls_debug_log ("errno: %d\n", err
);
439 return GNUTLS_E_AGAIN
;
440 else if (err
== EINTR
)
441 return GNUTLS_E_INTERRUPTED
;
445 return GNUTLS_E_PUSH_ERROR
;
451 #define RCVLOWAT session->internals.lowat
453 /* This function is only used with berkeley style sockets.
454 * Clears the peeked data (read with MSG_PEEK).
457 _gnutls_io_clear_peeked_data (gnutls_session_t session
)
459 mbuffer_st
*peekdata
;
462 if (session
->internals
.have_peeked_data
== 0 || RCVLOWAT
== 0)
465 /* this was already read by using MSG_PEEK - so it shouldn't fail */
468 { /* we need this to finish now */
470 _gnutls_read (session
, &peekdata
, RCVLOWAT
- sum
,
471 session
->internals
.pull_func
);
474 _mbuffer_xfree (&peekdata
);
476 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
485 session
->internals
.have_peeked_data
= 0;
490 /* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
491 * It does return gnutls_errno instead.
492 * This function reads data from the socket and keeps them in a buffer, of up to
495 * This is not a general purpose function. It returns EXACTLY the data requested,
496 * which are stored in a local (in the session) buffer.
500 _gnutls_io_read_buffered (gnutls_session_t session
, size_t total
,
501 content_type_t recv_type
)
503 ssize_t ret
= 0, ret2
= 0;
505 mbuffer_st
*bufel
= NULL
;
506 size_t recvlowat
, recvdata
, readsize
;
508 if (total
> MAX_RECV_SIZE(session
) || total
== 0)
510 gnutls_assert (); /* internal error */
511 return GNUTLS_E_INVALID_REQUEST
;
514 /* If an external pull function is used, then do not leave
515 * any data into the kernel buffer.
517 if (session
->internals
.pull_func
!= system_read
)
523 /* leave peeked data to the kernel space only if application data
524 * is received and we don't have any peeked
525 * data in gnutls session.
527 if (recv_type
!= GNUTLS_APPLICATION_DATA
528 && session
->internals
.have_peeked_data
== 0)
531 recvlowat
= RCVLOWAT
;
536 /* calculate the actual size, ie. get the minimum of the
537 * buffered data and the requested data.
539 min
= MIN (session
->internals
.record_recv_buffer
.byte_length
, total
);
542 /* if we have enough buffered data
543 * then just return them.
551 if(_gnutls_is_dtls(session
)
552 && session
->internals
.record_recv_buffer
.byte_length
!= 0)
554 /* Attempt to read across records while using DTLS. */
556 return GNUTLS_E_INVALID_REQUEST
;
559 /* min is over zero. recvdata is the data we must
560 * receive in order to return the requested data.
562 recvdata
= total
- min
;
563 readsize
= recvdata
- recvlowat
;
565 /* Check if the previously read data plus the new data to
566 * receive are longer than the maximum receive buffer size.
568 if ((session
->internals
.record_recv_buffer
.byte_length
+ recvdata
) >
569 MAX_RECV_SIZE(session
))
571 gnutls_assert (); /* internal error */
572 return GNUTLS_E_INVALID_REQUEST
;
581 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer.
586 _gnutls_read (session
, &bufel
, readsize
,
587 session
->internals
.pull_func
);
589 /* return immediately if we got an interrupt or eagain
592 if (ret
< 0 && gnutls_error_is_fatal (ret
) == 0)
594 _mbuffer_xfree (&bufel
);
599 /* copy fresh data to our buffer.
604 ("RB: Have %d bytes into buffer. Adding %d bytes.\n",
605 (int) session
->internals
.record_recv_buffer
.byte_length
, (int) ret
);
606 _gnutls_read_log ("RB: Requested %d bytes\n", (int) total
);
608 _mbuffer_enqueue (&session
->internals
.record_recv_buffer
, bufel
);
611 _mbuffer_xfree (&bufel
);
614 /* This is hack in order for select to work. Just leave recvlowat data,
615 * into the kernel buffer (using a read with MSG_PEEK), thus making
616 * select think, that the socket is ready for reading.
617 * MSG_PEEK is only used with berkeley style sockets.
619 if (ret
== readsize
&& recvlowat
> 0 && !_gnutls_is_dtls(session
) &&
620 session
->internals
.pull_func
== system_read
)
622 ret2
= _gnutls_read (session
, &bufel
, recvlowat
, system_read_peek
);
624 if (ret2
< 0 && gnutls_error_is_fatal (ret2
) == 0)
626 _mbuffer_xfree (&bufel
);
632 _gnutls_read_log ("RB-PEEK: Read %d bytes in PEEK MODE.\n",
635 ("RB-PEEK: Have %d bytes into buffer. Adding %d bytes.\nRB: Requested %d bytes\n",
636 (int) session
->internals
.record_recv_buffer
.byte_length
,
637 (int) ret2
, (int) total
);
638 session
->internals
.have_peeked_data
= 1;
639 _mbuffer_enqueue (&session
->internals
.record_recv_buffer
, bufel
);
642 _mbuffer_xfree (&bufel
);
645 if (ret
< 0 || ret2
< 0)
648 /* that's because they are initialized to 0 */
649 return MIN (ret
, ret2
);
654 if (ret
> 0 && ret
< recvlowat
)
657 return GNUTLS_E_AGAIN
;
666 if(_gnutls_is_dtls(session
))
667 ret
= MIN(total
, session
->internals
.record_recv_buffer
.byte_length
);
669 ret
= session
->internals
.record_recv_buffer
.byte_length
;
671 if ((ret
> 0) && ((size_t) ret
< total
))
675 return GNUTLS_E_AGAIN
;
683 /* This function is like write. But it does not return -1 on error.
684 * It does return gnutls_errno instead.
686 * This function takes full responsibility of freeing msg->data.
688 * In case of E_AGAIN and E_INTERRUPTED errors, you must call
689 * gnutls_write_flush(), until it returns ok (0).
691 * We need to push exactly the data in msg->size, since we cannot send
692 * less data. In TLS the peer must receive the whole packet in order
693 * to decrypt and verify the integrity.
697 _gnutls_io_write_buffered (gnutls_session_t session
,
698 mbuffer_st
* bufel
, unsigned int mflag
)
700 mbuffer_head_st
*const send_buffer
= &session
->internals
.record_send_buffer
;
702 _mbuffer_enqueue (send_buffer
, bufel
);
705 ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n",
706 (int) bufel
->msg
.size
, session
->internals
.transport_recv_ptr
,
707 (int) send_buffer
->byte_length
);
709 if (mflag
== MBUFFER_FLUSH
)
710 return _gnutls_io_write_flush (session
);
712 return bufel
->msg
.size
;
715 typedef ssize_t (*send_func
) (gnutls_session_t
, const giovec_t
*, int);
717 /* This function writes the data that are left in the
718 * TLS write buffer (ie. because the previous write was
722 _gnutls_io_write_flush (gnutls_session_t session
)
725 mbuffer_head_st
*send_buffer
= &session
->internals
.record_send_buffer
;
727 ssize_t sent
= 0, tosend
= 0;
728 giovec_t iovec
[MAX_QUEUE
];
732 _gnutls_write_log ("WRITE FLUSH: %d bytes in buffer.\n",
733 (int) send_buffer
->byte_length
);
735 for (cur
= _mbuffer_get_first (send_buffer
, &msg
);
736 cur
!= NULL
; cur
= _mbuffer_get_next (cur
, &msg
))
738 iovec
[i
].iov_base
= msg
.data
;
739 iovec
[i
++].iov_len
= msg
.size
;
742 /* we buffer up to MAX_QUEUE messages */
743 if (i
>= sizeof (iovec
) / sizeof (iovec
[0]))
746 return GNUTLS_E_INTERNAL_ERROR
;
750 ret
= _gnutls_writev (session
, iovec
, i
);
753 _mbuffer_remove_bytes (send_buffer
, ret
);
754 _gnutls_write_log ("WRITE: wrote %d bytes, %d bytes left.\n",
755 ret
, (int) send_buffer
->byte_length
);
759 else if (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
)
761 _gnutls_write_log ("WRITE interrupted: %d bytes left.\n",
762 (int) send_buffer
->byte_length
);
767 _gnutls_write_log ("WRITE error: code %d, %d bytes left.\n",
768 ret
, (int) send_buffer
->byte_length
);
777 return GNUTLS_E_AGAIN
;
784 /* Checks whether there are received data within
787 * Returns 0 if data were received, GNUTLS_E_TIMEDOUT
788 * on timeout and a negative value on error.
791 _gnutls_io_check_recv (gnutls_session_t session
, void* data
, size_t data_size
, unsigned int ms
)
793 gnutls_transport_ptr_t fd
= session
->internals
.transport_send_ptr
;
796 if (session
->internals
.pull_timeout_func
== system_recv_timeout
&&
797 session
->internals
.pull_func
!= system_read
)
798 return gnutls_assert_val(GNUTLS_E_PULL_ERROR
);
800 ret
= session
->internals
.pull_timeout_func(fd
, data
, data_size
, ms
);
802 return gnutls_assert_val(GNUTLS_E_PULL_ERROR
);
806 else return GNUTLS_E_TIMEDOUT
;
809 /* This function writes the data that are left in the
810 * Handshake write buffer (ie. because the previous write was
815 _gnutls_handshake_io_write_flush (gnutls_session_t session
)
817 mbuffer_head_st
*const send_buffer
=
818 &session
->internals
.handshake_send_buffer
;
825 _gnutls_write_log ("HWRITE FLUSH: %d bytes in buffer.\n",
826 (int) send_buffer
->byte_length
);
828 if (IS_DTLS(session
))
829 return _dtls_transmit(session
);
831 for (cur
= _mbuffer_get_first (send_buffer
, &msg
);
832 cur
!= NULL
; cur
= _mbuffer_get_first (send_buffer
, &msg
))
836 ret
= _gnutls_send_int (session
, cur
->type
,
839 msg
.data
, msg
.size
, 0);
845 ret
= _mbuffer_remove_bytes (send_buffer
, ret
);
847 _gnutls_epoch_refcount_dec(session
, epoch
);
849 _gnutls_write_log ("HWRITE: wrote %d bytes, %d bytes left.\n",
850 ret
, (int) send_buffer
->byte_length
);
855 _gnutls_write_log ("HWRITE error: code %d, %d bytes left.\n",
856 ret
, (int) send_buffer
->byte_length
);
863 return _gnutls_io_write_flush (session
);
868 /* This is a send function for the gnutls handshake
869 * protocol. Just makes sure that all data have been sent.
873 _gnutls_handshake_io_cache_int (gnutls_session_t session
,
874 gnutls_handshake_description_t htype
,
877 mbuffer_head_st
* send_buffer
;
879 if (IS_DTLS(session
))
881 bufel
->sequence
= session
->internals
.dtls
.hsk_write_seq
-1;
885 &session
->internals
.handshake_send_buffer
;
887 bufel
->epoch
= (uint16_t)_gnutls_epoch_refcount_inc(session
, EPOCH_WRITE_CURRENT
);
889 bufel
->htype
= htype
;
890 if (bufel
->htype
== GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC
)
891 bufel
->type
= GNUTLS_CHANGE_CIPHER_SPEC
;
893 bufel
->type
= GNUTLS_HANDSHAKE
;
895 _mbuffer_enqueue (send_buffer
, bufel
);
898 ("HWRITE: enqueued [%s] %d. Total %d bytes.\n",
899 _gnutls_handshake2str (bufel
->htype
), (int) bufel
->msg
.size
, (int) send_buffer
->byte_length
);
904 /* Skips a handshake packet
907 _gnutls_handshake_io_recv_skip (gnutls_session_t session
,
909 gnutls_handshake_description_t htype
,
915 if (ptr_size
== 0) return 0;
917 ptr
= gnutls_malloc(ptr_size
);
919 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR
);
921 ret
= _gnutls_handshake_io_recv_int(session
, type
, htype
, ptr
, ptr_size
);
925 return gnutls_assert_val(ret
);
930 /* This is a receive function for the gnutls handshake
931 * protocol. Makes sure that we have received all data.
934 _gnutls_handshake_io_recv_int (gnutls_session_t session
,
936 gnutls_handshake_description_t htype
,
937 void *iptr
, size_t ptr_size
)
947 if (ptr_size
== 0 || iptr
== NULL
)
950 return GNUTLS_E_INVALID_REQUEST
;
953 if (session
->internals
.handshake_recv_buffer
.length
> 0)
957 /* if we have already received some data */
958 if (ptr_size
<= session
->internals
.handshake_recv_buffer
.length
)
960 /* if requested less data then return it.
965 _gnutls_buffer_pop_data (&session
->internals
.handshake_recv_buffer
,
972 _gnutls_buffer_pop_data (&session
->internals
.handshake_recv_buffer
,
979 dsize
= ptr_size
- left
;
980 i
= _gnutls_recv_int (session
, type
, htype
, &ptr
[dsize
], left
, NULL
);
984 if (dsize
> 0 && (i
== GNUTLS_E_INTERRUPTED
|| i
== GNUTLS_E_AGAIN
))
988 _gnutls_buffer_append_data (&session
->internals
.
989 handshake_recv_buffer
, iptr
, dsize
);
1004 session
->internals
.handshake_recv_buffer
.length
= 0;
1006 return ptr_size
- left
;
1009 /* Buffer for handshake packets. Keeps the packets in order
1010 * for finished messages to use them. Used in HMAC calculation
1011 * and finished messages.
1014 _gnutls_handshake_buffer_put (gnutls_session_t session
, opaque
* data
,
1021 if ((session
->internals
.max_handshake_data_buffer_size
> 0) &&
1022 ((length
+ session
->internals
.handshake_hash_buffer
.length
) >
1023 session
->internals
.max_handshake_data_buffer_size
))
1026 return GNUTLS_E_HANDSHAKE_TOO_LARGE
;
1029 _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", (int) length
);
1030 if (_gnutls_buffer_append_data (&session
->internals
.handshake_hash_buffer
,
1034 return GNUTLS_E_MEMORY_ERROR
;
1041 _gnutls_handshake_buffer_get_size (gnutls_session_t session
)
1044 return session
->internals
.handshake_hash_buffer
.length
;
1047 /* this function does not touch the buffer
1048 * and returns data from it (peek mode!)
1051 _gnutls_handshake_buffer_get_ptr (gnutls_session_t session
,
1052 opaque
** data_ptr
, size_t * length
)
1055 *length
= session
->internals
.handshake_hash_buffer
.length
;
1057 _gnutls_buffers_log ("BUF[HSK]: Peeked %d bytes of Data\n",
1058 (int) session
->internals
.handshake_hash_buffer
.length
);
1060 if (data_ptr
!= NULL
)
1061 *data_ptr
= session
->internals
.handshake_hash_buffer
.data
;
1066 /* Does not free the buffer
1069 _gnutls_handshake_buffer_empty (gnutls_session_t session
)
1072 _gnutls_buffers_log ("BUF[HSK]: Emptied buffer\n");
1074 session
->internals
.handshake_hash_buffer
.length
= 0;
1081 _gnutls_handshake_buffer_clear (gnutls_session_t session
)
1084 _gnutls_buffers_log ("BUF[HSK]: Cleared Data from buffer\n");
1085 _gnutls_buffer_clear (&session
->internals
.handshake_hash_buffer
);