Data-transfer interface should now be functionally complete.
authorMichael Brown <mcb30@etherboot.org>
Tue, 15 May 2007 15:23:09 +0000 (15:23 +0000)
committerMichael Brown <mcb30@etherboot.org>
Tue, 15 May 2007 15:23:09 +0000 (15:23 +0000)
src/core/downloader.c
src/core/hw.c [new file with mode: 0644]
src/core/xfer.c
src/include/gpxe/xfer.h

index f539bb6..2e466cb 100644 (file)
@@ -115,7 +115,7 @@ static void downloader_job_start ( struct job_interface *job ) {
                container_of ( job, struct downloader, job );
 
        /* Start data transfer */
-       xfer_start ( &downloader->xfer );
+       xfer_request_all ( &downloader->xfer );
 }
 
 /**
@@ -152,17 +152,30 @@ static struct job_interface_operations downloader_job_operations = {
  * @v pos              New position
  * @ret rc             Return status code
  */
-static int downloader_xfer_seek ( struct xfer_interface *xfer, size_t pos ) {
+static int downloader_xfer_seek ( struct xfer_interface *xfer, off_t offset,
+                                 int whence ) {
        struct downloader *downloader =
                container_of ( xfer, struct downloader, xfer );
+       off_t new_pos;
        int rc;
 
+       /* Calculate new buffer position */
+       switch ( whence ) {
+       case SEEK_SET:
+               new_pos = offset;
+               break;
+       case SEEK_CUR:
+               new_pos = ( downloader->pos + offset );
+               break;
+       default:
+               assert ( 0 );
+               return -EINVAL;
+       }
+
        /* Ensure that we have enough buffer space for this buffer position */
-       if ( ( rc = downloader_ensure_size ( downloader, pos ) ) != 0 )
+       if ( ( rc = downloader_ensure_size ( downloader, new_pos ) ) != 0 )
                return rc;
-
-       /* Update current buffer position */
-       downloader->pos = pos;
+       downloader->pos = new_pos;
 
        return 0;
 }
@@ -216,11 +229,11 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) {
 
 /** Downloader data transfer interface operations */
 static struct xfer_interface_operations downloader_xfer_operations = {
-       .start          = ignore_xfer_start,
        .close          = downloader_xfer_close,
-       .vredirect      = default_xfer_vredirect,
+       .vredirect      = vopen,
+       .request        = ignore_xfer_request,
        .seek           = downloader_xfer_seek,
-       .deliver        = xfer_deliver_as_raw,
+       .deliver_iob    = xfer_deliver_as_raw,
        .deliver_raw    = downloader_xfer_deliver_raw,
 };
 
diff --git a/src/core/hw.c b/src/core/hw.c
new file mode 100644 (file)
index 0000000..80cac99
--- /dev/null
@@ -0,0 +1,68 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
+
+/** @file
+ *
+ * "Hello World" data source
+ *
+ */
+
+struct hw {
+       struct refcnt refcnt;
+       struct xfer_interface xfer;
+};
+
+static const char hw_msg[] = "Hello world!\n";
+
+static void hw_finished ( struct hw *hw, int rc ) {
+       xfer_nullify ( &hw->xfer );
+       xfer_close ( &hw->xfer, rc );
+       ref_put ( &hw->refcnt );
+}
+
+static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) {
+       struct hw *hw = container_of ( xfer, struct hw, xfer );
+
+       hw_finished ( hw, rc );
+}
+
+static int hw_xfer_request ( struct xfer_interface *xfer, off_t start __unused,
+                            int whence __unused, size_t len __unused ) {
+       struct hw *hw = container_of ( xfer, struct hw, xfer );
+
+       xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) );
+       hw_finished ( hw, 0 );
+       return 0;
+}
+
+static struct xfer_interface_operations hw_xfer_operations = {
+       .close          = hw_xfer_close,
+       .vredirect      = ignore_xfer_vredirect,
+       .request        = hw_xfer_request,
+       .seek           = ignore_xfer_seek,
+       .deliver_iob    = xfer_deliver_as_raw,
+       .deliver_raw    = ignore_xfer_deliver_raw,
+};
+
+static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) {
+       struct hw *hw;
+
+       hw = malloc ( sizeof ( *hw ) );
+       if ( ! hw )
+               return -ENOMEM;
+       memset ( hw, 0, sizeof ( *hw ) );
+       xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt );
+
+       xfer_plug_plug ( &hw->xfer, xfer );
+       return 0;
+}
+
+struct uri_opener hw_uri_opener __uri_opener = {
+       .scheme = "hw",
+       .open = hw_open,
+};
index 8a5d03d..bfbf1ce 100644 (file)
@@ -39,19 +39,6 @@ void xfer_close ( struct xfer_interface *xfer, int rc ) {
        xfer_unplug ( xfer );
 }
 
