gnutls-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnutls-dev] Re: Gnutls4win: Problem with custom push/pull functions, er


From: Simon Josefsson
Subject: [gnutls-dev] Re: Gnutls4win: Problem with custom push/pull functions, errno and Visual Studio (Workaround included)
Date: Sun, 05 Nov 2006 10:24:58 +0100
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/22.0.90 (gnu/linux)

This patch actually compiles...

/Simon

--- gnutls_int.h        13 Aug 2006 17:08:15 +0200      2.369
+++ gnutls_int.h        05 Nov 2006 10:18:25 +0100      
@@ -598,6 +598,16 @@
    */
   gnutls_datum_t recv_buffer;
 
+  /* To avoid using global variables, and especially on Windows where
+   * the application may use a different errno variable than GnuTLS,
+   * it is possible to use gnutls_transport_set_errno to set a
+   * session-specific errno variable in the user-replaceable push/pull
+   * functions.  This value is used by the send/recv functions.  (the
+   * strange name of this variable is because 'errno' is typically
+   * #define'd.)
+   */
+  int errnum;
+
   /* If you add anything here, check _gnutls_handshake_internal_state_clear().
    */
 } internals_st;
--- gnutls_buffers.c    13 Aug 2006 17:05:52 +0200      2.128
+++ gnutls_buffers.c    05 Nov 2006 10:20:05 +0100      
@@ -77,6 +77,54 @@
 # include <io_debug.h>
 #endif
 
+/**
+ * gnutls_transport_set_errno:
+ * @session: is a #gnutls_session_t structure.
+ * @err: error value to store in session-specific errno variable.
+ *
+ * Store @err in the session-specific errno variable.
+ *
+ * This function is useful in replacement push/pull functions set by
+ * gnutls_transport_set_push_function and
+ * gnutls_transport_set_pullpush_function under Windows, where the
+ * replacement push/pull may not have access to the same @errno
+ * variable that is used by GnuTLS (e.g., the application is linked to
+ * msvcr71.dll and gnutls is linked to msvcrt.dll).
+ *
+ * If you don't have the @session variable easily accessible from the
+ * push/pull function, and don't worry about thread conflicts, you can
+ * also use gnutls_transport_set_global_errno().
+ **/
+void
+gnutls_transport_set_errno (gnutls_session_t session, int err)
+{
+  session->internals.errnum = err;
+}
+
+/**
+ * gnutls_transport_set_global_errno:
+ * @err: error value to store in global errno variable.
+ *
+ * Store @err in the global errno variable.
+ *
+ * This function is useful in replacement push/pull functions set by
+ * gnutls_transport_set_push_function and
+ * gnutls_transport_set_pullpush_function under Windows, where the
+ * replacement push/pull may not have access to the same @errno
+ * variable that is used by GnuTLS (e.g., the application is linked to
+ * msvcr71.dll and gnutls is linked to msvcrt.dll).
+ *
+ * Whether this function is thread safe or not depends on whether the
+ * global variable errno is thread safe, some system libraries make it
+ * a thread-local variable.  When feasible, using the guaranteed
+ * thread-safe gnutls_transport_set_errno() may be better.
+ **/
+void
+gnutls_transport_set_global_errno (int err)
+{
+  errno = err;
+}
+
 /* Buffers received packets of type APPLICATION DATA and
  * HANDSHAKE DATA.
  */
@@ -264,6 +312,8 @@
   while (left > 0)
     {
 
+      session->internals.errnum = 0;
+
       if (session->internals._gnutls_pull_func == NULL)
        i = recv (GNUTLS_POINTER_TO_INT(fd), &ptr[sizeOfPtr - left],
                  left, flags);
@@ -274,10 +324,13 @@
 
       if (i < 0)
        {
-         _gnutls_read_log ("READ: %d returned from %d, errno=%d\n", i,
-                           fd, errno);
+         int err = session->internals.errnum ? session->internals.errnum
+           : errno;
+
+         _gnutls_read_log ("READ: %d returned from %d, errno=%d gerrno=%d\n",
+                           i, fd, errno, session->internals.errnum);
 
-         if (errno == EAGAIN || errno == EINTR)
+         if (err == EAGAIN || err == EINTR)
            {
              if (sizeOfPtr - left > 0)
                {
@@ -289,7 +342,7 @@
                }
              gnutls_assert ();
 
-             return RET (errno);
+             return RET (err);
            }
          else
            {
@@ -701,6 +754,8 @@
   while (left > 0)
     {
 
+      session->internals.errnum = 0;
+
       if (session->internals._gnutls_push_func == NULL)
        i = send (GNUTLS_POINTER_TO_INT(fd), &ptr[n - left], left, 0);
       else
@@ -708,7 +763,10 @@
 
       if (i == -1)
        {
-         if (errno == EAGAIN || errno == EINTR)
+         int err = session->internals.errnum ? session->internals.errnum
+           : errno;
+
+         if (err == EAGAIN || err == EINTR)
            {
              session->internals.record_send_buffer_prev_size += n - left;
 
@@ -726,7 +784,7 @@
                ("WRITE: Interrupted. Stored %d bytes to buffer. Already sent 
%d bytes.\n",
                 left, n - left);
 
-             retval = RET (errno);
+             retval = RET (err);
 
              return retval;
            }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]