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>
65 #define EAGAIN EWOULDBLOCK
68 /* this is the maximum number of messages allowed to queue.
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().
93 gnutls_transport_set_errno (gnutls_session_t session
, int err
)
95 session
->internals
.errnum
= err
;
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.
119 gnutls_transport_set_global_errno (int err
)
122 /* Keep this in sync with system_errno */
126 SetLastError (WSAEWOULDBLOCK
);
129 SetLastError (WSAEINTR
);
132 /* We don't care about anything else */
133 SetLastError (NO_ERROR
);
141 /* Buffers received packets of type APPLICATION DATA and
145 _gnutls_record_buffer_put (content_type_t type
,
146 gnutls_session_t session
, opaque
* data
,
149 gnutls_buffer_st
*buf
;
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
);
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
);
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
);
176 return GNUTLS_E_INVALID_REQUEST
;
179 if (_gnutls_buffer_append_data (buf
, data
, length
) < 0)
182 return GNUTLS_E_MEMORY_ERROR
;
189 _gnutls_record_buffer_get_size (content_type_t type
, gnutls_session_t session
)
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
;
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
214 * Returns: the size of that data or 0.
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
,
227 if (length
== 0 || data
== NULL
)
230 return GNUTLS_E_INVALID_REQUEST
;
235 case GNUTLS_APPLICATION_DATA
:
236 _gnutls_buffer_pop_data (&session
->internals
.application_data_buffer
,
238 _gnutls_buffers_log ("BUFFER[REC][AD]: Read %d bytes of Data(%d)\n",
239 (int) length
, (int) type
);
242 case GNUTLS_HANDSHAKE
:
243 _gnutls_buffer_pop_data (&session
->internals
.handshake_data_buffer
,
245 _gnutls_buffers_log ("BUF[REC][HD]: Read %d bytes of Data(%d)\n",
246 (int) length
, (int) type
);
249 case GNUTLS_INNER_APPLICATION
:
251 _gnutls_buffer_pop_data (&session
->internals
.ia_data_buffer
, data
,
253 _gnutls_buffers_log ("BUF[REC][IA]: Read %d bytes of Data(%d)\n",
254 (int) length
, (int) type
);
259 return GNUTLS_E_INVALID_REQUEST
;
267 reset_errno (gnutls_session_t session
)
269 session
->internals
.errnum
= 0;
273 get_errno (gnutls_session_t session
)
275 if (session
->internals
.errnum
!= 0)
276 return session
->internals
.errnum
;
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.
289 _gnutls_read (gnutls_session_t session
, mbuffer_st
** bufel
,
290 size_t size
, gnutls_pull_func pull_func
)
295 gnutls_transport_ptr_t fd
= session
->internals
.transport_recv_ptr
;
300 return GNUTLS_E_INTERNAL_ERROR
;
303 *bufel
= _mbuffer_alloc (0, size
);
307 return GNUTLS_E_MEMORY_ERROR
;
309 ptr
= (*bufel
)->msg
.data
;
311 session
->internals
.direction
= 0;
316 reset_errno (session
);
318 i
= pull_func (fd
, &ptr
[size
- left
], left
);
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
)
332 _gnutls_read_log ("READ: returning %d bytes from %p\n",
333 (int) (size
- left
), fd
);
339 return GNUTLS_E_AGAIN
;
340 return GNUTLS_E_INTERRUPTED
;
345 return GNUTLS_E_PULL_ERROR
;
351 _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i
, fd
);
358 (*bufel
)->msg
.size
+= i
;
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
);
376 _gnutls_writev_emu (gnutls_session_t session
, const giovec_t
* giovec
,
380 gnutls_transport_ptr_t fd
= session
->internals
.transport_send_ptr
;
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
);
397 if (ret
!= giovec
[j
].iov_len
)
408 _gnutls_writev (gnutls_session_t session
, const giovec_t
* giovec
,
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
);
419 i
= session
->internals
.vec_push_func (fd
, giovec
, giovec_cnt
);
423 int err
= get_errno (session
);
424 _gnutls_debug_log ("errno: %d\n", err
);
426 return GNUTLS_E_AGAIN
;
427 else if (err
== EINTR
)
428 return GNUTLS_E_INTERRUPTED
;
432 return GNUTLS_E_PUSH_ERROR
;
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
;
449 if (session
->internals
.have_peeked_data
== 0 || RCVLOWAT
== 0)
452 /* this was already read by using MSG_PEEK - so it shouldn't fail */
455 { /* we need this to finish now */
457 _gnutls_read (session
, &peekdata
, RCVLOWAT
- sum
,
458 session
->internals
.pull_func
);
461 _mbuffer_xfree (&peekdata
);
463 while (ret
== GNUTLS_E_INTERRUPTED
|| ret
== GNUTLS_E_AGAIN
472 session
->internals
.have_peeked_data
= 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
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.
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;
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
)
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)
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
);
529 /* if we have enough buffered data
530 * then just return them.
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
) >
550 gnutls_assert (); /* internal error */
551 return GNUTLS_E_INVALID_REQUEST
;
560 /* READ DATA - but leave RCVLOWAT bytes in the kernel buffer.
565 _gnutls_read (session
, &bufel
, readsize
,
566 session
->internals
.pull_func
);
568 /* return immediately if we got an interrupt or eagain
571 if (ret
< 0 && gnutls_error_is_fatal (ret
) == 0)
573 _mbuffer_xfree (&bufel
);
578 /* copy fresh data to our buffer.
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
);
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
);
610 _gnutls_read_log ("RB-PEEK: Read %d bytes in PEEK MODE.\n",
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
);
620 _mbuffer_xfree (&bufel
);
623 if (ret
< 0 || ret2
< 0)
626 /* that's because they are initialized to 0 */
627 return MIN (ret
, ret2
);
632 if (ret
> 0 && ret
< recvlowat
)
635 return GNUTLS_E_AGAIN
;
644 ret
= session
->internals
.record_recv_buffer
.byte_length
;
646 if ((ret
> 0) && ((size_t) ret
< total
))
650 return GNUTLS_E_AGAIN
;
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.
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
);
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
);
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
697 _gnutls_io_write_flush (gnutls_session_t session
)
700 mbuffer_head_st
*send_buffer
= &session
->internals
.record_send_buffer
;
702 ssize_t sent
= 0, tosend
= 0;
703 giovec_t iovec
[MAX_QUEUE
];
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
;
717 /* we buffer up to MAX_QUEUE messages */
718 if (i
>= sizeof (iovec
) / sizeof (iovec
[0]))
721 return GNUTLS_E_INTERNAL_ERROR
;
731 ret
= _gnutls_writev (session
, iovec
, i
);
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
);
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
);
748 _gnutls_write_log ("WRITE error: code %d, %d bytes left.\n",
749 ret
, (int) send_buffer
->byte_length
);
758 return GNUTLS_E_AGAIN
;
764 /* This function writes the data that are left in the
765 * Handshake write buffer (ie. because the previous write was
770 _gnutls_handshake_io_write_flush (gnutls_session_t session
)
772 mbuffer_head_st
*const send_buffer
=
773 &session
->internals
.handshake_send_buffer
;
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
,
788 msg
.data
, msg
.size
, 0 /* do not flush */ );
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
);
801 _gnutls_write_log ("HWRITE error: code %d, %d bytes left.\n",
802 ret
, (int) send_buffer
->byte_length
);
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.
819 _gnutls_handshake_io_cache_int (gnutls_session_t session
,
820 gnutls_handshake_description_t htype
,
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
;
830 ("HWRITE: enqueued %d. Total %d bytes.\n",
831 (int) bufel
->msg
.size
, (int) send_buffer
->byte_length
);
836 /* This is a receive function for the gnutls handshake
837 * protocol. Makes sure that we have received all data.
840 _gnutls_handshake_io_recv_int (gnutls_session_t session
,
842 gnutls_handshake_description_t htype
,
843 void *iptr
, size_t sizeOfPtr
)
853 if (sizeOfPtr
== 0 || iptr
== NULL
)
856 return GNUTLS_E_INVALID_REQUEST
;
859 if (session
->internals
.handshake_recv_buffer
.length
> 0)
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.
871 _gnutls_buffer_pop_data (&session
->internals
.handshake_recv_buffer
,
878 _gnutls_buffer_pop_data (&session
->internals
.handshake_recv_buffer
,
882 htype
= session
->internals
.handshake_recv_buffer_htype
;
883 type
= session
->internals
.handshake_recv_buffer_type
;
888 dsize
= sizeOfPtr
- left
;
889 i
= _gnutls_recv_int (session
, type
, htype
, &ptr
[dsize
], left
);
893 if (dsize
> 0 && (i
== GNUTLS_E_INTERRUPTED
|| i
== GNUTLS_E_AGAIN
))
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
;
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
,
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
))
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
,
946 return GNUTLS_E_MEMORY_ERROR
;
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
)
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
;
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;
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
);
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);
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);
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);
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.
1078 gnutls_transport_set_errno_function (gnutls_session_t session
,
1079 gnutls_errno_func errno_func
)
1081 session
->internals
.errno_func
= errno_func
;