diff --git a/lib/modules/SSL.pmod/sslfile.pike b/lib/modules/SSL.pmod/sslfile.pike
index 3cc5322f1058199ea00cbb27e68dfd4c204e81f4..a04397b72bf0020f3f3550a91b3ada386b8fd7d8 100644
--- a/lib/modules/SSL.pmod/sslfile.pike
+++ b/lib/modules/SSL.pmod/sslfile.pike
@@ -7,7 +7,7 @@ inherit "connection" : connection;
 
 object context;
   
-string read_buffer; /* Data that is recieved before there is any
+string read_buffer; /* Data that is received before there is any
 		     * read_callback */
 string write_buffer; /* Data to be written */
 function(mixed,string:void) read_callback;
@@ -19,11 +19,14 @@ int connected; /* 1 if the connect callback has been called */
 int blocking;  /* 1 if in blocking mode.
 		* So far, there's no true blocking i/o, read and write
 		* requests are just queued up. */
+int is_closed;
+
+private void ssl_write_callback(mixed id);
 
 private void die(int status)
 {
 #ifdef SSL3_DEBUG
-  werror("SSL.sslfile->die\n");
+  werror(sprintf("SSL.sslfile->die: is_closed = %d\n", is_closed));
 #endif
   if (status < 0)
   {
@@ -33,48 +36,44 @@ private void die(int status)
     werror("SSL.sslfile: Killed\n");
 #endif
   }
-  if (close_callback)
-    close_callback(socket::query_id());
+  is_closed = 1;
   socket::close();
 }
   
 /* Return 0 if the connection is still alive,
    * 1 if it was closed politely, and -1 if it died unexpectedly
    */
-private int try_write()
+private int queue_write()
 {
   int|string data = to_write();
 #ifdef SSL3_DEBUG
-  werror(sprintf("sslport->try_write: '%O'\n", data));
+  werror(sprintf("SSL.sslfile->queue_write: '%O'\n", data));
+  werror(master()->describe_backtrace(backtrace()));
 #endif
   if (stringp(data))
     write_buffer += data;
-  if (strlen(write_buffer))
-  {
-    int written = socket::write(write_buffer);
-    if (written > 0)
-      write_buffer = write_buffer[written..];
-    else
-    {
 #ifdef SSL3_DEBUG
-      werror("SSL.sslfile->try_write: write failed\n");
+  werror(sprintf("SSL.sslfile->queue_write: buffer = '%s'\n", write_buffer));
 #endif
-      return -1;
-    }
-  }
+
+  socket::set_write_callback(ssl_write_callback);
+  
 #ifdef SSL3_DEBUG
-  werror("SSL.sslfile->try_write: end\n");
+  werror("SSL.sslfile->queue_write: end\n");
 #endif
   return stringp(data) ? 0 : data;
 }
 
 void close()
 {
+  if (is_closed)
+    throw( ({ "SSL.sslfile->close: Already closed!\n", backtrace() }) );
 #ifdef SSL3_DEBUG
   werror("SSL.sslfile->close\n");
 #endif
-  send_packet(Alert(ALERT_warning, ALERT_close_notify));
-  try_write();
+  is_closed = 1;
+  send_close();
+  queue_write();
   read_callback = 0;
   write_callback = 0;
   close_callback = 0;
@@ -96,7 +95,13 @@ int write(string s)
     send_packet(packet);
     s = s[PACKET_MAX_SIZE..];
   }
-  (res = try_write()) && die(res);
+#if 0
+  if (queue_write() == -1)
+  {
+    die(-1);
+    return -1;
+  }
+#endif
   return len;
 }
 
