diff src/lstream.c @ 5922:4b055de36bb9 cygwin

merging heads 2
author Henry Thompson <ht@markup.co.uk>
date Fri, 27 Feb 2015 17:47:15 +0000
parents a216b3c2b09e
children
line wrap: on
line diff
--- a/src/lstream.c	Wed Apr 23 22:22:37 2014 +0100
+++ b/src/lstream.c	Fri Feb 27 17:47:15 2015 +0000
@@ -28,6 +28,7 @@
 #include "buffer.h"
 #include "insdel.h"
 #include "lstream.h"
+#include "tls.h"
 
 #include "sysfile.h"
 
@@ -742,6 +743,12 @@
   return Lstream_read_1 (lstr, data, size, 0);
 }
 
+int
+Lstream_errno (Lstream *lstr)
+{
+  return (lstr->imp->error) ? (lstr->imp->error) (lstr) : 0;
+}
+
 Charcount
 Lstream_character_tell (Lstream *lstr)
 {
@@ -984,6 +991,25 @@
   Lstream_unread (lstr, &ch, 1);
 }
 
+/* Detect an active TLS session */
+
+int
+Lstream_tls_p (Lstream *lstr)
+{
+  return (lstr->imp->tls_p) ? (lstr->imp->tls_p) (lstr) : 0;
+}
+
+/* STARTTLS negotiation */
+
+int
+Lstream_tls_negotiate (Lstream *instr, Lstream *outstr, const Extbyte *host,
+		       Lisp_Object keylist)
+{
+  return (instr->imp->tls_negotiater)
+    ? (instr->imp->tls_negotiater) (instr, outstr, host, keylist)
+    : 0;
+}
+
 
 /************************ some stream implementations *********************/
 
@@ -1111,6 +1137,7 @@
 
 struct filedesc_stream
 {
+  tls_state_t *tls_state;
   int fd;
   int pty_max_bytes;
   Ibyte eof_char;
@@ -1118,6 +1145,7 @@
   int current_pos;
   int end_pos;
   int chars_sans_newline;
+  int saved_errno;
   unsigned int closing :1;
   unsigned int allow_quit :1;
   unsigned int blocked_ok :1;
@@ -1135,18 +1163,20 @@
    ignored when writing); -1 for unlimited. */
 static Lisp_Object
 make_filedesc_stream_1 (int filedesc, int offset, int count, int flags,
-			const char *mode)
+			tls_state_t *state, const char *mode)
 {
   Lstream *lstr = Lstream_new (lstream_filedesc, mode);
   struct filedesc_stream *fstr = FILEDESC_STREAM_DATA (lstr);
-  fstr->fd = filedesc;
+  fstr->tls_state = state;
+  fstr->fd = state ? tls_get_fd (state) : filedesc;
   fstr->closing      = !!(flags & LSTR_CLOSING);
   fstr->allow_quit   = !!(flags & LSTR_ALLOW_QUIT);
   fstr->blocked_ok   = !!(flags & LSTR_BLOCKED_OK);
   fstr->pty_flushing = !!(flags & LSTR_PTY_FLUSHING);
   fstr->blocking_error_p = 0;
   fstr->chars_sans_newline = 0;
-  fstr->starting_pos = lseek (filedesc, offset, SEEK_CUR);
+  fstr->saved_errno = 0;
+  fstr->starting_pos = lseek (fstr->fd, offset, SEEK_CUR);
   fstr->current_pos = max (fstr->starting_pos, 0);
   if (count < 0)
     fstr->end_pos = -1;
@@ -1176,15 +1206,17 @@
  */
 
 Lisp_Object
-make_filedesc_input_stream (int filedesc, int offset, int count, int flags)
+make_filedesc_input_stream (int filedesc, int offset, int count, int flags,
+			    tls_state_t *state)
 {
-  return make_filedesc_stream_1 (filedesc, offset, count, flags, "r");
+  return make_filedesc_stream_1 (filedesc, offset, count, flags, state, "r");
 }
 
 Lisp_Object
-make_filedesc_output_stream (int filedesc, int offset, int count, int flags)
+make_filedesc_output_stream (int filedesc, int offset, int count, int flags,
+			     tls_state_t *state)
 {
-  return make_filedesc_stream_1 (filedesc, offset, count, flags, "w");
+  return make_filedesc_stream_1 (filedesc, offset, count, flags, state, "w");
 }
 
 static Bytecount
@@ -1192,17 +1224,23 @@
 {
   Bytecount nread;
   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
+  str->saved_errno = 0;
   if (str->end_pos >= 0)
     size = min (size, (Bytecount) (str->end_pos - str->current_pos));
-  nread = str->allow_quit ?
-    read_allowing_quit (str->fd, data, size) :
-    retry_read (str->fd, data, size);
+  nread = str->tls_state
+    ? tls_read (str->tls_state, data, size, str->allow_quit)
+    : (str->allow_quit ?
+       read_allowing_quit (str->fd, data, size) :
+       retry_read (str->fd, data, size));
   if (nread > 0)
     str->current_pos += nread;
   if (nread == 0)
     return 0; /* LSTREAM_EOF; */
   if (nread < 0)
-    return LSTREAM_ERROR;
+    {
+      str->saved_errno = errno;
+      return LSTREAM_ERROR;
+    }
   return nread;
 }
 
@@ -1228,6 +1266,8 @@
   Bytecount retval;
   int need_newline = 0;
 
+  str->saved_errno = 0;
+
   /* This function would be simple if it were not for the blasted
      PTY max-bytes stuff.  Why the hell can't they just have written
      the PTY drivers right so this problem doesn't exist?
@@ -1254,9 +1294,11 @@
 
   /**** start of non-PTY-crap ****/
   if (size > 0)
-    retval = str->allow_quit ?
-      write_allowing_quit (str->fd, data, size) :
-      retry_write (str->fd, data, size);
+    retval = str->tls_state
+      ? tls_write (str->tls_state, data, size, str->allow_quit)
+      : (str->allow_quit ?
+	 write_allowing_quit (str->fd, data, size) :
+	 retry_write (str->fd, data, size));
   else
     retval = 0;
   if (retval < 0 && errno_would_block_p (errno) && str->blocked_ok)
@@ -1266,7 +1308,10 @@
     }
   str->blocking_error_p = 0;
   if (retval < 0)
