/******************************************************************************
Function: globus_gass_server_ez_init()

Description: 

Parameters: 

Returns: 
******************************************************************************/
int
globus_gass_server_ez_init(globus_gass_transfer_listener_t * listener,
			   globus_gass_transfer_listenerattr_t * attr,
			   char * scheme,
			   globus_gass_transfer_requestattr_t * reqattr,
			   unsigned long options,
			   globus_gass_server_ez_client_shutdown_t callback,
               int fd)
{
    int rc;
    globus_l_gass_server_ez_t *server;
    globus_bool_t free_scheme=GLOBUS_FALSE;
    
    if(scheme==GLOBUS_NULL)
    {
	scheme=globus_malloc(6);  /* https/0 is the default */
	if(scheme == GLOBUS_NULL)
        {
            rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED;
            goto error_exit;
        }
        free_scheme=GLOBUS_TRUE;
	globus_libc_lock();
        sprintf(scheme, "https");
        globus_libc_unlock();
    }

    if(reqattr==GLOBUS_NULL)
    {
	reqattr=(globus_gass_transfer_requestattr_t *)globus_malloc(sizeof(globus_gass_transfer_requestattr_t));

        globus_gass_transfer_requestattr_init(reqattr,
    					      scheme);
        globus_gass_transfer_secure_requestattr_set_authorization(reqattr,
							   GLOBUS_GASS_TRANSFER_AUTHORIZE_SELF,
							   scheme);
    }
    rc=globus_gass_transfer_create_listener(listener,
					    attr,
					    scheme);


    if(rc!=GLOBUS_SUCCESS)
    {
	goto error_exit;
    }

    server=(globus_l_gass_server_ez_t *)globus_malloc(
					sizeof (globus_l_gass_server_ez_t));
    if(server==GLOBUS_NULL)
    {
        rc = GLOBUS_GASS_TRANSFER_ERROR_MALLOC_FAILED;
	goto error_exit;
    }

    server->options=options;
    server->listener=*listener;
    server->reqattr=reqattr;
    server->callback=callback;
    server->fd=fd;

    globus_hashtable_insert(&globus_l_gass_server_ez_listeners,
			    (void *)*listener,
			    server);

    rc=globus_gass_transfer_register_listen(*listener,
				globus_l_gass_server_ez_listen_callback,
					(void *)reqattr);
/* insert error handling here*/

    error_exit:

    if (free_scheme) globus_free(scheme);

    return rc;
} /* globus_gass_server_ez_init() */
/* Test Case:
 * Submit a job that generates output after a short time.
 * Before that output is generated, send a STDIO_UPDATE signal, to
 * direct the output to a different port.
 * Verify that the output arrives at the new port
 */
int
test_stdio_update(void)
{
    char                                *old_listener_url, *new_listener_url;
    char                                *old_job_contact;
    int                                 rc;
    char                                *callback_contact;
    char                                *old_rsl, *new_rsl;
    test_monitor_t                      monitor;
    const char                          rsl_spec[] =
            "&(executable=/bin/sh)"
            "(arguments=-c 'sleep 30; echo hello;')"
            "(rsl_substitution = (TEST_GASS_URL %s))"
            "(stdout = $(TEST_GASS_URL)/out)";
    const char                          stdio_update_rsl_spec[] =
            "&(stdout = %s/out)";

    globus_mutex_init(&monitor.mutex, NULL);
    globus_cond_init(&monitor.cond, NULL);

    memset(monitor.old_output, 0, sizeof(monitor.old_output));
    memset(monitor.new_output, 0, sizeof(monitor.new_output));
    monitor.old_request = GLOBUS_NULL_HANDLE;
    monitor.new_request = GLOBUS_NULL_HANDLE;
    monitor.status = GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED;
    monitor.failure_code = 0;

    /* Create a pair of listeners and get their base URLs. The job will be
     * submitted with stdout directed to the first, then redirected to the
     * second via a stdio update signal
     */
    rc = globus_gass_transfer_create_listener(
            &monitor.old_listener,
            NULL,
            "https");
    test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS);
    test_assert(monitor.old_listener != GLOBUS_NULL_HANDLE);

    old_listener_url = globus_gass_transfer_listener_get_base_url(
            monitor.old_listener);
    test_assert(old_listener_url != NULL);

    rc = globus_gass_transfer_register_listen(
            monitor.old_listener,
            test_l_old_listener_callback,
            &monitor);
    test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS);

    rc = globus_gass_transfer_create_listener(
            &monitor.new_listener,
            NULL,
            "https");
    test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS);
    test_assert(monitor.new_listener != GLOBUS_NULL_HANDLE);

    new_listener_url = globus_gass_transfer_listener_get_base_url(
            monitor.new_listener);
    test_assert(new_listener_url != NULL);

    rc = globus_gass_transfer_register_listen(
            monitor.new_listener,
            test_l_new_listener_callback,
            &monitor);
    test_assert(rc == GLOBUS_SUCCESS);

    old_rsl = globus_common_create_string(rsl_spec, old_listener_url);
    test_assert(old_rsl != NULL);

    /* Submit the job, do the two-phase commit, then submit a restart
     * request with the new stdout destination
     */
    rc = globus_gram_client_callback_allow(
            test_l_gram_callback,
            &monitor,
            &callback_contact);
    test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS);
    test_assert(callback_contact != NULL);

    rc = globus_gram_client_job_request(
            contact_string,
            old_rsl,
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED|
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_STAGE_IN|
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_PENDING|
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_ACTIVE|
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_STAGE_OUT|
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE|
            GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED,
            callback_contact,
            &old_job_contact);
    test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS);
    test_assert(old_job_contact != NULL);

    globus_mutex_lock(&monitor.mutex);
    while (monitor.status == GLOBUS_GRAM_PROTOCOL_JOB_STATE_UNSUBMITTED)
    {
        globus_cond_wait(&monitor.cond, &monitor.mutex);
    }

    new_rsl = globus_common_create_string(
            stdio_update_rsl_spec, new_listener_url);
    test_assert(new_rsl != NULL);

    rc = globus_gram_client_job_signal(
            old_job_contact,
            GLOBUS_GRAM_PROTOCOL_JOB_SIGNAL_STDIO_UPDATE,
            new_rsl,
            &monitor.status,
            &monitor.failure_code);
    test_assert_gram_rc_equals(rc, GLOBUS_SUCCESS);

    /* Wait for job to complete. After it's done, check to see which
     * destination got stdout
     */
    while (monitor.status != GLOBUS_GRAM_PROTOCOL_JOB_STATE_DONE &&
           monitor.status != GLOBUS_GRAM_PROTOCOL_JOB_STATE_FAILED)
    {
        globus_cond_wait(&monitor.cond, &monitor.mutex);
    }
    if (monitor.old_request)
    {
        globus_gass_transfer_fail(monitor.old_request, test_l_gass_fail, NULL);
    }

    globus_mutex_unlock(&monitor.mutex);

    if (monitor.new_output[0] == 0)
    {
        fprintf(stderr, "Didn't get expected output to new handle\n");
        test_assert(strcmp((char *) monitor.new_output, "hello\n") == 0);
    }
    if (monitor.old_output[0] != 0)
    {
        fprintf(stderr, "Unexpected output to old handle: %s",
                monitor.old_output);
        test_assert(monitor.old_output[0] == 0);
    }

    return rc;
}