-/**
- * Seek to position
- *
- * @v xfer             Data transfer interface
- * @v pos              New position
- * @ret rc             Return status code
- */
-int xfer_seek ( struct xfer_interface *xfer, size_t pos ) {
-       struct xfer_interface *dest = xfer_dest ( xfer );
-
-       return dest->op->seek ( dest, pos );
-}
-
 /**
  * Send redirection event
  *
@@ -84,6 +71,59 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
        return rc;
 }
 
+/**
+ * Request data
+ *
+ * @v xfer             Data transfer interface
+ * @v offset           Offset to new position
+ * @v whence           Basis for new position
+ * @v len              Length of requested data
+ * @ret rc             Return status code
+ */
+int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence,
+                  size_t len ) {
+       struct xfer_interface *dest = xfer_dest ( xfer );
+
+       return dest->op->request ( dest, offset, whence, len );
+}
+
+/**
+ * Request all data
+ *
+ * @v xfer             Data transfer interface
+ * @ret rc             Return status code
+ */
+int xfer_request_all ( struct xfer_interface *xfer ) {
+       return xfer_request ( xfer, 0, SEEK_SET, ~( ( size_t ) 0 ) );
+}
+
+/**
+ * Seek to position
+ *
+ * @v xfer             Data transfer interface
+ * @v offset           Offset to new position
+ * @v whence           Basis for new position
+ * @ret rc             Return status code
+ */
+int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
+       struct xfer_interface *dest = xfer_dest ( xfer );
+
+       return dest->op->seek ( dest, offset, whence );
+}
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v xfer             Data transfer interface
+ * @v len              I/O buffer payload length
+ * @ret iobuf          I/O buffer
+ */
+struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
+       struct xfer_interface *dest = xfer_dest ( xfer );
+
+       return dest->op->alloc_iob ( dest, len );
+}
+
 /**
  * Deliver datagram
  *
@@ -91,10 +131,10 @@ int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
  * @v iobuf            Datagram I/O buffer
  * @ret rc             Return status code
  */
-int xfer_deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
+int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) {
        struct xfer_interface *dest = xfer_dest ( xfer );
 
-       return dest->op->deliver ( dest, iobuf );
+       return dest->op->deliver_iob ( dest, iobuf );
 }
 
 /**
@@ -120,15 +160,6 @@ int xfer_deliver_raw ( struct xfer_interface *xfer,
  *
  */
 
-/**
- * Ignore start() event
- *
- * @v xfer             Data transfer interface
- */
-void ignore_xfer_start ( struct xfer_interface *xfer __unused ) {
-       /* Nothing to do */
-}
-
 /**
  * Ignore close() event
  *
@@ -153,18 +184,46 @@ int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
        return 0;
 }
 
+/**
+ * Ignore request() event
+ *
+ * @v xfer             Data transfer interface
+ * @v offset           Offset to new position
+ * @v whence           Basis for new position
+ * @v len              Length of requested data
+ * @ret rc             Return status code
+ */
+int ignore_xfer_request ( struct xfer_interface *xfer __unused,
+                         off_t offset __unused, int whence __unused, 
+                         size_t len __unused ) {
+       return 0;
+}
+
 /**
  * Ignore seek() event
  *
  * @v xfer             Data transfer interface
- * @v pos              New position
+ * @v offset           Offset to new position
+ * @v whence           Basis for new position
  * @ret rc             Return status code
  */
 int ignore_xfer_seek ( struct xfer_interface *xfer __unused,
-                      size_t pos __unused ) {
+                      off_t offset __unused, int whence __unused ) {
        return 0;
 }
 
