/*
 * Function:    main
 *
 * Description: 
 *              
 * Parameters:  
 *
 * Returns:     
 */
int
main(int argc, char **argv)
{
    int                                 rc;
    globus_result_t                     result;
    globus_object_t *                   error = NULL;
    char *                              errstring;
    globus_io_handle_t                  handle;
    globus_io_handle_t                  stdout_handle;
    globus_size_t                       bytes;
    globus_size_t                       i;
    globus_byte_t                       buf[1024];
#ifdef TARGET_ARCH_WIN32
	HANDLE						outputFile;
    globus_io_handle_t			write_handle;

	if ( argc < 3 )
	{
		usage( argv[0] );
		return -1;
	}
#endif

    globus_module_activate(GLOBUS_COMMON_MODULE);
    globus_module_activate(GLOBUS_IO_MODULE);

#ifndef TARGET_ARCH_WIN32
    result = globus_io_file_open("/etc/group",
				 O_RDONLY,
				 0600,
				 GLOBUS_NULL,
				 &handle);
#else
    result = globus_io_file_open( argv[1],
				 O_RDONLY,
				 0600,
				 GLOBUS_NULL,
				 &handle);
#endif

    if(result != GLOBUS_SUCCESS)
    {
        error = globus_error_get(result);
        errstring = globus_object_printable_to_string(error);
#ifndef TARGET_ARCH_WIN32
        globus_libc_printf("test failed to open /etc/group: %s\n", errstring);
#else
        globus_libc_printf("test failed to open %s: %s\n", argv[1], errstring);
#endif
        goto done;
    }
    
#ifndef TARGET_ARCH_WIN32
    result = globus_io_file_posix_convert(
        fileno(stdout),
        GLOBUS_NULL,
        &stdout_handle);
#else
	outputFile= CreateFile( argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
	 FILE_FLAG_OVERLAPPED, NULL );
	if ( outputFile == INVALID_HANDLE_VALUE )
	{
		printf( "An error occurred while trying to create the output file (error is %d)...exiting\n",
		 GetLastError() );
		return -1;
	}
    result= globus_io_file_windows_convert(
		outputFile,
		GLOBUS_NULL,
		&write_handle);
#endif
    if(result != GLOBUS_SUCCESS)
    {
        error = globus_error_get(result);
        errstring = globus_object_printable_to_string(error);
        globus_libc_printf("test failed to convert stdout to io handle: %s\n",
                           errstring);
        goto done;
    }

    do
    {
        result = globus_io_read(&handle,
                                buf,
                                sizeof(buf),
                                sizeof(buf),
                                &bytes);
        if(result == GLOBUS_SUCCESS ||
           ((error = globus_error_get(result)) &&
            (globus_object_type_match(globus_object_get_type(error),
                                      GLOBUS_IO_ERROR_TYPE_EOF))))
        {
            globus_size_t           nbytes2;
            
#ifndef TARGET_ARCH_WIN32
	globus_io_write(&stdout_handle,
			buf,
			bytes,
			&nbytes2);
#else
		globus_io_write( &write_handle,
				buf,
				bytes,
				&nbytes2);
#endif
        }
        else
        {
            errstring = globus_object_printable_to_string(error);
            globus_libc_printf("test failed to read /etc/group: %s\n",
                               errstring);
            goto done;

        }
    }
    while(result == GLOBUS_SUCCESS);

 done:

    if(error)
    {
        globus_object_free(error);
    }
    
    globus_io_close(&handle);
#ifndef TARGET_ARCH_WIN32
    globus_io_close(&stdout_handle);
#else
    globus_io_close( &write_handle);
#endif

    globus_module_deactivate(GLOBUS_IO_MODULE);
    globus_module_deactivate(GLOBUS_COMMON_MODULE);

    return 0;
}
int
main(
    int					argc,
    char *				argv[])
{
    globus_io_handle_t			listener;
    globus_io_handle_t			server_handle;
    globus_io_handle_t			client_handle;
    globus_io_attr_t			attr;
    unsigned short			port = 0;
    globus_result_t			result;
    globus_io_secure_authorization_data_t
					auth_data;
    globus_l_io_authorization_test_monitor_t
					monitor;
    char				greeting[] = "Hello, my friend.";
    char 				reply_buffer[256];
    globus_size_t			written;
    globus_size_t			read_amt;

    LTDL_SET_PRELOADED_SYMBOLS();

    globus_module_activate(GLOBUS_COMMON_MODULE);
    globus_module_activate(GLOBUS_IO_MODULE);

    /* Initialize monitor */
    globus_mutex_init(&monitor.mutex, GLOBUS_NULL);
    globus_cond_init(&monitor.cond, GLOBUS_NULL);
    monitor.connected = GLOBUS_FALSE;

    /* Prepare attributes */
    globus_io_secure_authorization_data_initialize(&auth_data);
    globus_io_tcpattr_init(&attr);
    globus_io_attr_set_secure_authentication_mode(
	    &attr,
	    GLOBUS_IO_SECURE_AUTHENTICATION_MODE_GSSAPI,
	    GSS_C_NO_CREDENTIAL);


    if(argc >= 2)
    {
	if(! strcasecmp(argv[1], "self"))
	{
	    globus_io_attr_set_secure_authorization_mode(
		    &attr,
		    GLOBUS_IO_SECURE_AUTHORIZATION_MODE_SELF,
		    &auth_data);
	}
	else if(argc > 2 && ! strcasecmp(argv[1], "identity") )
	{
	    globus_io_secure_authorization_data_set_identity(&auth_data,
		                                             argv[2]);
	    globus_io_attr_set_secure_authorization_mode(
		    &attr,
		    GLOBUS_IO_SECURE_AUTHORIZATION_MODE_IDENTITY,
		    &auth_data);
	}
	else if(! strcasecmp(argv[1], "callback"))
	{
	    globus_io_secure_authorization_data_set_callback(
		    &auth_data,
		    globus_l_io_authorization_test_callback,
		    GLOBUS_NULL);

	    globus_io_attr_set_secure_authorization_mode(
		    &attr,
		    GLOBUS_IO_SECURE_AUTHORIZATION_MODE_CALLBACK,
		    &auth_data);
	}
	else if(! strcasecmp(argv[1], "-callback"))
	{
	    globus_io_secure_authorization_data_set_callback(
		    &auth_data,
		    globus_l_io_authorization_test_callback,
		    (void *) 0x1);

	    globus_io_attr_set_secure_authorization_mode(
		    &attr,
		    GLOBUS_IO_SECURE_AUTHORIZATION_MODE_CALLBACK,
		    &auth_data);
	}
	else
	{
	    goto no_authorization_mode;
	}
    }
    else
    {
	goto no_authorization_mode;
    }

    result = globus_io_tcp_create_listener(
	    &port,
	    -1,
	    &attr,
	    &listener);

    if(result != GLOBUS_SUCCESS)
    {
        char *msg = globus_error_print_friendly(globus_error_peek(result));
	globus_libc_fprintf(stderr, "# Could not create listener: %s\n", msg);
        free(msg);

	goto error_exit;
    }

    result = globus_io_tcp_register_connect(
	    "localhost",
	    port,
	    &attr,
	    globus_l_io_authorization_test_connect_callback,
	    &monitor,
	    &client_handle);

    if(result != GLOBUS_SUCCESS)
    {
	globus_libc_printf("# Could not register connect\n");
	goto error_exit;
    }

    result = globus_io_tcp_listen(&listener);
    if(result != GLOBUS_SUCCESS)
    {
	globus_libc_printf("# Could not listen for connections\n");
	goto error_exit;
    }
    result = globus_io_tcp_accept(&listener,
	                          &attr,
			          &server_handle);
    if(result != GLOBUS_SUCCESS)
    {
	if(strcasecmp(argv[1], "-callback") == 0)
	{
	    globus_module_deactivate_all();
	    exit(0);
	}
	else
	{
	    globus_libc_printf("# Could not accept connection\n");
	    goto error_exit;
	}
    }

    globus_mutex_lock(&monitor.mutex);
    while(! monitor.connected)
    {
	globus_cond_wait(&monitor.cond, &monitor.mutex);
    }

    result = globus_io_close(&listener);
    if(result != GLOBUS_SUCCESS)
    {
	globus_libc_printf("# Could not close listener\n");
	goto error_exit;
    }

    result = globus_io_write(&server_handle,
			     greeting,
		             sizeof(greeting),
		             &written);
    if(result != GLOBUS_SUCCESS)
    {
	globus_libc_printf("# Could not write greeting\n");
	goto error_exit;
    }
    result = globus_io_close(&server_handle);
    if(result != GLOBUS_SUCCESS)
    {
	globus_libc_printf("# Could not close server\n");
	goto error_exit;
    }
    result = globus_io_read(&client_handle,
	                    reply_buffer,
		            sizeof(reply_buffer),
		            sizeof(reply_buffer),
		            &read_amt);
    if(result != GLOBUS_SUCCESS)
    {
	globus_object_t * err;

	err = globus_error_get(result);

	if(! globus_io_eof(err))
	{
	    globus_libc_printf("# Could not read greeting\n");
	    goto error_exit;
	}
    }
    result = globus_io_close(&client_handle);
    if(result != GLOBUS_SUCCESS)
    {
	globus_libc_printf("# Could not close client\n");
	goto error_exit;
    }

    if(!memcmp(greeting, reply_buffer, sizeof(greeting)) == 0)
    {
	result = GLOBUS_FAILURE;
        goto error_exit;
    }

    globus_module_deactivate_all();
    exit(0);


no_authorization_mode:
    globus_libc_printf(
    "Usage: %s AUTHORIZATION\n"
    "      AUTHORIZATION is one of\n"
    "      self                 use Globus I/O's self-authorization mode\n"
    "      identity \"subject\"   use Globus I/O's subject-based authorization\n"
    "      callback             use Globus I/O's callback authorization\n"
    "      -callback            use Globus I/O's callback authorization with\n"
    "                           a failure callback\n",
    argv[0]);

error_exit:
    globus_module_deactivate_all();
    exit(1);
}