Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2007 Michael Brown <mbrown (at) fensystems.co.uk>.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of the
      7  * License, or any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <string.h>
     22 #include <stdio.h>
     23 #include <errno.h>
     24 #include <gpxe/xfer.h>
     25 
     26 /** @file
     27  *
     28  * Data transfer interfaces
     29  *
     30  */
     31 
     32 /**
     33  * Dummy transfer metadata
     34  *
     35  * This gets passed to xfer_interface::deliver_iob() and equivalents
     36  * when no metadata is available.
     37  */
     38 static struct xfer_metadata dummy_metadata;
     39 
     40 /**
     41  * Close data transfer interface
     42  *
     43  * @v xfer		Data transfer interface
     44  * @v rc		Reason for close
     45  */
     46 void xfer_close ( struct xfer_interface *xfer, int rc ) {
     47 	struct xfer_interface *dest = xfer_get_dest ( xfer );
     48 	struct xfer_interface_operations *op = xfer->op;
     49 
     50 	DBGC ( xfer, "XFER %p->%p close\n", xfer, dest );
     51 
     52 	xfer_unplug ( xfer );
     53 	xfer_nullify ( xfer );
     54 	dest->op->close ( dest, rc );
     55 	xfer->op = op;
     56 	xfer_put ( dest );
     57 }
     58 
     59 /**
     60  * Send redirection event
     61  *
     62  * @v xfer		Data transfer interface
     63  * @v type		New location type
     64  * @v args		Remaining arguments depend upon location type
     65  * @ret rc		Return status code
     66  */
     67 int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) {
     68 	struct xfer_interface *dest = xfer_get_dest ( xfer );
     69 	int rc;
     70 
     71 	DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest );
     72 
     73 	rc = dest->op->vredirect ( dest, type, args );
     74 
     75 	if ( rc != 0 ) {
     76 		DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest,
     77 		       strerror ( rc ) );
     78 	}
     79 	xfer_put ( dest );
     80 	return rc;
     81 }
     82 
     83 /**
     84  * Send redirection event
     85  *
     86  * @v xfer		Data transfer interface
     87  * @v type		New location type
     88  * @v ...		Remaining arguments depend upon location type
     89  * @ret rc		Return status code
     90  */
     91 int xfer_redirect ( struct xfer_interface *xfer, int type, ... ) {
     92 	va_list args;
     93 	int rc;
     94 
     95 	va_start ( args, type );
     96 	rc = xfer_vredirect ( xfer, type, args );
     97 	va_end ( args );
     98 	return rc;
     99 }
    100 
    101 /**
    102  * Check flow control window
    103  *
    104  * @v xfer		Data transfer interface
    105  * @ret len		Length of window
    106  */
    107 size_t xfer_window ( struct xfer_interface *xfer ) {
    108 	struct xfer_interface *dest = xfer_get_dest ( xfer );
    109 	size_t len;
    110 
    111 	len = dest->op->window ( dest );
    112 
    113 	xfer_put ( dest );
    114 	return len;
    115 }
    116 
    117 /**
    118  * Allocate I/O buffer
    119  *
    120  * @v xfer		Data transfer interface
    121  * @v len		I/O buffer payload length
    122  * @ret iobuf		I/O buffer
    123  */
    124 struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) {
    125 	struct xfer_interface *dest = xfer_get_dest ( xfer );
    126 	struct io_buffer *iobuf;
    127 
    128 	DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len );
    129 
    130 	iobuf = dest->op->alloc_iob ( dest, len );
    131 
    132 	if ( ! iobuf ) {
    133 		DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest );
    134 	}
    135 	xfer_put ( dest );
    136 	return iobuf;
    137 }
    138 
    139 /**
    140  * Deliver datagram as I/O buffer with metadata
    141  *
    142  * @v xfer		Data transfer interface
    143  * @v iobuf		Datagram I/O buffer
    144  * @v meta		Data transfer metadata
    145  * @ret rc		Return status code
    146  */
    147 int xfer_deliver_iob_meta ( struct xfer_interface *xfer,
    148 			    struct io_buffer *iobuf,
    149 			    struct xfer_metadata *meta ) {
    150 	struct xfer_interface *dest = xfer_get_dest ( xfer );
    151 	int rc;
    152 
    153 	DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest,
    154 	       iob_len ( iobuf ) );
    155 
    156 	rc = dest->op->deliver_iob ( dest, iobuf, meta );
    157 
    158 	if ( rc != 0 ) {
    159 		DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest,
    160 		       strerror ( rc ) );
    161 	}
    162 	xfer_put ( dest );
    163 	return rc;
    164 }
    165 
    166 /**
    167  * Deliver datagram as I/O buffer with metadata
    168  *
    169  * @v xfer		Data transfer interface
    170  * @v iobuf		Datagram I/O buffer
    171  * @ret rc		Return status code
    172  */
    173 int xfer_deliver_iob ( struct xfer_interface *xfer,
    174 		       struct io_buffer *iobuf ) {
    175 	return xfer_deliver_iob_meta ( xfer, iobuf, &dummy_metadata );
    176 }
    177 
    178 /**
    179  * Deliver datagram as raw data
    180  *
    181  * @v xfer		Data transfer interface
    182  * @v iobuf		Datagram I/O buffer
    183  * @ret rc		Return status code
    184  */
    185 int xfer_deliver_raw ( struct xfer_interface *xfer,
    186 		       const void *data, size_t len ) {
    187 	struct xfer_interface *dest = xfer_get_dest ( xfer );
    188 	int rc;
    189 
    190 	DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest,
    191 	       data, len );
    192 
    193 	rc = dest->op->deliver_raw ( dest, data, len );
    194 
    195 	if ( rc != 0 ) {
    196 		DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest,
    197 		       strerror ( rc ) );
    198 	}
    199 	xfer_put ( dest );
    200 	return rc;
    201 }
    202 
    203 /**
    204  * Deliver formatted string
    205  *
    206  * @v xfer		Data transfer interface
    207  * @v format		Format string
    208  * @v args		Arguments corresponding to the format string
    209  * @ret rc		Return status code
    210  */
    211 int xfer_vprintf ( struct xfer_interface *xfer, const char *format,
    212 		   va_list args ) {
    213 	size_t len;
    214 	va_list args_tmp;
    215 
    216 	va_copy ( args_tmp, args );
    217 	len = vsnprintf ( NULL, 0, format, args );
    218 	{
    219 		char buf[len + 1];
    220 		vsnprintf ( buf, sizeof ( buf ), format, args_tmp );
    221 		va_end ( args_tmp );
    222 		return xfer_deliver_raw ( xfer, buf, len );
    223 	}
    224 }
    225 
    226 /**
    227  * Deliver formatted string
    228  *
    229  * @v xfer		Data transfer interface
    230  * @v format		Format string
    231  * @v ...		Arguments corresponding to the format string
    232  * @ret rc		Return status code
    233  */
    234 int xfer_printf ( struct xfer_interface *xfer, const char *format, ... ) {
    235 	va_list args;
    236 	int rc;
    237 
    238 	va_start ( args, format );
    239 	rc = xfer_vprintf ( xfer, format, args );
    240 	va_end ( args );
    241 	return rc;
    242 }
    243 
    244 /**
    245  * Seek to position
    246  *
    247  * @v xfer		Data transfer interface
    248  * @v offset		Offset to new position
    249  * @v whence		Basis for new position
    250  * @ret rc		Return status code
    251  */
    252 int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) {
    253 	struct io_buffer *iobuf;
    254 	struct xfer_metadata meta = {
    255 		.offset = offset,
    256 		.whence = whence,
    257 	};
    258 
    259 	DBGC ( xfer, "XFER %p seek %s+%ld\n", xfer,
    260 	       whence_text ( whence ), offset );
    261 
    262 	/* Allocate and send a zero-length data buffer */
    263 	iobuf = xfer_alloc_iob ( xfer, 0 );
    264 	if ( ! iobuf )
    265 		return -ENOMEM;
    266 	return xfer_deliver_iob_meta ( xfer, iobuf, &meta );
    267 }
    268 
    269 /****************************************************************************
    270  *
    271  * Helper methods
    272  *
    273  * These functions are designed to be used as methods in the
    274  * xfer_interface_operations table.
    275  *
    276  */
    277 
    278 /**
    279  * Ignore close() event
    280  *
    281  * @v xfer		Data transfer interface
    282  * @v rc		Reason for close
    283  */
    284 void ignore_xfer_close ( struct xfer_interface *xfer __unused,
    285 			 int rc __unused ) {
    286 	/* Nothing to do */
    287 }
    288 
    289 /**
    290  * Ignore vredirect() event
    291  *
    292  * @v xfer		Data transfer interface
    293  * @v type		New location type
    294  * @v args		Remaining arguments depend upon location type
    295  * @ret rc		Return status code
    296  */
    297 int ignore_xfer_vredirect ( struct xfer_interface *xfer __unused,
    298 			    int type __unused, va_list args __unused ) {
    299 	return 0;
    300 }
    301 
    302 /**
    303  * Unlimited flow control window
    304  *
    305  * @v xfer		Data transfer interface
    306  * @ret len		Length of window
    307  *
    308  * This handler indicates that the interface is always ready to accept
    309  * data.
    310  */
    311 size_t unlimited_xfer_window ( struct xfer_interface *xfer __unused ) {
    312 	return ~( ( size_t ) 0 );
    313 }
    314 
    315 /**
    316  * No flow control window
    317  *
    318  * @v xfer		Data transfer interface
    319  * @ret len		Length of window
    320  *
    321  * This handler indicates that the interface is never ready to accept
    322  * data.
    323  */
    324 size_t no_xfer_window ( struct xfer_interface *xfer __unused ) {
    325 	return 0;
    326 }
    327 
    328 /**
    329  * Allocate I/O buffer
    330  *
    331  * @v xfer		Data transfer interface
    332  * @v len		I/O buffer payload length
    333  * @ret iobuf		I/O buffer
    334  */
    335 struct io_buffer *
    336 default_xfer_alloc_iob ( struct xfer_interface *xfer __unused, size_t len ) {
    337 	return alloc_iob ( len );
    338 }
    339 
    340 /**
    341  * Deliver datagram as raw data
    342  *
    343  * @v xfer		Data transfer interface
    344  * @v iobuf		Datagram I/O buffer
    345  * @v meta		Data transfer metadata
    346  * @ret rc		Return status code
    347  *
    348  * This function is intended to be used as the deliver() method for
    349  * data transfer interfaces that prefer to handle raw data.
    350  */
    351 int xfer_deliver_as_raw ( struct xfer_interface *xfer,
    352 			  struct io_buffer *iobuf,
    353 			  struct xfer_metadata *meta __unused ) {
    354 	int rc;
    355 
    356 	rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) );
    357 	free_iob ( iobuf );
    358 	return rc;
    359 }
    360 
    361 /**
    362  * Deliver datagram as I/O buffer
    363  *
    364  * @v xfer		Data transfer interface
    365  * @v data		Data buffer
    366  * @v len		Length of data buffer
    367  * @ret rc		Return status code
    368  *
    369  * This function is intended to be used as the deliver_raw() method
    370  * for data transfer interfaces that prefer to handle I/O buffers.
    371  */
    372 int xfer_deliver_as_iob ( struct xfer_interface *xfer,
    373 			  const void *data, size_t len ) {
    374 	struct io_buffer *iobuf;
    375 
    376 	iobuf = xfer->op->alloc_iob ( xfer, len );
    377 	if ( ! iobuf )
    378 		return -ENOMEM;
    379 
    380 	memcpy ( iob_put ( iobuf, len ), data, len );
    381 	return xfer->op->deliver_iob ( xfer, iobuf, &dummy_metadata );
    382 }
    383 
    384 /**
    385  * Ignore datagram as raw data event
    386  *
    387  * @v xfer		Data transfer interface
    388  * @v data		Data buffer
    389  * @v len		Length of data buffer
    390  * @ret rc		Return status code
    391  */
    392 int ignore_xfer_deliver_raw ( struct xfer_interface *xfer,
    393 			      const void *data __unused, size_t len ) {
    394 	DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len,
    395 	       ( ( xfer == &null_xfer ) ?
    396 		 "before connection" : "after termination" ) );
    397 	return 0;
    398 }
    399 
    400 /** Null data transfer interface operations */
    401 struct xfer_interface_operations null_xfer_ops = {
    402 	.close		= ignore_xfer_close,
    403 	.vredirect	= ignore_xfer_vredirect,
    404 	.window		= unlimited_xfer_window,
    405 	.alloc_iob	= default_xfer_alloc_iob,
    406 	.deliver_iob	= xfer_deliver_as_raw,
    407 	.deliver_raw	= ignore_xfer_deliver_raw,
    408 };
    409 
    410 /**
    411  * Null data transfer interface
    412  *
    413  * This is the interface to which data transfer interfaces are
    414  * connected when unplugged.  It will never generate messages, and
    415  * will silently absorb all received messages.
    416  */
    417 struct xfer_interface null_xfer = XFER_INIT ( &null_xfer_ops );
    418