-    return LSTREAM_ERROR;
+    {
+      str->saved_errno = errno;
+      return LSTREAM_ERROR;
+    }
   /**** end non-PTY-crap ****/
 
   if (str->pty_flushing)
@@ -1298,7 +1343,10 @@
 		      return 0;
 		    }
 		  else
-		    return LSTREAM_ERROR;
+		    {
+		      str->saved_errno = errno;
+		      return LSTREAM_ERROR;
+		    }
 		}
 	      else
 		return retval;
@@ -1334,7 +1382,10 @@
 		  return 0;
 		}
 	      else
-		return LSTREAM_ERROR;
+		{
+		  str->saved_errno = errno;
+		  return LSTREAM_ERROR;
+		}
 	    }
 	  else
 	    return retval;
@@ -1345,6 +1396,13 @@
 }
 
 static int
+filedesc_error (Lstream *stream)
+{
+  struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
+  return str->saved_errno;
+}
+
+static int
 filedesc_rewinder (Lstream *stream)
 {
   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
@@ -1379,7 +1437,9 @@
 filedesc_closer (Lstream *stream)
 {
   struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
-  if (str->closing)
+  if (str->tls_state)
+    return tls_close (str->tls_state);
+  else if (str->closing)
     return retry_close (str->fd);
   else
     return 0;
@@ -1409,6 +1469,32 @@
   return str->fd;
 }
 
+static int
+filedesc_tls_p (Lstream *stream)
+{
+  struct filedesc_stream *str = FILEDESC_STREAM_DATA (stream);
+  return str->tls_state != NULL;
+}
+
+static int
+filedesc_tls_negotiater (Lstream *instream, Lstream *outstream,
+			 const Extbyte *host, Lisp_Object keylist)
+{
+  struct filedesc_stream *in_str, *out_str;
+
+  if (!LSTREAM_TYPE_P (outstream, filedesc))
+    invalid_argument ("STARTTLS applies to file descriptor streams only",
+		      wrap_lstream (outstream));
+
+  in_str = FILEDESC_STREAM_DATA (instream);
+  out_str = FILEDESC_STREAM_DATA (outstream);
+  in_str->tls_state = out_str->tls_state =
+    tls_negotiate (out_str->fd, host, keylist);
+  if (out_str->tls_state != NULL)
+    in_str->fd = out_str->fd = tls_get_fd (out_str->tls_state);
+  return out_str->tls_state != NULL;
+}
+
 /*********** read from a Lisp string ***********/
 
 #define LISP_STRING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, lisp_string)
@@ -1926,10 +2012,13 @@
 
   LSTREAM_HAS_METHOD (filedesc, reader);
   LSTREAM_HAS_METHOD (filedesc, writer);
+  LSTREAM_HAS_METHOD (filedesc, error);
   LSTREAM_HAS_METHOD (filedesc, was_blocked_p);
   LSTREAM_HAS_METHOD (filedesc, rewinder);
   LSTREAM_HAS_METHOD (filedesc, seekable_p);
   LSTREAM_HAS_METHOD (filedesc, closer);
+  LSTREAM_HAS_METHOD (filedesc, tls_p);
+  LSTREAM_HAS_METHOD (filedesc, tls_negotiater);
 
   LSTREAM_HAS_METHOD (lisp_string, reader);
   LSTREAM_HAS_METHOD (lisp_string, rewinder);