stream: allow async read/write callback to destroy the stream explicitly
authorMartin Willi <martin@revosec.ch>
Tue, 2 Jul 2013 12:09:45 +0000 (14:09 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 18 Jul 2013 14:00:29 +0000 (16:00 +0200)
src/libstrongswan/networking/streams/stream.c
src/libstrongswan/networking/streams/stream.h

index 20379fb..b3dd768 100644 (file)
@@ -175,21 +175,26 @@ static void remove_watcher(private_stream_t *this)
 static bool watch(private_stream_t *this, int fd, watcher_event_t event)
 {
        bool keep = FALSE;
+       stream_cb_t cb;
 
        switch (event)
        {
                case WATCHER_READ:
-                       keep = this->read_cb(this->read_data, &this->public);
-                       if (!keep)
+                       cb = this->read_cb;
+                       this->read_cb = NULL;
+                       keep = cb(this->read_data, &this->public);
+                       if (keep)
                        {
-                               this->read_cb = NULL;
+                               this->read_cb = cb;
                        }
                        break;
                case WATCHER_WRITE:
-                       keep = this->write_cb(this->write_data, &this->public);
-                       if (!keep)
+                       cb = this->write_cb;
+                       this->write_cb = NULL;
+                       keep = cb(this->write_data, &this->public);
+                       if (keep)
                        {
-                               this->write_cb = NULL;
+                               this->write_cb = cb;
                        }
                        break;
                case WATCHER_EXCEPT:
index 8cd8419..810514d 100644 (file)
@@ -39,9 +39,9 @@ typedef stream_t*(*stream_constructor_t)(char *uri);
 /**
  * Callback function prototype, called when stream is ready.
  *
- * It is not allowed to destroy the stream during the callback, this would
- * deadlock. Instead, return FALSE to destroy the stream. It is not allowed
- * to call on_read()/on_write() during this callback.
+ * It is allowed to destroy the stream during the callback, but only if it has
+ * no other active on_read()/on_write() callback and returns FALSE. It is not
+ * allowed to to call on_read()/on_write/() during the callback.
  *
  * As select() may return even if a read()/write() would actually block, it is
  * recommended to use the non-blocking calls and handle return values
@@ -49,7 +49,7 @@ typedef stream_t*(*stream_constructor_t)(char *uri);
  *
  * @param data                 data passed during callback registration
  * @param stream               associated stream
- * @return                             FALSE to destroy the stream
+ * @return                             FALSE unregisters the invoked callback, TRUE keeps it
  */
 typedef bool (*stream_cb_t)(void *data, stream_t *stream);