/*
 * Portions of this file Copyright 1999-2005 University of Chicago
 * Portions of this file Copyright 1999-2005 The University of Southern California.
 *
 * This file or a portion of this file is licensed under the
 * terms of the Globus Toolkit Public License, found at
 * http://www.globus.org/toolkit/download/license.html.
 * If you redistribute this file, with or without
 * modifications, you must include this notice in the file.
 */

#ifndef GLOBUS_XIO_MODE_E_DRIVER_INCLUDE
#define GLOBUS_XIO_MODE_E_DRIVER_INCLUDE

/**
 * @file
 * Header file for XIO MODE_E Driver
 */

#include "globus_xio_system.h"
#include "globus_common.h"

/**
 * @defgroup mode_e_driver Globus XIO MODE_E Driver
 */

/**
 * @defgroup mode_e_driver_instance Opening/Closing
 * @ingroup mode_e_driver
 *
 * An XIO handle with the mode_e driver can be created with either
 * @ref globus_xio_handle_create() or @ref globus_xio_server_register_accept().
 *
 * If the handle is created with @ref globus_xio_handle_create(), the contact
 * string passed to ref globus_xio_register_open() call must contain
 * a host name and service/port. The number of streams required can be 
 * specified on the attr using @ref GLOBUS_XIO_MODE_E_SET_NUM_STREAMS (default
 * is one stream). The stack of drivers to be used on the streams can be
 * specified on the attr using @ref GLOBUS_XIO_MODE_E_SET_STACK (default is
 * a stack containing TCP driver). 
 *
 * When the XIO handle is closed, the mode_e driver will destroy its internal
 * resources and close the stream(s).
 */

/**
 * @defgroup mode_e_driver_io Reading/Writing
 * @ingroup mode_e_driver
 * Mode E is unidirectional. Clients can only write and the server can only 
 * read.
 * The @ref globus_xio_register_read() enforce that the waitforbytes parameter
 * should be one. When multiple transport streams are used between the client 
 * and the server, data might not be delivered in order.
 * @ref globus_xio_data_descriptor_cntl() can be used to get the offset of the
 * data.
 *
 * @ref globus_xio_register_write() does not enforce any restriction on the
 * waitforbytes parameter.
 *
 * In any case, when an error or EOF occurs before the waitforbytes request
 * has been met, the outgoing nbytes is set to the amount of data actually
 * read/written before the error or EOF occurred.
 */

/**
 * @defgroup mode_e_driver_server Server
 * @ingroup mode_e_driver
 *
 * @ref globus_xio_server_create() causes a mode_e listener to be created
 * and listened upon.  @ref globus_xio_server_register_accept() performs an
 * asynchronous accept(). @ref globus_xio_server_register_close() cleans up
 * the internal resources associated with the mode_e server.
 *
 * All accepted handles inherit all mode_e specific attributes set in the attr 
 * to @ref globus_xio_server_create()
 */

/**
 * @defgroup mode_e_driver_envs Env Variables
 * @ingroup mode_e_driver
 *
 * - GLOBUS_XIO_MODE_E_DEBUG Available if using a debug build.  See 
 * globus_debug.h for format.  
 */

/**
 * @defgroup mode_e_driver_cntls Attributes and Cntls
 * @ingroup mode_e_driver
 *
 * Mode_e driver specific attrs and cntls.
 *
 * @see globus_xio_attr_cntl()
 * @see globus_xio_handle_cntl()
 * @see globus_xio_server_cntl()
 * @see globus_xio_data_descriptor_cntl()
 */
/**
 * @defgroup mode_e_driver_types Types
 * @ingroup mode_e_driver
 */
/**
 * @defgroup mode_e_driver_errors Error Types
 * @ingroup mode_e_driver
 *
 * The errors reported by MODE_E driver include
 * GLOBUS_XIO_ERROR_COMMAND, GLOBUS_XIO_ERROR_MEMORY, GLOBUS_XIO_ERROR_STATE, 
 * GLOBUS_XIO_ERROR_PARAMETER, GLOBUS_XIO_ERROR_EOF, 
 * GLOBUS_XIO_ERROR_CANCELED, @ref GLOBUS_XIO_MODE_E_HEADER_ERROR
 * 
 * @see globus_xio_driver_error_match()
 * @see globus_error_errno_match()
 */

/**
 * MODE_E driver specific error types
 * @ingroup mode_e_driver_errors
 */
typedef enum
{   
    /**
     * Indicates that the mode_e header is erroneous
     */
    GLOBUS_XIO_MODE_E_HEADER_ERROR
    
} globus_xio_mode_e_error_type_t;


/** doxygen varargs filter stuff
 * GlobusVarArgDefine(
 *      attr, globus_result_t, globus_xio_attr_cntl, attr, driver)
 * GlobusVarArgDefine(
 *      handle, globus_result_t, globus_xio_handle_cntl, handle, driver)
 * GlobusVarArgDefine(
 *      dd, globus_result_t, globus_xio_data_descriptor_cntl, dd, driver)
 */

/**
 * MODE_E driver specific cntls
 * @ingroup mode_e_driver_cntls
 */

