Modify data-xfer semantics: it is no longer necessary to call one of
[people/pcmattman/gpxe.git] / src / core / downloader.c
index f539bb6..15ef962 100644 (file)
@@ -50,6 +50,19 @@ struct downloader {
        int ( * register_image ) ( struct image *image );
 };
 
+/**
+ * Free downloader object
+ *
+ * @v refcnt           Downloader reference counter
+ */
+static void downloader_free ( struct refcnt *refcnt ) {
+       struct downloader *downloader =
+               container_of ( refcnt, struct downloader, refcnt );
+
+       image_put ( downloader->image );
+       free ( downloader );
+}
+
 /**
  * Terminate download
  *
@@ -63,12 +76,8 @@ static void downloader_finished ( struct downloader *downloader, int rc ) {
        xfer_nullify ( &downloader->xfer );
 
        /* Free resources and close interfaces */
-       image_put ( downloader->image );
        xfer_close ( &downloader->xfer, rc );
        job_done ( &downloader->job, rc );
-
-       /* Drop reference to self */
-       ref_put ( &downloader->refcnt );
 }
 
 /**
@@ -105,19 +114,6 @@ static int downloader_ensure_size ( struct downloader *downloader,
  *
  */
 
-/**
- * Handle start() event received via job control interface
- *
- * @v job              Downloader job control interface
- */
-static void downloader_job_start ( struct job_interface *job ) {
-       struct downloader *downloader = 
-               container_of ( job, struct downloader, job );
-
-       /* Start data transfer */
-       xfer_start ( &downloader->xfer );
-}
-
 /**
  * Handle kill() event received via job control interface
  *
@@ -133,7 +129,7 @@ static void downloader_job_kill ( struct job_interface *job ) {
 
 /** Downloader job control interface operations */
 static struct job_interface_operations downloader_job_operations = {
-       .start          = downloader_job_start,
+       .start          = ignore_job_start,
        .done           = ignore_job_done,
        .kill           = downloader_job_kill,
        .progress       = ignore_job_progress,
@@ -152,17 +148,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 +225,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      = xfer_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,
 };
 
@@ -254,6 +263,7 @@ int create_downloader ( struct job_interface *job, const char *uri_string,
        if ( ! downloader )
                return -ENOMEM;
        memset ( downloader, 0, sizeof ( *downloader ) );
+       downloader->refcnt.free = downloader_free;
        job_init ( &downloader->job, &downloader_job_operations,
                   &downloader->refcnt );
        xfer_init ( &downloader->xfer, &downloader_xfer_operations,
@@ -262,15 +272,17 @@ int create_downloader ( struct job_interface *job, const char *uri_string,
        downloader->register_image = register_image;
 
        /* Instantiate child objects and attach to our interfaces */
-       if ( ( rc = open ( &downloader->xfer, LOCATION_URI,
-                          uri_string ) ) != 0 )
+       if ( ( rc = xfer_open ( &downloader->xfer, LOCATION_URI,
+                               uri_string ) ) != 0 )
                goto err;
 
-       /* Attach parent interface and return */
+       /* Attach parent interface, mortalise self, and return */
        job_plug_plug ( &downloader->job, job );
+       ref_put ( &downloader->refcnt );
        return 0;
 
  err:
        downloader_finished ( downloader, rc );
+       ref_put ( &downloader->refcnt );
        return rc;
 }