@@ -114,31 +119,38 @@ private void ssl_read_callback(mixed id, string s)
   if (stringp(data))
   {
 #ifdef SSL3_DEBUG
-    werror(sprintf("SSL.sslfile: application_data: '%s'\n", data));
+    werror(sprintf("SSL.sslfile->ssl_read_callback: application_data: '%s'\n", data));
 #endif
+    if (!connected && handshake_finished)
+    {
+      connected = 1;
+      if (accept_callback)
+	accept_callback(this_object());
+    }
     if (strlen(data))
     {
       read_buffer += data;
-      if (!connected)
-      {
-	connected = 1;
-	if (accept_callback)
-	  accept_callback(this_object());
-      }
       if (!blocking && read_callback && strlen(read_buffer))
       {
 	read_callback(id, read_buffer + data);
 	read_buffer = "";
       }
     }
+  } else {
+    if (data > 0)
+    {
+      if (close_callback)
+	close_callback();
+    }
+    else
+      if (data < 0)
+      {
+	/* Fatal error, remove from session cache */
+	die(-1);
+	return;
+      }
   }
-  else
-  {
-    if (data < 0)
-      /* Fatal error, remove from session cache */
-      context->purge_session(this_object());
-  }
-  int res = try_write();
+  int res = queue_write();
   if (res)
     die(res);
 }
@@ -150,18 +162,34 @@ private void ssl_write_callback(mixed id)
 		 "blocking = %d, write_callback = %O\n",
 		 handshake_finished, blocking, write_callback));
 #endif
-  int res;
+
+  if (strlen(write_buffer))
+  {
+    int written = socket::write(write_buffer);
+    if (written > 0)
+    {
+      write_buffer = write_buffer[written ..];
+    } else {
+      if (written < 0)
+	die(-1);
+    }
+  }
+  int res = queue_write();
+#ifdef SSL3_DEBUG
+  werror(sprintf("SSL.sslport->ssl_write_callback: res = '%O'\n", res));
+#endif
   
-  if ( !(res = try_write()) && !strlen(write_buffer)
-       && handshake_finished && !blocking && write_callback)
+  if ( !res && !strlen(write_buffer)
+       && connected && !blocking && write_callback)
   {
 #ifdef SSL3_DEBUG
-  werror("SSL.sslport->ssl_write_callback: Calling write_callback\n");
+    werror("SSL.sslport->ssl_write_callback: Calling write_callback\n");
 #endif
-    
     write_callback(id);
-    res = try_write();
+    res = queue_write();
   }
+  if (!strlen(write_buffer) && !query_write_callback())
+    socket::set_write_callback(0);
   if (res)
     die(res);
 }
@@ -171,7 +199,9 @@ private void ssl_close_callback(mixed id)
 #ifdef SSL3_DEBUG
   werror("SSL.sslport: ssl_close_callback\n");
 #endif
-  die(-1);
+  if (close_callback)
+    close_callback(socket::query_id());
+  die(closing ? 1 : -1);
 }
 
 void set_accept_callback(function(mixed:void) a)
@@ -179,21 +209,34 @@ void set_accept_callback(function(mixed:void) a)
   accept_callback = a;
 }
 
+function query_accept_callback() { return accept_callback; }
+
 void set_read_callback(function(mixed,string:void) r)
 {
   read_callback = r;
 }
 
+function query_read_callback() { return read_callback; }
+
 void set_write_callback(function(mixed:void) w)
 {
+#ifdef SSL3_DEBUG
+  werror("SSL.sslfile->set_write_callback\n");
+#endif
   write_callback = w;
+  if (w)
+    socket::set_write_callback(ssl_write_callback);
 }
 
+function query_write_callback() { return write_callback; }
+
 void set_close_callback(function(mixed:void) c)
 {
   close_callback = c;
 }
-  
+
+function query_close_callback() { return close_callback; }
+
 void set_nonblocking(function ...args)
 {
 #ifdef SSL3_DEBUG
@@ -215,7 +258,6 @@ void set_nonblocking(function ...args)
   blocking = 0;
   if (strlen(read_buffer))
     ssl_read_callback(socket::query_id(), "");
-  ssl_write_callback(socket::query_id());
 }
 
 void set_blocking()
@@ -247,7 +289,7 @@ void create(object f, object c)
   context = c;
   read_buffer = write_buffer = "";
   socket::assign(f);
-  socket::set_nonblocking(ssl_read_callback, ssl_write_callback, ssl_close_callback);
+  socket::set_nonblocking(ssl_read_callback, 0, ssl_close_callback);
   connection::create(1);
 }