+/**
+ * Allocate I/O buffer
+ *
+ * @v xfer             Data transfer interface
+ * @v len              I/O buffer payload length
+ * @ret iobuf          I/O buffer
+ */
+struct io_buffer *
+default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
+       return alloc_iob ( len );
+}
+
 /**
  * Deliver datagram as raw data
  *
@@ -195,16 +254,16 @@ int xfer_deliver_as_raw ( struct xfer_interface *xfer,
  * This function is intended to be used as the deliver_raw() method
  * for data transfer interfaces that prefer to handle I/O buffers.
  */
-int xfer_deliver_as_iobuf ( struct xfer_interface *xfer,
-                           const void *data, size_t len ) {
+int xfer_deliver_as_iob ( struct xfer_interface *xfer,
+                         const void *data, size_t len ) {
        struct io_buffer *iobuf;
 
-       iobuf = alloc_iob ( len );
+       iobuf = xfer->op->alloc_iob ( xfer, len );
        if ( ! iobuf )
                return -ENOMEM;
 
        memcpy ( iob_put ( iobuf, len ), data, len );
-       return xfer->op->deliver ( xfer, iobuf );
+       return xfer->op->deliver_iob ( xfer, iobuf );
 }
 
 /**
@@ -225,11 +284,12 @@ int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
 
 /** Null data transfer interface operations */
 struct xfer_interface_operations null_xfer_ops = {
-       .start          = ignore_xfer_start,
        .close          = ignore_xfer_close,
        .vredirect      = ignore_xfer_vredirect,
+       .request        = ignore_xfer_request,
        .seek           = ignore_xfer_seek,
-       .deliver        = xfer_deliver_as_raw,
+       .alloc_iob      = default_xfer_alloc_iob,
+       .deliver_iob    = xfer_deliver_as_raw,
        .deliver_raw    = ignore_xfer_deliver_raw,
 };
 
index 61f5d86..4fb3a51 100644 (file)
@@ -16,22 +16,6 @@ struct xfer_interface;
 
 /** Data transfer interface operations */
 struct xfer_interface_operations {
-
-       /* Missing features:
-        *
-        * notification of non-close status - e.g. connected/opened, ...
-        *
-        * prompt for data delivery
-        *
-        * I/O buffer preparation
-        *
-        */
-
-       /** Start data transfer
-        *
-        * @v xfer              Data transfer interface
-        */
-       void ( * start ) ( struct xfer_interface *xfer );
        /** Close interface
         *
         * @v xfer              Data transfer interface
@@ -47,14 +31,39 @@ struct xfer_interface_operations {
         */
        int ( * vredirect ) ( struct xfer_interface *xfer, int type,
                              va_list args );
+       /** Request data
+        *
+        * @v xfer              Data transfer interface
+        * @v offset            Offset to new position
+        * @v whence            Basis for new position
+        * @v len               Length of requested data
+        * @ret rc              Return status code
+        */
+       int ( * request ) ( struct xfer_interface *xfer, off_t offset,
+                           int whence, size_t len );
        /** Seek to position
         *
         * @v xfer              Data transfer interface
-        * @v pos               New position
+        * @v offset            Offset to new position
+        * @v whence            Basis for new position
         * @ret rc              Return status code
+        *
+        * @c whence must be one of @c SEEK_SET or @c SEEK_CUR.  A
+        * successful return indicates that the interface is ready to
+        * immediately accept datagrams; return -EAGAIN if this is not
+        * the case.
         */
-       int ( * seek ) ( struct xfer_interface *xfer, size_t pos );
-       /** Deliver datagram
+       int ( * seek ) ( struct xfer_interface *xfer, off_t offset,
+                        int whence );
+       /** Allocate I/O buffer
+        *
+        * @v xfer              Data transfer interface
+        * @v len               I/O buffer payload length
+        * @ret iobuf           I/O buffer
+        */
+       struct io_buffer * ( * alloc_iob ) ( struct xfer_interface *xfer,
+                                            size_t len );
+       /** Deliver datagram as I/O buffer
         *
         * @v xfer              Data transfer interface
         * @v iobuf             Datagram I/O buffer
@@ -63,9 +72,13 @@ struct xfer_interface_operations {
         * A data transfer interface that wishes to support only raw
         * data delivery should set this method to
         * xfer_deliver_as_raw().
+        *
+        * Interfaces may not temporarily refuse to accept data by
+        * returning -EAGAIN; such a response may be treated as a
+        * fatal error.
         */
-       int ( * deliver ) ( struct xfer_interface *xfer,
-                           struct io_buffer *iobuf );
+       int ( * deliver_iob ) ( struct xfer_interface *xfer,
+                               struct io_buffer *iobuf );
        /** Deliver datagram as raw data
         *
         * @v xfer              Data transfer interface
@@ -75,7 +88,11 @@ struct xfer_interface_operations {
         *
         * A data transfer interface that wishes to support only I/O
         * buffer delivery should set this method to
-        * xfer_deliver_as_iobuf().
+        * xfer_deliver_as_iob().
+        *
+        * Interfaces may not temporarily refuse to accept data by
+        * returning -EAGAIN; such a response may be treated as a
+        * fatal error.
         */
        int ( * deliver_raw ) ( struct xfer_interface *xfer,
                                const void *data, size_t len );
@@ -89,31 +106,43 @@ struct xfer_interface {
        struct xfer_interface_operations *op;
 };
 
+/** Basis positions for seek() events */
+enum seek_whence {
+       SEEK_SET = 0,
+       SEEK_CUR,
+};
+
 extern struct xfer_interface null_xfer;
 extern struct xfer_interface_operations null_xfer_ops;
 
-extern void xfer_start ( struct xfer_interface *xfer );
 extern void xfer_close ( struct xfer_interface *xfer, int rc );
-extern int xfer_seek ( struct xfer_interface *xfer, size_t pos );
 extern int xfer_vredirect ( struct xfer_interface *xfer, int type,
                            va_list args );
 extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... );
-extern int xfer_deliver ( struct xfer_interface *xfer,
-                         struct io_buffer *iobuf );
+extern int xfer_request ( struct xfer_interface *xfer, off_t offset,
+                         int whence, size_t len );
+extern int xfer_request_all ( struct xfer_interface *xfer );
+extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence );
+extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer,
+                                          size_t len );
+extern int xfer_deliver_iob ( struct xfer_interface *xfer,
+                             struct io_buffer *iobuf );
 extern int xfer_deliver_raw ( struct xfer_interface *xfer,
                              const void *data, size_t len );
 
-extern void ignore_xfer_start ( struct xfer_interface *xfer );
 extern void ignore_xfer_close ( struct xfer_interface *xfer, int rc );
 extern int ignore_xfer_vredirect ( struct xfer_interface *xfer,
                                   int type, va_list args );
-extern int default_xfer_vredirect ( struct xfer_interface *xfer,
-                                   int type, va_list args );
-extern int ignore_xfer_seek ( struct xfer_interface *xfer, size_t pos );
+extern int ignore_xfer_request ( struct xfer_interface *xfer, off_t offset,
+                                int whence, size_t len );
+extern int ignore_xfer_seek ( struct xfer_interface *xfer, off_t offset,
+                             int whence );
+extern struct io_buffer * default_xfer_alloc_iob ( struct xfer_interface *xfer,
+                                                  size_t len );
 extern int xfer_deliver_as_raw ( struct xfer_interface *xfer,
                                 struct io_buffer *iobuf );
-extern int xfer_deliver_as_iobuf ( struct xfer_interface *xfer,
-                                  const void *data, size_t len );
+extern int xfer_deliver_as_iob ( struct xfer_interface *xfer,
+                                const void *data, size_t len );
 extern int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
                                     const void *data __unused, size_t len );