diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/open.c | 144 | ||||
| -rw-r--r-- | src/core/xfer.c | 76 |
2 files changed, 208 insertions, 12 deletions
diff --git a/src/core/open.c b/src/core/open.c new file mode 100644 index 000000000..ffcb4e292 --- /dev/null +++ b/src/core/open.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <gpxe/xfer.h> +#include <gpxe/uri.h> +#include <gpxe/socket.h> +#include <gpxe/open.h> + +/** @file + * + * Data transfer interface opening + * + */ + +/** Registered URI openers */ +static struct uri_opener uri_openers[0] + __table_start ( struct uri_opener, uri_openers ); +static struct uri_opener uri_openers_end[0] + __table_end ( struct uri_opener, uri_openers ); + +/** Registered socket openers */ +static struct socket_opener socket_openers[0] + __table_start ( struct socket_opener, socket_openers ); +static struct socket_opener socket_openers_end[0] + __table_end ( struct socket_opener, socket_openers ); + +/** + * Open URI + * + * @v xfer Data-transfer interface + * @v uri_string URI string (e.g. "http://etherboot.org/kernel") + * @ret rc Return status code + */ +int open_uri ( struct xfer_interface *xfer, const char *uri_string ) { + struct uri *uri; + struct uri_opener *opener; + + DBGC ( xfer, "XFER %p opening URI %s\n", xfer, uri_string ); + + uri = parse_uri ( uri_string ); + if ( ! uri ) + return -ENOMEM; + + for ( opener = uri_openers ; opener < uri_openers_end ; opener++ ) { + if ( strcmp ( uri->scheme, opener->scheme ) == 0 ) { + return opener->open ( xfer, uri ); + } + } + + DBGC ( xfer, "XFER %p attempted to open unsupported URI scheme " + "\"%s\"\n", xfer, uri->scheme ); + free_uri ( uri ); + return -ENOTSUP; +} + +/** + * Open socket + * + * @v xfer Data-transfer interface + * @v domain Communication domain (e.g. PF_INET) + * @v type Communication semantics (e.g. SOCK_STREAM) + */ +int open_socket ( struct xfer_interface *xfer, + int domain, int type, struct sockaddr *sa ) { + struct socket_opener *opener; + + DBGC ( xfer, "XFER %p opening (%s,%s) socket\n", xfer, + socket_domain_name ( domain ), socket_type_name ( type ) ); + + for ( opener = socket_openers; opener < socket_openers_end; opener++ ){ + if ( ( opener->domain == domain ) && + ( opener->type == type ) ) { + return opener->open ( xfer, sa ); + } + } + + DBGC ( xfer, "XFER %p attempted to open unsupported socket type " + "(%s,%s)\n", xfer, socket_domain_name ( domain ), + socket_type_name ( type ) ); + return -ENOTSUP; +} + +/** + * Open location + * + * @v xfer Data-transfer interface + * @v type Location type + * @v args Remaining arguments depend upon location type + * @ret rc Return status code + */ +int vopen ( struct xfer_interface *xfer, int type, va_list args ) { + switch ( type ) { + case LOCATION_URI: { + const char *uri_string = va_arg ( args, const char * ); + + return open_uri ( xfer, uri_string ); } + case LOCATION_SOCKET: { + int domain = va_arg ( args, int ); + int type = va_arg ( args, int ); + struct sockaddr *sa = va_arg ( args, struct sockaddr * ); + + return open_socket ( xfer, domain, type, sa ); } + default: + DBGC ( xfer, "XFER %p attempted to open unsupported location " + "type %d\n", xfer, type ); + return -ENOTSUP; + } +} + +/** + * Open location + * + * @v xfer Data-transfer interface + * @v type Location type + * @v ... Remaining arguments depend upon location type + * @ret rc Return status code + */ +int open ( struct xfer_interface *xfer, int type, ... ) { + va_list args; + int rc; + + va_start ( args, type ); + rc = vopen ( xfer, type, args ); + va_end ( args ); + return rc; +} diff --git a/src/core/xfer.c b/src/core/xfer.c index bf56d0600..c3993799c 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -27,6 +27,38 @@ */ /** + * Send redirection event + * + * @v xfer Data-transfer interface + * @v type New location type + * @v args Remaining arguments depend upon location type + * @ret rc Return status code + */ +int vredirect ( struct xfer_interface *xfer, int type, va_list args ) { + struct xfer_interface *dest = xfer_dest ( xfer ); + + return dest->op->vredirect ( dest, type, args ); +} + +/** + * Send redirection event + * + * @v xfer Data-transfer interface + * @v type New location type + * @v ... Remaining arguments depend upon location type + * @ret rc Return status code + */ +int redirect ( struct xfer_interface *xfer, int type, ... ) { + va_list args; + int rc; + + va_start ( args, type ); + rc = vredirect ( xfer, type, args ); + va_end ( args ); + return rc; +} + +/** * Deliver datagram * * @v xfer Data-transfer interface @@ -36,14 +68,35 @@ int deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf ) { struct xfer_interface *dest = xfer_dest ( xfer ); - return dest->op->deliver ( dest, xfer, iobuf ); + return dest->op->deliver ( dest, iobuf ); +} + +/** + * Deliver datagram as raw data + * + * @v xfer Data-transfer interface + * @v iobuf Datagram I/O buffer + * @ret rc Return status code + */ +int deliver_raw ( struct xfer_interface *xfer, const void *data, size_t len ) { + struct xfer_interface *dest = xfer_dest ( xfer ); + + return dest->op->deliver_raw ( dest, data, len ); } +/**************************************************************************** + * + * Helper methods + * + * These functions are designed to be used as methods in the + * xfer_interface_operations table. + * + */ + /** * Deliver datagram as raw data * * @v xfer Data-transfer interface - * @v src Source interface * @v iobuf Datagram I/O buffer * @ret rc Return status code * @@ -51,12 +104,10 @@ int deliver ( struct xfer_interface *xfer, struct io_buffer *iobuf ) { * data transfer interfaces that prefer to handle raw data. */ int deliver_as_raw ( struct xfer_interface *xfer, - struct xfer_interface *src, struct io_buffer *iobuf ) { int rc; - rc = xfer->op->deliver_raw ( xfer, src, iobuf->data, - iob_len ( iobuf ) ); + rc = xfer->op->deliver_raw ( xfer, iobuf->data, iob_len ( iobuf ) ); free_iob ( iobuf ); return rc; } @@ -65,7 +116,6 @@ int deliver_as_raw ( struct xfer_interface *xfer, * Deliver datagram as I/O buffer * * @v xfer Data-transfer interface - * @v src Source interface * @v data Data buffer * @v len Length of data buffer * @ret rc Return status code @@ -74,32 +124,34 @@ int deliver_as_raw ( struct xfer_interface *xfer, * for data transfer interfaces that prefer to handle I/O buffers. */ int deliver_as_iobuf ( struct xfer_interface *xfer, - struct xfer_interface *src, const void *data, size_t len ) { struct io_buffer *iobuf; -#warning "Do we need interface-specific I/O buffer allocation?" iobuf = alloc_iob ( len ); if ( ! iobuf ) return -ENOMEM; memcpy ( iob_put ( iobuf, len ), data, len ); - return xfer->op->deliver ( xfer, src, iobuf ); + return xfer->op->deliver ( xfer, iobuf ); } +/**************************************************************************** + * + * Null data transfer interface + * + */ + /** * Null deliver datagram as raw data * * @v xfer Data-transfer interface - * @v src Source interface * @v data Data buffer * @v len Length of data buffer * @ret rc Return status code */ static int null_deliver_raw ( struct xfer_interface *xfer, - struct xfer_interface *src, const void *data __unused, size_t len ) { - DBGC ( src, "XFER %p->%p %zd bytes delivered %s\n", src, xfer, len, + DBGC ( xfer, "XFER %p %zd bytes delivered %s\n", xfer, len, ( ( xfer == &null_xfer ) ? "before connection" : "after termination" ) ); return -EPIPE; |