typedef enum
{
    /** GlobusVarArgEnum(attr)
     * Set the stack (of xio drivers) to be used for the connection(s).
     * @ingroup mode_e_driver_cntls
     * Do not create a new ftp client handle, use this handle instead.
     * 
     * @param stack
     *      Specifies the stack to use for the connection(s).
     *      Note: this stack will not be destroyed.
     */
    /* globus_xio_stack_t 			stack */
    GLOBUS_XIO_MODE_E_SET_STACK,

    /** GlobusVarArgEnum(attr)
     * Get the stack on the attr.
     * @ingroup mode_e_driver_cntls
     * 
     * @param stack_out
     *      The stack will be stored here. If none is set, GLOBUS_NULL will be 
     *      set.
     */
    /* globus_xio_stack_t *			stack_out */
    GLOBUS_XIO_MODE_E_GET_STACK,

    /** GlobusVarArgEnum(attr)
     * Set the number of streams to be used between the client and the
     * server.
     * @ingroup mode_e_driver_cntls
     *
     * @param num_streams
     *      Specifies the number of streams to use.
     */
    /* int					max_connection_count */
    GLOBUS_XIO_MODE_E_SET_NUM_STREAMS,

    /** GlobusVarArgEnum(attr)
     * Get the number of streams on the attr.
     * @ingroup mode_e_driver_cntls
     *
     * @param num_streams_out
     *      The stream count will be stored here.
     */
    /* int *					max_connection_count_out */
    GLOBUS_XIO_MODE_E_GET_NUM_STREAMS,

    /** GlobusVarArgEnum(attr)
     * Set the attr cntl function that should be called before creating a new
     * connection with the stack specified. If any driver specific cntls is 
     * needed on the stack, this function should take care of applying all 
     * those cntls on the xio_attr passed to it.
     * @see globus_xio_mode_e_attr_cntl_callback_t
     * @ingroup mode_e_driver_cntls
     *
     * @param attr_cntl_cb
     *      Specifies the function pointer.
     */
    /* globus_xio_mode_e_attr_cntl_callback_t 	attr_cntl_cb */
    GLOBUS_XIO_MODE_E_APPLY_ATTR_CNTLS,

    /** GlobusVarArgEnum(attr)
     * Set flag to indicate whether the data read from user would always be 
     * preceded by an offset read or not. The user can do a read with 
     * wait_for_bytes set to zero, to find the offset of the data that he is 
     * going to get in his next read operation
     * @ingroup mode_e_driver_cntls
     *
     * @param offset_reads
     *      GLOBUS_TRUE to enable offset reads, GLOBUS_FALSE to disable 
     * offset reads (default).
     */
    /* globus_bool_t				offset_reads */
    GLOBUS_XIO_MODE_E_SET_OFFSET_READS,

    /** GlobusVarArgEnum(attr)
     * Get OFFSET_READS flag on the attr.
     * @ingroup mode_e_driver_cntls
     *
     * @param offset_reads_out
     *      The OFFSET_READS flag will be stored here.
     */
    /* globus_bool_t *				offset_reads_out */
    GLOBUS_XIO_MODE_E_GET_OFFSET_READS,

    /** GlobusVarArgEnum(attr)
     * Set flag to indicate whether EODC will be set manually by the user on 
     * a data_desc or the driver has to calculate the EODC
     * @ingroup mode_e_driver_cntls
     *
     * @param eof
     *      GLOBUS_TRUE to send EOF (default), GLOBUS_FALSE to not send EOF.
     * @param eod_count
     *      Specifies the number of EODs that must be received by the server.
     */
    /* globus_bool_t				manual_eodc */
    GLOBUS_XIO_MODE_E_SET_MANUAL_EODC,

    /** GlobusVarArgEnum(attr)
     * Get MANUAL_EODC flag on the attr.
     * @ingroup mode_e_driver_cntls
     *
     * @param eof_out
     *      The MANUAL_EODC flag will be stored here.
     */
    /* globus_bool_t *				manual_eodc_out */
    GLOBUS_XIO_MODE_E_GET_MANUAL_EODC,

    /** GlobusVarArgEnum(dd)
     * Set SEND_EOD flag
     * @ingroup mode_e_driver_cntls
     * Used only for data descriptors to write calls.
     *
     * @param send_eod
     *	    GLOBUS_TRUE to send EOD, GLOBUS_FALSE to not send EOD (default).
     */
    /* globus_bool_t				send_eod */
    GLOBUS_XIO_MODE_E_SEND_EOD,

    /** GlobusVarArgEnum(handle)
     * Set EOD count
     * @ingroup mode_e_driver_cntls
     * Used only if MANUAL_EODC flag is set to GLOBUS_TRUE.
     *
     * @param eod_count
     *      specifies the eod count 
     */
    /* int					eod_count */
    GLOBUS_XIO_MODE_E_SET_EODC,

    /** GlobusVarArgEnum(dd)
     * Get offset of the next available data 
     * @ingroup mode_e_driver_cntls
     * Used only if OFFSET_READS is enabled.
     *
     * @param offset_out
     *      offset will be stored here
     */
    /* globus_off_t *				offset_out */
    GLOBUS_XIO_MODE_E_DD_GET_OFFSET

} globus_xio_mode_e_cmd_t;	

#endif

/**
 * MODE_E driver specific types
 * @ingroup mode_e_driver_types
 * @hideinitializer
 */
typedef globus_result_t
(*globus_xio_mode_e_attr_cntl_callback_t)(
    globus_xio_attr_t                   attr);
