gnutls-cli: Fix uninitialized variable when PKCS#11 uris in use.
[gnutls.git] / lib / gnutls_buffers.c
blob0c48d26b672971485e75d36e85f59185e3a1c417
1 /*
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,
22 * USA
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:
31 * RECORD LAYER:
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
37 * was interrupted)
38 * (see _gnutls_io_read_buffered(), _gnutls_io_write_buffered() etc.)
40 * HANDSHAKE LAYER:
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
43 * long).
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 <system.h>
59 #include <errno.h>
60 #ifdef _WIN32
61 # include <windows.h>
62 #endif
64 #ifndef EAGAIN
65 #define EAGAIN EWOULDBLOCK
66 #endif
68 /* this is the maximum number of messages allowed to queue.
70 #define MAX_QUEUE 16
72 /**
73 * gnutls_transport_set_errno:
74 * @session: is a #gnutls_session_t structure.
75 * @err: error value to store in session-specific errno variable.
77 * Store @err in the session-specific errno variable. Useful values
78 * for @err is EAGAIN and EINTR, other values are treated will be
79 * treated as real errors in the push/pull function.
81 * This function is useful in replacement push/pull functions set by
82 * gnutls_transport_set_push_function and
83 * gnutls_transport_set_pullpush_function under Windows, where the
84 * replacement push/pull may not have access to the same @errno
85 * variable that is used by GnuTLS (e.g., the application is linked to
86 * msvcr71.dll and gnutls is linked to msvcrt.dll).
88 * If you don't have the @session variable easily accessible from the
89 * push/pull function, and don't worry about thread conflicts, you can
90 * also use gnutls_transport_set_global_errno().
91 **/
92 void
93 gnutls_transport_set_errno (gnutls_session_t session, int err)
95 session->internals.errnum = err;
98 /**
99 * gnutls_transport_set_global_errno:
100 * @err: error value to store in global errno variable.
102 * Store @err in the global errno variable. Useful values for @err is
103 * EAGAIN and EINTR, other values are treated will be treated as real
104 * errors in the push/pull function.
106 * This function is useful in replacement push/pull functions set by
107 * gnutls_transport_set_push_function and
108 * gnutls_transport_set_pullpush_function under Windows, where the
109 * replacement push/pull may not have access to the same @errno
110 * variable that is used by GnuTLS (e.g., the application is linked to
111 * msvcr71.dll and gnutls is linked to msvcrt.dll).
113 * Whether this function is thread safe or not depends on whether the
114 * global variable errno is thread safe, some system libraries make it
115 * a thread-local variable. When feasible, using the guaranteed
116 * thread-safe gnutls_transport_set_errno() may be better.
118 void
119 gnutls_transport_set_global_errno (int err)
121 #ifdef _WIN32
122 /* Keep this in sync with system_errno */
123 switch (err)
125 case EAGAIN:
126 SetLastError (WSAEWOULDBLOCK);
127 break;
128 case EINTR:
129 SetLastError (WSAEINTR);
130 break;
131 default:
132 /* We don't care about anything else */
133 SetLastError (NO_ERROR);
134 break;
136 #else
137 errno = err;
138 #endif
141 /* Buffers received packets of type APPLICATION DATA and
142 * HANDSHAKE DATA.
145 _gnutls_record_buffer_put (content_type_t type,
146 gnutls_session_t session, opaque * data,
147 size_t length)
149 gnutls_buffer_st *buf;
151 if (length == 0)
152 return 0;
154 switch (type)
156 case GNUTLS_APPLICATION_DATA:
157 buf = &session->internals.application_data_buffer;
158 _gnutls_buffers_log ("BUF[REC]: Inserted %d bytes of Data(%d)\n",
159 (int) length, (int) type);
160 break;
162 case GNUTLS_HANDSHAKE:
163 buf = &session->internals.handshake_data_buffer;
164 _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data(%d)\n",
165 (int) length, (int) type);
166 break;
168 case GNUTLS_INNER_APPLICATION:
169 buf = &session->internals.ia_data_buffer;
170 _gnutls_buffers_log ("BUF[IA]: Inserted %d bytes of Data(%d)\n",
171 (int) length, (int) type);
172 break;
174 default:
175 gnutls_assert ();
176 return GNUTLS_E_INVALID_REQUEST;
179 if (_gnutls_buffer_append_data (buf, data, length) < 0)
181 gnutls_assert ();
182 return GNUTLS_E_MEMORY_ERROR;
185 return 0;
189 _gnutls_record_buffer_get_size (content_type_t type, gnutls_session_t session)
191 switch (type)
193 case GNUTLS_APPLICATION_DATA:
194 return session->internals.application_data_buffer.length;
196 case GNUTLS_HANDSHAKE:
197 return session->internals.handshake_data_buffer.length;
199 case GNUTLS_INNER_APPLICATION:
200 return session->internals.ia_data_buffer.length;
202 default:
203 return GNUTLS_E_INVALID_REQUEST;
208 * gnutls_record_check_pending:
209 * @session: is a #gnutls_session_t structure.
211 * This function checks if there are any data to receive in the gnutls
212 * buffers.
214 * Returns: the size of that data or 0.
216 size_t
217 gnutls_record_check_pending (gnutls_session_t session)
219 return _gnutls_record_buffer_get_size (GNUTLS_APPLICATION_DATA, session);
223 _gnutls_record_buffer_get (content_type_t type,
224 gnutls_session_t session, opaque * data,
225 size_t length)
227 if (length == 0 || data == NULL)
229 gnutls_assert ();
230 return GNUTLS_E_INVALID_REQUEST;
233 switch (type)
235 case GNUTLS_APPLICATION_DATA:
236 _gnutls_buffer_pop_data (&session->internals.application_data_buffer,
237 data, &length);
238 _gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n",
239 (int) length, (int) type);
240 break;
242 case GNUTLS_HANDSHAKE:
243 _gnutls_buffer_pop_data (&session->internals.handshake_data_buffer,
244 data, &length);
245 _gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n",
246 (int) length, (int) type);
247 break;
249 case GNUTLS_INNER_APPLICATION:
251 _gnutls_buffer_pop_data (&session->internals.ia_data_buffer, data,
252 &length);
253 _gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n",
254 (int) length, (int) type);
255 break;
257 default:
258 gnutls_assert ();
259 return GNUTLS_E_INVALID_REQUEST;
263 return length;
266 inline static void
267 reset_errno (gnutls_session_t session)
269 session->internals.errnum = 0;
272 inline static int
273 get_errno (gnutls_session_t session)
275 if (session->internals.errnum != 0)
276 return session->internals.errnum;
277 else
278 return session->internals.errno_func (session->
279 internals.transport_recv_ptr);
283 /* This function is like read. But it does not return -1 on error.
284 * It does return gnutls_errno instead.
286 * Flags are only used if the default recv() function is being used.
288 static ssize_t
289 _gnutls_read (gnutls_session_t session, mbuffer_st ** bufel,
290 size_t size, gnutls_pull_func pull_func)
292 size_t left;
293 ssize_t i = 0;
294 char *ptr;
295 gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
297 if (!bufel)
299 gnutls_assert ();
300 return GNUTLS_E_INTERNAL_ERROR;
303 *bufel = _mbuffer_alloc (0, size);
304 if (!*bufel)
306 gnutls_assert ();
307 return GNUTLS_E_MEMORY_ERROR;
309 ptr = (*bufel)->msg.data;
311 session->internals.direction = 0;
313 left = size;
314 while (left > 0)
316 reset_errno (session);
318 i = pull_func (fd, &ptr[size - left], left);
320 if (i < 0)
322 int err = get_errno (session);
324 _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
325 (int) i, fd, errno, session->internals.errnum);
327 if (err == EAGAIN || err == EINTR)
329 if (size - left > 0)
332 _gnutls_read_log ("READ: returning %d bytes from %p\n",
333 (int) (size - left), fd);
335 goto finish;
338 if (err == EAGAIN)
339 return GNUTLS_E_AGAIN;
340 return GNUTLS_E_INTERRUPTED;
342 else
344 gnutls_assert ();
345 return GNUTLS_E_PULL_ERROR;
348 else
351 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);
353 if (i == 0)
354 break; /* EOF */
357 left -= i;
358 (*bufel)->msg.size += i;
361 finish:
363 if (_gnutls_log_level >= 7)
365 _gnutls_read_log ("READ: read %d bytes from %p\n",
366 (int) (size - left), fd);
370 return (size - left);
375 static ssize_t
376 _gnutls_writev_emu (gnutls_session_t session, const giovec_t * giovec,
377 int giovec_cnt)
379 int ret = 0, j = 0;
380 gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
381 void *iptr;
382 size_t sizeOfPtr;
383 size_t total = 0;
385 for (j = 0; j < giovec_cnt; j++)
387 sizeOfPtr = giovec[j].iov_len;
388 iptr = giovec[j].iov_base;
390 ret = session->internals.push_func (fd, iptr, sizeOfPtr);
392 if (ret == -1)
393 break;
395 total += ret;
397 if (ret != giovec[j].iov_len)
398 break;
401 if (total > 0)
402 return total;
404 return ret;
407 static ssize_t
408 _gnutls_writev (gnutls_session_t session, const giovec_t * giovec,
409 int giovec_cnt)
411 int i;
412 gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
414 reset_errno (session);
416 if (session->internals.push_func != NULL)
417 i = _gnutls_writev_emu (session, giovec, giovec_cnt);
418 else
419 i = session->internals.vec_push_func (fd, giovec, giovec_cnt);
421 if (i == -1)
423 int err = get_errno (session);
424 _gnutls_debug_log ("errno: %d\n", err);
425 if (err == EAGAIN)
426 return GNUTLS_E_AGAIN;
427 else if (err == EINTR)
428 return GNUTLS_E_INTERRUPTED;
429 else
431 gnutls_assert ();
432 return GNUTLS_E_PUSH_ERROR;
435 return i;
438 #define RCVLOWAT session->internals.lowat
440 /* This function is only used with berkeley style sockets.
441 * Clears the peeked data (read with MSG_PEEK).
444 _gnutls_io_clear_peeked_data (gnutls_session_t session)
446 mbuffer_st *peekdata;
447 int ret, sum;
449 if (session->internals.have_peeked_data == 0 || RCVLOWAT == 0)
450 return 0;
452 /* this was already read by using MSG_PEEK - so it shouldn't fail */
453 sum = 0;
455 { /* we need this to finish now */
456 ret =
457 _gnutls_read (session, &peekdata, RCVLOWAT - sum,
458 session->internals.pull_func);
459 if (ret > 0)
460 sum += ret;
461 _mbuffer_xfree (&peekdata);
463 while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN
464 || sum < RCVLOWAT);
466 if (ret < 0)
468 gnutls_assert ();
469 return ret;
472 session->internals.have_peeked_data = 0;
474 return 0;
477 /* This function is like recv(with MSG_PEEK). But it does not return -1 on error.
478 * It does return gnutls_errno instead.
479 * This function reads data from the socket and keeps them in a buffer, of up to
480 * MAX_RECV_SIZE.
482 * This is not a general purpose function. It returns EXACTLY the data requested,
483 * which are stored in a local (in the session) buffer.
486 ssize_t
487 _gnutls_io_read_buffered (gnutls_session_t session, size_t total,
488 content_type_t recv_type)
490 ssize_t ret = 0, ret2 = 0;
491 size_t min;
492 mbuffer_st *bufel = NULL;
493 size_t recvlowat, recvdata, readsize;
495 if (total > MAX_RECV_SIZE || total == 0)
497 gnutls_assert (); /* internal error */
498 return GNUTLS_E_INVALID_REQUEST;
501 /* If an external pull function is used, then do not leave
502 * any data into the kernel buffer.
504 if (session->internals.pull_func != system_read)
506 recvlowat = 0;
508 else
510 /* leave peeked data to the kernel space only if application data
511 * is received and we don't have any peeked
512 * data in gnutls session.
514 if (recv_type != GNUTLS_APPLICATION_DATA
515 && session->internals.have_peeked_data == 0)
516 recvlowat = 0;
517 else
518 recvlowat = RCVLOWAT;
523 /* calculate the actual size, ie. get the minimum of the
524 * buffered data and the requested data.
526 min = MIN (session->internals.record_recv_buffer.byte_length, total);
527 if (min > 0)
529 /* if we have enough buffered data
530 * then just return them.
532 if (min == total)
534 return min;
538 /* min is over zero. recvdata is the data we must
539 * receive in order to return the requested data.
541 recvdata = total - min;
542 readsize = recvdata - recvlowat;
544 /* Check if the previously read data plus the new data to
545 * receive are longer than the maximum receive buffer size.
547 if ((session->internals.record_recv_buffer.byte_length + recvdata) >
548 MAX_RECV_SIZE)
550 gnutls_assert (); /* internal error */
551 return GNUTLS_E_INVALID_REQUEST;
554 if (ret < 0)
556 gnutls_assert ();
557 return ret;
560 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer.
562 if (readsize > 0)
564 ret =
565 _gnutls_read (session, &bufel, readsize,
566 session->internals.pull_func);
568 /* return immediately if we got an interrupt or eagain
569 * error.
571 if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
573 _mbuffer_xfree (&bufel);
574 return ret;
578 /* copy fresh data to our buffer.
580 if (ret > 0)
582 _gnutls_read_log
583 ("RB: Have %d bytes into buffer. Adding %d bytes.\n",
584 (int) session->internals.record_recv_buffer.byte_length, (int) ret);
585 _gnutls_read_log ("RB: Requested %d bytes\n", (int) total);
587 _mbuffer_enqueue (&session->internals.record_recv_buffer, bufel);
589 else
590 _mbuffer_xfree (&bufel);
593 /* This is hack in order for select to work. Just leave recvlowat data,
594 * into the kernel buffer (using a read with MSG_PEEK), thus making
595 * select think, that the socket is ready for reading.
596 * MSG_PEEK is only used with berkeley style sockets.
598 if (ret == readsize && recvlowat > 0)
600 ret2 = _gnutls_read (session, &bufel, recvlowat, system_read_peek);
602 if (ret2 < 0 && gnutls_error_is_fatal (ret2) == 0)
604 _mbuffer_xfree (&bufel);
605 return ret2;
608 if (ret2 > 0)
610 _gnutls_read_log ("RB-PEEK: Read %d bytes in PEEK MODE.\n",
611 (int) ret2);
612 _gnutls_read_log
613 ("RB-PEEK: Have %d bytes into buffer. Adding %d bytes.\nRB: Requested %d bytes\n",
614 (int) session->internals.record_recv_buffer.byte_length,
615 (int) ret2, (int) total);
616 session->internals.have_peeked_data = 1;
617 _mbuffer_enqueue (&session->internals.record_recv_buffer, bufel);
619 else
620 _mbuffer_xfree (&bufel);
623 if (ret < 0 || ret2 < 0)
625 gnutls_assert ();
626 /* that's because they are initialized to 0 */
627 return MIN (ret, ret2);
630 ret += ret2;
632 if (ret > 0 && ret < recvlowat)
634 gnutls_assert ();
635 return GNUTLS_E_AGAIN;
638 if (ret == 0)
639 { /* EOF */
640 gnutls_assert ();
641 return 0;
644 ret = session->internals.record_recv_buffer.byte_length;
646 if ((ret > 0) && ((size_t) ret < total))
648 /* Short Read */
649 gnutls_assert ();
650 return GNUTLS_E_AGAIN;
652 else
654 return ret;
658 /* This function is like write. But it does not return -1 on error.
659 * It does return gnutls_errno instead.
661 * This function takes full responsibility of freeing msg->data.
663 * In case of E_AGAIN and E_INTERRUPTED errors, you must call
664 * gnutls_write_flush(), until it returns ok (0).
666 * We need to push exactly the data in msg->size, since we cannot send
667 * less data. In TLS the peer must receive the whole packet in order
668 * to decrypt and verify the integrity.
671 ssize_t
672 _gnutls_io_write_buffered (gnutls_session_t session,
673 mbuffer_st * bufel, unsigned int mflag)
675 mbuffer_head_st *const send_buffer = &session->internals.record_send_buffer;
677 _mbuffer_enqueue (send_buffer, bufel);
679 _gnutls_write_log
680 ("WRITE: enqueued %d bytes for %p. Total %d bytes.\n",
681 (int) bufel->msg.size, session->internals.transport_recv_ptr,
682 (int) send_buffer->byte_length);
684 if (mflag == MBUFFER_FLUSH)
685 return _gnutls_io_write_flush (session);
686 else
687 return bufel->msg.size;
690 typedef ssize_t (*send_func) (gnutls_session_t, const giovec_t *, int);
692 /* This function writes the data that are left in the
693 * TLS write buffer (ie. because the previous write was
694 * interrupted.
696 ssize_t
697 _gnutls_io_write_flush (gnutls_session_t session)
699 gnutls_datum_t msg;
700 mbuffer_head_st *send_buffer = &session->internals.record_send_buffer;
701 int ret;
702 ssize_t sent = 0, tosend = 0;
703 giovec_t iovec[MAX_QUEUE];
704 int i = 0;
705 mbuffer_st *cur;
707 _gnutls_write_log ("WRITE FLUSH: %d bytes in buffer.\n",
708 (int) send_buffer->byte_length);
710 for (cur = _mbuffer_get_first (send_buffer, &msg);
711 cur != NULL; cur = _mbuffer_get_next (cur, &msg))
713 iovec[i].iov_base = msg.data;
714 iovec[i++].iov_len = msg.size;
715 tosend += msg.size;
717 /* we buffer up to MAX_QUEUE messages */
718 if (i >= sizeof (iovec) / sizeof (iovec[0]))
720 gnutls_assert ();
721 return GNUTLS_E_INTERNAL_ERROR;
725 if (tosend == 0)
727 gnutls_assert();
728 return 0;
731 ret = _gnutls_writev (session, iovec, i);
732 if (ret >= 0)
734 _mbuffer_remove_bytes (send_buffer, ret);
735 _gnutls_write_log ("WRITE: wrote %d bytes, %d bytes left.\n",
736 ret, (int) send_buffer->byte_length);
738 sent += ret;
740 else if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN)
742 _gnutls_write_log ("WRITE interrupted: %d bytes left.\n",
743 (int) send_buffer->byte_length);
744 return ret;
746 else
748 _gnutls_write_log ("WRITE error: code %d, %d bytes left.\n",
749 ret, (int) send_buffer->byte_length);
751 gnutls_assert ();
752 return ret;
755 if (sent < tosend)
757 gnutls_assert ();
758 return GNUTLS_E_AGAIN;
761 return sent;
764 /* This function writes the data that are left in the
765 * Handshake write buffer (ie. because the previous write was
766 * interrupted.
769 ssize_t
770 _gnutls_handshake_io_write_flush (gnutls_session_t session)
772 mbuffer_head_st *const send_buffer =
773 &session->internals.handshake_send_buffer;
774 gnutls_datum_t msg;
775 int ret;
776 ssize_t total = 0;
777 mbuffer_st *cur;
779 _gnutls_write_log ("HWRITE FLUSH: %d bytes in buffer.\n",
780 (int) send_buffer->byte_length);
782 for (cur = _mbuffer_get_first (send_buffer, &msg);
783 cur != NULL; cur = _mbuffer_get_first (send_buffer, &msg))
785 ret = _gnutls_send_int (session, GNUTLS_HANDSHAKE,
786 session->internals.handshake_send_buffer_htype,
787 EPOCH_WRITE_CURRENT,
788 msg.data, msg.size, 0 /* do not flush */ );
790 if (ret >= 0)
792 _mbuffer_remove_bytes (send_buffer, ret);
794 _gnutls_write_log ("HWRITE: wrote %d bytes, %d bytes left.\n",
795 ret, (int) send_buffer->byte_length);
797 total += ret;
799 else
801 _gnutls_write_log ("HWRITE error: code %d, %d bytes left.\n",
802 ret, (int) send_buffer->byte_length);
804 gnutls_assert ();
805 return ret;
809 return _gnutls_io_write_flush (session);
814 /* This is a send function for the gnutls handshake
815 * protocol. Just makes sure that all data have been sent.
818 void
819 _gnutls_handshake_io_cache_int (gnutls_session_t session,
820 gnutls_handshake_description_t htype,
821 mbuffer_st * bufel)
823 mbuffer_head_st *const send_buffer =
824 &session->internals.handshake_send_buffer;
826 _mbuffer_enqueue (send_buffer, bufel);
827 session->internals.handshake_send_buffer_htype = htype;
829 _gnutls_write_log
830 ("HWRITE: enqueued %d. Total %d bytes.\n",
831 (int) bufel->msg.size, (int) send_buffer->byte_length);
833 return;
836 /* This is a receive function for the gnutls handshake
837 * protocol. Makes sure that we have received all data.
839 ssize_t
840 _gnutls_handshake_io_recv_int (gnutls_session_t session,
841 content_type_t type,
842 gnutls_handshake_description_t htype,
843 void *iptr, size_t sizeOfPtr)
845 size_t left;
846 ssize_t i;
847 opaque *ptr;
848 size_t dsize;
850 ptr = iptr;
851 left = sizeOfPtr;
853 if (sizeOfPtr == 0 || iptr == NULL)
855 gnutls_assert ();
856 return GNUTLS_E_INVALID_REQUEST;
859 if (session->internals.handshake_recv_buffer.length > 0)
861 size_t tmp;
863 /* if we have already received some data */
864 if (sizeOfPtr <= session->internals.handshake_recv_buffer.length)
866 /* if requested less data then return it.
868 gnutls_assert ();
870 tmp = sizeOfPtr;
871 _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer,
872 iptr, &tmp);
873 return tmp;
875 gnutls_assert ();
877 tmp = sizeOfPtr;
878 _gnutls_buffer_pop_data (&session->internals.handshake_recv_buffer,
879 iptr, &tmp);
880 left -= tmp;
882 htype = session->internals.handshake_recv_buffer_htype;
883 type = session->internals.handshake_recv_buffer_type;
886 while (left > 0)
888 dsize = sizeOfPtr - left;
889 i = _gnutls_recv_int (session, type, htype, &ptr[dsize], left);
890 if (i < 0)
893 if (dsize > 0 && (i == GNUTLS_E_INTERRUPTED || i == GNUTLS_E_AGAIN))
895 gnutls_assert ();
897 _gnutls_buffer_append_data (&session->internals.
898 handshake_recv_buffer, iptr, dsize);
900 session->internals.handshake_recv_buffer_htype = htype;
901 session->internals.handshake_recv_buffer_type = type;
904 return i;
906 else
908 if (i == 0)
909 break; /* EOF */
912 left -= i;
916 session->internals.handshake_recv_buffer.length = 0;
918 return sizeOfPtr - left;
921 /* Buffer for handshake packets. Keeps the packets in order
922 * for finished messages to use them. Used in HMAC calculation
923 * and finished messages.
926 _gnutls_handshake_buffer_put (gnutls_session_t session, opaque * data,
927 size_t length)
930 if (length == 0)
931 return 0;
933 if ((session->internals.max_handshake_data_buffer_size > 0) &&
934 ((length + session->internals.handshake_hash_buffer.length) >
935 session->internals.max_handshake_data_buffer_size))
937 gnutls_assert ();
938 return GNUTLS_E_HANDSHAKE_TOO_LARGE;
941 _gnutls_buffers_log ("BUF[HSK]: Inserted %d bytes of Data\n", (int) length);
942 if (_gnutls_buffer_append_data (&session->internals.handshake_hash_buffer,
943 data, length) < 0)
945 gnutls_assert ();
946 return GNUTLS_E_MEMORY_ERROR;
949 return 0;
953 _gnutls_handshake_buffer_get_size (gnutls_session_t session)
956 return session->internals.handshake_hash_buffer.length;
959 /* this function does not touch the buffer
960 * and returns data from it (peek mode!)
963 _gnutls_handshake_buffer_get_ptr (gnutls_session_t session,
964 opaque ** data_ptr, size_t * length)
966 if (length != NULL)
967 *length = session->internals.handshake_hash_buffer.length;
969 _gnutls_buffers_log ("BUF[HSK]: Peeked %d bytes of Data\n",
970 (int) session->internals.handshake_hash_buffer.length);
972 if (data_ptr != NULL)
973 *data_ptr = session->internals.handshake_hash_buffer.data;
975 return 0;
978 /* Does not free the buffer
981 _gnutls_handshake_buffer_empty (gnutls_session_t session)
984 _gnutls_buffers_log ("BUF[HSK]: Emptied buffer\n");
986 session->internals.handshake_hash_buffer.length = 0;
988 return 0;
993 _gnutls_handshake_buffer_clear (gnutls_session_t session)
996 _gnutls_buffers_log ("BUF[HSK]: Cleared Data from buffer\n");
997 _gnutls_buffer_clear (&session->internals.handshake_hash_buffer);
999 return 0;
1003 * gnutls_transport_set_pull_function:
1004 * @session: is a #gnutls_session_t structure.
1005 * @pull_func: a callback function similar to read()
1007 * This is the function where you set a function for gnutls to receive
1008 * data. Normally, if you use berkeley style sockets, do not need to
1009 * use this function since the default (recv(2)) will probably be ok.
1011 * PULL_FUNC is of the form,
1012 * ssize_t (*gnutls_pull_func)(gnutls_transport_ptr_t, void*, size_t);
1014 void
1015 gnutls_transport_set_pull_function (gnutls_session_t session,
1016 gnutls_pull_func pull_func)
1018 session->internals.pull_func = pull_func;
1022 * gnutls_transport_set_push_function:
1023 * @session: is a #gnutls_session_t structure.
1024 * @push_func: a callback function similar to write()
1026 * This is the function where you set a push function for gnutls to
1027 * use in order to send data. If you are going to use berkeley style
1028 * sockets, you do not need to use this function since the default
1029 * (send(2)) will probably be ok. Otherwise you should specify this
1030 * function for gnutls to be able to send data.
1032 * PUSH_FUNC is of the form,
1033 * ssize_t (*gnutls_push_func)(gnutls_transport_ptr_t, const void*, size_t);
1035 void
1036 gnutls_transport_set_push_function (gnutls_session_t session,
1037 gnutls_push_func push_func)
1039 session->internals.push_func = push_func;
1040 session->internals.vec_push_func = NULL;
1044 * gnutls_transport_set_vec_push_function:
1045 * @session: is a #gnutls_session_t structure.
1046 * @vec_func: a callback function similar to writev()
1048 * This is the function where you set a push function for gnutls to
1049 * use in order to send data. If you are going to use berkeley style
1050 * sockets, you do not need to use this function since the default
1051 * (send(2)) will probably be ok. Otherwise you should specify this
1052 * function for gnutls to be able to send data.
1054 * PUSH_FUNC is of the form,
1055 * ssize_t (*gnutls_push_func)(gnutls_transport_ptr_t, const void*, size_t);
1057 void
1058 gnutls_transport_set_vec_push_function (gnutls_session_t session,
1059 gnutls_vec_push_func vec_func)
1061 session->internals.push_func = NULL;
1062 session->internals.vec_push_func = vec_func;
1066 * gnutls_transport_set_errno_function:
1067 * @session: is a #gnutls_session_t structure.
1068 * @errno_func: a callback function similar to write()
1070 * This is the function where you set a function to retrieve errno
1071 * after a failed push or pull operation.
1073 * errno_func is of the form,
1074 * int (*gnutls_errno_func)(gnutls_transport_ptr_t);
1075 * and should return the errno.
1077 void
1078 gnutls_transport_set_errno_function (gnutls_session_t session,
1079 gnutls_errno_func errno_func)
1081 session->internals.errno_func = errno_func;