[Spice-devel] [PATCH 07/17] Move async code to RedsStream

Christophe Fergeau cfergeau at redhat.com
Tue Jan 7 03:14:33 PST 2014


The AsyncRead structure in reds.h wraps an async read + callback to
be done on a stream. Moving it to reds_stream.h is needed in order
to move SASL authentication there.
---
 server/reds.c        | 60 ------------------------------------------------
 server/reds_stream.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 server/reds_stream.h | 18 +++++++++++++++
 3 files changed, 82 insertions(+), 60 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index e8654b0..c12ec3c 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -121,15 +121,6 @@ static bool exit_on_disconnect = FALSE;
 
 static RedsState *reds = NULL;
 
-typedef struct AsyncRead {
-    RedsStream *stream;
-    void *opaque;
-    uint8_t *now;
-    uint8_t *end;
-    void (*done)(void *opaque);
-    void (*error)(void *opaque, int err);
-} AsyncRead;
-
 typedef struct RedLinkInfo {
     RedsStream *stream;
     AsyncRead async_read;
@@ -1879,57 +1870,6 @@ end:
     g_free(password);
 }
 
-static inline void async_read_clear_handlers(AsyncRead *obj)
-{
-    if (!obj->stream->watch) {
-        return;
-    }
-
-    reds_stream_remove_watch(obj->stream);
-}
-
-static void async_read_handler(int fd, int event, void *data)
-{
-    AsyncRead *obj = (AsyncRead *)data;
-
-    for (;;) {
-        int n = obj->end - obj->now;
-
-        spice_assert(n > 0);
-        n = reds_stream_read(obj->stream, obj->now, n);
-        if (n <= 0) {
-            if (n < 0) {
-                switch (errno) {
-                case EAGAIN:
-                    if (!obj->stream->watch) {
-                        obj->stream->watch = core->watch_add(obj->stream->socket,
-                                                           SPICE_WATCH_EVENT_READ,
-                                                           async_read_handler, obj);
-                    }
-                    return;
-                case EINTR:
-                    break;
-                default:
-                    async_read_clear_handlers(obj);
-                    obj->error(obj->opaque, errno);
-                    return;
-                }
-            } else {
-                async_read_clear_handlers(obj);
-                obj->error(obj->opaque, 0);
-                return;
-            }
-        } else {
-            obj->now += n;
-            if (obj->now == obj->end) {
-                async_read_clear_handlers(obj);
-                obj->done(obj->opaque);
-                return;
-            }
-        }
-    }
-}
-
 static void reds_get_spice_ticket(RedLinkInfo *link)
 {
     AsyncRead *obj = &link->async_read;
diff --git a/server/reds_stream.c b/server/reds_stream.c
index b3614e6..f4513e6 100644
--- a/server/reds_stream.c
+++ b/server/reds_stream.c
@@ -246,6 +246,8 @@ RedsStream *reds_stream_new(int socket)
     stream->write = stream_write_cb;
     stream->writev = stream_writev_cb;
 
+    stream->async_read.stream = stream;
+
     return stream;
 }
 
@@ -303,6 +305,68 @@ int reds_stream_enable_ssl(RedsStream *stream, SSL_CTX *ctx)
     return reds_stream_ssl_accept(stream);
 }
 
+void async_read_set_error_handler(AsyncRead *async,
+                                  AsyncReadError error_handler,
+                                 void *opaque)
+{
+    async->error = error_handler;
+}
+
+static inline void async_read_clear_handlers(AsyncRead *obj)
+{
+    if (!obj->stream->watch) {
+        return;
+    }
+
+    reds_stream_remove_watch(obj->stream);
+}
+
+void async_read_handler(int fd, int event, void *data)
+{
+    AsyncRead *obj = (AsyncRead *)data;
+
+    for (;;) {
+        int n = obj->end - obj->now;
+
+        spice_assert(n > 0);
+        n = reds_stream_read(obj->stream, obj->now, n);
+        if (n <= 0) {
+            if (n < 0) {
+                switch (errno) {
+                case EAGAIN:
+                    if (!obj->stream->watch) {
+                        obj->stream->watch = core->watch_add(obj->stream->socket,
+                                                           SPICE_WATCH_EVENT_READ,
+                                                           async_read_handler, obj);
+                    }
+                    return;
+                case EINTR:
+                    break;
+                default:
+                    async_read_clear_handlers(obj);
+		    if (obj->error) {
+                        obj->error(obj->opaque, errno);
+		    }
+                    return;
+                }
+            } else {
+                async_read_clear_handlers(obj);
+		if (obj->error) {
+		    obj->error(obj->opaque, 0);
+		}
+                return;
+            }
+        } else {
+            obj->now += n;
+            if (obj->now == obj->end) {
+                async_read_clear_handlers(obj);
+                obj->done(obj->opaque);
+                return;
+            }
+        }
+    }
+}
+
 #if HAVE_SASL
 bool reds_stream_write_u8(RedsStream *s, uint8_t n)
 {
diff --git a/server/reds_stream.h b/server/reds_stream.h
index ed1c61d..fa41cbb 100644
--- a/server/reds_stream.h
+++ b/server/reds_stream.h
@@ -28,6 +28,9 @@
 #if HAVE_SASL
 #include <sasl/sasl.h>
 
+typedef void (*AsyncReadDone)(void *opaque);
+typedef void (*AsyncReadError)(void *opaque, int err);
+
 typedef struct RedsSASL {
     sasl_conn_t *conn;
 
@@ -57,6 +60,19 @@ typedef struct RedsSASL {
 #endif
 
 typedef struct RedsStream RedsStream;
+typedef struct AsyncRead {
+    RedsStream *stream;
+    void *opaque;
+    uint8_t *now;
+    uint8_t *end;
+    AsyncReadDone done;
+    AsyncReadError error;
+} AsyncRead;
+
+void async_read_handler(int fd, int event, void *data);
+void async_read_set_error_handler(AsyncRead *async,
+                                  AsyncReadError error_handler,
+                                  void *opaque);
 
 struct RedsStream {
     int socket;
@@ -67,6 +83,8 @@ struct RedsStream {
     int shutdown;
     SSL *ssl;
 
+    AsyncRead async_read;
+
 #if HAVE_SASL
     RedsSASL sasl;
 #endif
-- 
1.8.4.2



More information about the Spice-devel mailing list