/*
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * You can also choose to distribute this program under the terms of
 * the Unmodified Binary Distribution Licence (as given in the file
 * COPYING.UBDL), provided that you have satisfied its requirements.
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FILE_SECBOOT ( PERMITTED );

#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <ipxe/xfer.h>
#include <ipxe/uri.h>
#include <ipxe/socket.h>
#include <ipxe/open.h>

/** @file
 *
 * Data transfer interface opening
 *
 */

/**
 * Find opener for URI scheme
 *
 * @v scheme		URI scheme
 * @ret opener		Opener, or NULL
 */
struct uri_opener * xfer_uri_opener ( const char *scheme ) {
	struct uri_opener *opener;

	for_each_table_entry ( opener, URI_OPENERS ) {
		if ( strcasecmp ( scheme, opener->scheme ) == 0 )
			return opener;
	}
	return NULL;
}

/**
 * Open URI
 *
 * @v intf		Data transfer interface
 * @v uri		URI
 * @ret rc		Return status code
 *
 * The URI will be regarded as being relative to the current working
 * URI (see churi()).
 */
int xfer_open_uri ( struct interface *intf, struct uri *uri ) {
	struct uri_opener *opener;
	struct uri *resolved_uri;
	int rc;

	/* Resolve URI */
	resolved_uri = resolve_uri ( cwuri, uri );
	if ( ! resolved_uri ) {
		rc = -ENOMEM;
		goto err_resolve_uri;
	}

	/* Find opener which supports this URI scheme */
	opener = xfer_uri_opener ( resolved_uri->scheme );
	if ( ! opener ) {
		DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
		       "unsupported URI scheme \"%s\"\n",
		       INTF_DBG ( intf ), resolved_uri->scheme );
		rc = -ENOTSUP;
		goto err_opener;
	}

	/* Call opener */
	DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening %s URI\n",
	       INTF_DBG ( intf ), resolved_uri->scheme );
	if ( ( rc = opener->open ( intf, resolved_uri ) ) != 0 ) {
		DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " could not open: "
		       "%s\n", INTF_DBG ( intf ), strerror ( rc ) );
		goto err_open;
	}

 err_open:
 err_opener:
	uri_put ( resolved_uri );
 err_resolve_uri:
	return rc;
}

/**
 * Open URI string
 *
 * @v intf		Data transfer interface
 * @v uri_string	URI string (e.g. "http://ipxe.org/kernel")
 * @ret rc		Return status code
 *
 * The URI will be regarded as being relative to the current working
 * URI (see churi()).
 */
int xfer_open_uri_string ( struct interface *intf,
			   const char *uri_string ) {
	struct uri *uri;
	int rc;

	DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening URI %s\n",
	       INTF_DBG ( intf ), uri_string );

	uri = parse_uri ( uri_string );
	if ( ! uri )
		return -ENOMEM;

	rc = xfer_open_uri ( intf, uri );

	uri_put ( uri );
	return rc;
}

/**
 * Open socket
 *
 * @v intf		Data transfer interface
 * @v semantics		Communication semantics (e.g. SOCK_STREAM)
 * @v peer		Peer socket address
 * @v local		Local socket address, or NULL
 * @ret rc		Return status code
 */
int xfer_open_socket ( struct interface *intf, int semantics,
		       struct sockaddr *peer, struct sockaddr *local ) {
	struct socket_opener *opener;

	DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " opening (%s,%s) socket\n",
	       INTF_DBG ( intf ), socket_semantics_name ( semantics ),
	       socket_family_name ( peer->sa_family ) );

	for_each_table_entry ( opener, SOCKET_OPENERS ) {
		if ( opener->semantics == semantics )
			return opener->open ( intf, peer, local );
	}

	DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open "
	       "unsupported socket type (%s,%s)\n",
	       INTF_DBG ( intf ), socket_semantics_name ( semantics ),
	       socket_family_name ( peer->sa_family ) );
	return -ENOTSUP;
}

/**
 * Open location
 *
 * @v intf		Data transfer interface
 * @v type		Location type
 * @v args		Remaining arguments depend upon location type
 * @ret rc		Return status code
 */
int xfer_vopen ( struct interface *intf, int type, va_list args ) {
	switch ( type ) {
	case LOCATION_URI_STRING: {
		const char *uri_string = va_arg ( args, const char * );

		return xfer_open_uri_string ( intf, uri_string ); }
	case LOCATION_URI: {
		struct uri *uri = va_arg ( args, struct uri * );

		return xfer_open_uri ( intf, uri ); }
	case LOCATION_SOCKET: {
		int semantics = va_arg ( args, int );
		struct sockaddr *peer = va_arg ( args, struct sockaddr * );
		struct sockaddr *local = va_arg ( args, struct sockaddr * );

		return xfer_open_socket ( intf, semantics, peer, local ); }
	default:
		DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to "
		       "open unsupported location type %d\n",
		       INTF_DBG ( intf ), type );
		return -ENOTSUP;
	}
}

/**
 * Open location
 *
 * @v intf		Data transfer interface
 * @v type		Location type
 * @v ...		Remaining arguments depend upon location type
 * @ret rc		Return status code
 */
int xfer_open ( struct interface *intf, int type, ... ) {
	va_list args;
	int rc;

	va_start ( args, type );
	rc = xfer_vopen ( intf, type, args );
	va_end ( args );
	return rc;
}

/**
 * Reopen location
 *
 * @v intf		Data transfer interface
 * @v type		Location type
 * @v args		Remaining arguments depend upon location type
 * @ret rc		Return status code
 *
 * This will close the existing connection and open a new connection
 * using xfer_vopen().  It is intended to be used as a .vredirect
 * method handler.
 */
int xfer_vreopen ( struct interface *intf, int type, va_list args ) {

	/* Close existing connection */
	intf_restart ( intf, 0 );

	/* Open new location */
	return xfer_vopen ( intf, type, args );
}
