xfer.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <errno.h>
00024 #include <gpxe/xfer.h>
00025 
00026 /** @file
00027  *
00028  * Data transfer interfaces
00029  *
00030  */
00031 
00032 /**
00033  * Dummy transfer metadata
00034  *
00035  * This gets passed to xfer_interface::deliver_iob() and equivalents
00036  * when no metadata is available.
00037  */
00038 static struct xfer_metadata dummy_metadata;
00039 
00040 /**
00041  * Close data transfer interface
00042  *
00043  * @v xfer              Data transfer interface
00044  * @v rc                Reason for close
00045  */
00046 void xfer_close ( struct xfer_interface *xfer, int rc ) {
00047         struct xfer_interface *dest = xfer_get_dest ( xfer );
00048         struct xfer_interface_operations *op = xfer->op;
00049 
00050         DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
00051 
00052         xfer_unplug ( xfer );
00053         xfer_nullify ( xfer );
00054         dest->op->close ( dest, rc );
00055         xfer->op = op;
00056         xfer_put ( dest );
00057 }
00058 
00059 /**
00060  * Send redirection event
00061  *
00062  * @v xfer              Data transfer interface
00063  * @v type              New location type
00064  * @v args              Remaining arguments depend upon location type
00065  * @ret rc              Return status code
00066  */
00067 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
00068         struct xfer_interface *dest = xfer_get_dest ( xfer );
00069         int rc;
00070 
00071         DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest );
00072 
00073         rc = dest->op->vredirect ( dest, type, args );
00074 
00075         if ( rc != 0 ) {
00076                 DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest,
00077                        strerror ( rc ) );
00078         }
00079         xfer_put ( dest );
00080         return rc;
00081 }
00082 
00083 /**
00084  * Send redirection event
00085  *
00086  * @v xfer              Data transfer interface
00087  * @v type              New location type
00088  * @v ...               Remaining arguments depend upon location type
00089  * @ret rc              Return status code
00090  */
00091 int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
00092         va_list args;
00093         int rc;
00094 
00095         va_start ( args, type );
00096         rc = xfer_vredirect ( xfer, type, args );
00097         va_end ( args );
00098         return rc;
00099 }
00100 
00101 /**
00102  * Check flow control window
00103  *
00104  * @v xfer              Data transfer interface
00105  * @ret len             Length of window
00106  */
00107 size_t xfer_window ( struct xfer_interface *xfer ) {
00108         struct xfer_interface *dest = xfer_get_dest ( xfer );
00109         size_t len;
00110 
00111         len = dest->op->window ( dest );
00112 
00113         xfer_put ( dest );
00114         return len;
00115 }
00116 
00117 /**
00118  * Allocate I/O buffer
00119  *
00120  * @v xfer              Data transfer interface
00121  * @v len               I/O buffer payload length
00122  * @ret iobuf           I/O buffer
00123  */
00124 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
00125         struct xfer_interface *dest = xfer_get_dest ( xfer );
00126         struct io_buffer *iobuf;
00127 
00128         DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
00129 
00130         iobuf = dest->op->alloc_iob ( dest, len );
00131 
00132         if ( ! iobuf ) {
00133                 DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
00134         }
00135         xfer_put ( dest );
00136         return iobuf;
00137 }
00138 
00139 /**
00140  * Deliver datagram as I/O buffer with metadata
00141  *
00142  * @v xfer              Data transfer interface
00143  * @v iobuf             Datagram I/O buffer
00144  * @v meta              Data transfer metadata
00145  * @ret rc              Return status code
00146  */
00147 int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
00148                             struct io_buffer *iobuf,
00149                             struct xfer_metadata *meta ) {
00150         struct xfer_interface *dest = xfer_get_dest ( xfer );
00151         int rc;
00152 
00153         DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
00154                iob_len ( iobuf ) );
00155 
00156         rc = dest->op->deliver_iob ( dest, iobuf, meta );
00157 
00158         if ( rc != 0 ) {
00159                 DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
00160                        strerror ( rc ) );
00161         }
00162         xfer_put ( dest );
00163         return rc;
00164 }
00165 
00166 /**
00167  * Deliver datagram as I/O buffer with metadata
00168  *
00169  * @v xfer              Data transfer interface
00170  * @v iobuf             Datagram I/O buffer
00171  * @ret rc              Return status code
00172  */
00173 int xfer_deliver_iob ( struct xfer_interface *xfer,
00174                        struct io_buffer *iobuf ) {
00175         return xfer_deliver_iob_meta ( xfer, iobuf, &dummy_metadata );
00176 }
00177 
00178 /**
00179  * Deliver datagram as raw data
00180  *
00181  * @v xfer              Data transfer interface
00182  * @v iobuf             Datagram I/O buffer
00183  * @ret rc              Return status code
00184  */
00185 int xfer_deliver_raw ( struct xfer_interface *xfer,
00186                        const void *data, size_t len ) {
00187         struct xfer_interface *dest = xfer_get_dest ( xfer );
00188         int rc;
00189 
00190         DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
00191                data, len );
00192 
00193         rc = dest->op->deliver_raw ( dest, data, len );
00194 
00195         if ( rc != 0 ) {
00196                 DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
00197                        strerror ( rc ) );
00198         }
00199         xfer_put ( dest );
00200         return rc;
00201 }
00202 
00203 /**
00204  * Deliver formatted string
00205  *
00206  * @v xfer              Data transfer interface
00207  * @v format            Format string
00208  * @v args              Arguments corresponding to the format string
00209  * @ret rc              Return status code
00210  */
00211 int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
00212                    va_list args ) {
00213         size_t len;
00214         va_list args_tmp;
00215 
00216         va_copy ( args_tmp, args );
00217         len = vsnprintf ( NULL, 0, format, args );
00218         {
00219                 char buf[len + 1];
00220                 vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
00221                 va_end ( args_tmp );
00222                 return xfer_deliver_raw ( xfer, buf, len );
00223         }
00224 }
00225 
00226 /**
00227  * Deliver formatted string
00228  *
00229  * @v xfer              Data transfer interface
00230  * @v format            Format string
00231  * @v ...               Arguments corresponding to the format string
00232  * @ret rc              Return status code
00233  */
00234 int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
00235         va_list args;
00236         int rc;
00237 
00238         va_start ( args, format );
00239         rc = xfer_vprintf ( xfer, format, args );
00240         va_end ( args );
00241         return rc;
00242 }
00243 
00244 /**
00245  * Seek to position
00246  *
00247  * @v xfer              Data transfer interface
00248  * @v offset            Offset to new position
00249  * @v whence            Basis for new position
00250  * @ret rc              Return status code
00251  */
00252 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
00253         struct io_buffer *iobuf;
00254         struct xfer_metadata meta = {
00255                 .offset = offset,
00256                 .whence = whence,
00257         };
00258 
00259         DBGC ( xfer, "XFER %p seek %s+%ld\n", xfer,
00260                whence_text ( whence ), offset );
00261 
00262         /* Allocate and send a zero-length data buffer */
00263         iobuf = xfer_alloc_iob ( xfer, 0 );
00264         if ( ! iobuf )
00265                 return -ENOMEM;
00266         return xfer_deliver_iob_meta ( xfer, iobuf, &meta );
00267 }
00268 
00269 /****************************************************************************
00270  *
00271  * Helper methods
00272  *
00273  * These functions are designed to be used as methods in the
00274  * xfer_interface_operations table.
00275  *
00276  */
00277 
00278 /**
00279  * Ignore close() event
00280  *
00281  * @v xfer              Data transfer interface
00282  * @v rc                Reason for close
00283  */
00284 void ignore_xfer_close ( struct xfer_interface *xfer __unused,
00285                          int rc __unused ) {
00286         /* Nothing to do */
00287 }
00288 
00289 /**
00290  * Ignore vredirect() event
00291  *
00292  * @v xfer              Data transfer interface
00293  * @v type              New location type
00294  * @v args              Remaining arguments depend upon location type
00295  * @ret rc              Return status code
00296  */
00297 int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
00298                             int type __unused, va_list args __unused ) {
00299         return 0;
00300 }
00301 
00302 /**
00303  * Unlimited flow control window
00304  *
00305  * @v xfer              Data transfer interface
00306  * @ret len             Length of window
00307  *
00308  * This handler indicates that the interface is always ready to accept
00309  * data.
00310  */
00311 size_t unlimited_xfer_window ( struct xfer_interface *xfer __unused ) {
00312         return ~( ( size_t ) 0 );
00313 }
00314 
00315 /**
00316  * No flow control window
00317  *
00318  * @v xfer              Data transfer interface
00319  * @ret len             Length of window
00320  *
00321  * This handler indicates that the interface is never ready to accept
00322  * data.
00323  */
00324 size_t no_xfer_window ( struct xfer_interface *xfer __unused ) {
00325         return 0;
00326 }
00327 
00328 /**
00329  * Allocate I/O buffer
00330  *
00331  * @v xfer              Data transfer interface
00332  * @v len               I/O buffer payload length
00333  * @ret iobuf           I/O buffer
00334  */
00335 struct io_buffer *
00336 default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
00337         return alloc_iob ( len );
00338 }
00339 
00340 /**
00341  * Deliver datagram as raw data
00342  *
00343  * @v xfer              Data transfer interface
00344  * @v iobuf             Datagram I/O buffer
00345  * @v meta              Data transfer metadata
00346  * @ret rc              Return status code
00347  *
00348  * This function is intended to be used as the deliver() method for
00349  * data transfer interfaces that prefer to handle raw data.
00350  */
00351 int xfer_deliver_as_raw ( struct xfer_interface *xfer,
00352                           struct io_buffer *iobuf,
00353                           struct xfer_metadata *meta __unused ) {
00354         int rc;
00355 
00356         rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) );
00357         free_iob ( iobuf );
00358         return rc;
00359 }
00360 
00361 /**
00362  * Deliver datagram as I/O buffer
00363  *
00364  * @v xfer              Data transfer interface
00365  * @v data              Data buffer
00366  * @v len               Length of data buffer
00367  * @ret rc              Return status code
00368  *
00369  * This function is intended to be used as the deliver_raw() method
00370  * for data transfer interfaces that prefer to handle I/O buffers.
00371  */
00372 int xfer_deliver_as_iob ( struct xfer_interface *xfer,
00373                           const void *data, size_t len ) {
00374         struct io_buffer *iobuf;
00375 
00376         iobuf = xfer->op->alloc_iob ( xfer, len );
00377         if ( ! iobuf )
00378                 return -ENOMEM;
00379 
00380         memcpy ( iob_put ( iobuf, len ), data, len );
00381         return xfer->op->deliver_iob ( xfer, iobuf, &dummy_metadata );
00382 }
00383 
00384 /**
00385  * Ignore datagram as raw data event
00386  *
00387  * @v xfer              Data transfer interface
00388  * @v data              Data buffer
00389  * @v len               Length of data buffer
00390  * @ret rc              Return status code
00391  */
00392 int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
00393                               const void *data __unused, size_t len ) {
00394         DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len,
00395                ( ( xfer == &null_xfer ) ?
00396                  "before connection" : "after termination" ) );
00397         return 0;
00398 }
00399 
00400 /** Null data transfer interface operations */
00401 struct xfer_interface_operations null_xfer_ops = {
00402         .close          = ignore_xfer_close,
00403         .vredirect      = ignore_xfer_vredirect,
00404         .window         = unlimited_xfer_window,
00405         .alloc_iob      = default_xfer_alloc_iob,
00406         .deliver_iob    = xfer_deliver_as_raw,
00407         .deliver_raw    = ignore_xfer_deliver_raw,
00408 };
00409 
00410 /**
00411  * Null data transfer interface
00412  *
00413  * This is the interface to which data transfer interfaces are
00414  * connected when unplugged.  It will never generate messages, and
00415  * will silently absorb all received messages.
00416  */
00417 struct xfer_interface null_xfer = XFER_INIT ( &null_xfer_ops );

Generated on Tue Apr 6 20:00:52 2010 for gPXE by  doxygen 1.5.7.1