static void test_l_old_accept_callback( void * callback_arg, globus_gass_transfer_request_t request) { test_monitor_t *monitor = callback_arg; int rc; globus_mutex_lock(&monitor->mutex); monitor->old_request = request; globus_mutex_unlock(&monitor->mutex); globus_gass_transfer_authorize( request, GLOBUS_GASS_TRANSFER_LENGTH_UNKNOWN); rc = globus_gass_transfer_receive_bytes( request, monitor->old_output, sizeof(monitor->old_output), 1, test_l_data_callback, monitor); rc = globus_gass_transfer_register_listen( monitor->old_listener, test_l_old_listener_callback, monitor); }
static void globus_l_gass_server_ez_register_accept_callback( void * listener, globus_gass_transfer_request_t request ) { int rc; char * subjectname; char * path=GLOBUS_NULL; char * url; globus_url_t parsed_url; globus_l_gass_server_ez_t * s; globus_gass_server_ez_request_t *r; struct stat statstruct; globus_byte_t * buf; int amt; int flags=0; subjectname=globus_gass_transfer_request_get_subject(request); /* lookup our options */ s=(globus_l_gass_server_ez_t *)globus_hashtable_lookup( &globus_l_gass_server_ez_listeners, listener); /* Check for valid URL */ url=globus_gass_transfer_request_get_url(request); rc = globus_url_parse(url, &parsed_url); if(rc != GLOBUS_SUCCESS || parsed_url.url_path == GLOBUS_NULL || strlen(parsed_url.url_path) == 0U) { globus_gass_transfer_deny(request, 404, "File Not Found"); globus_gass_transfer_request_destroy(request); if (rc == GLOBUS_SUCCESS) globus_url_destroy(&parsed_url); goto reregister_nourl; } if(globus_gass_transfer_request_get_type(request) == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND) { flags = O_CREAT | O_WRONLY | O_APPEND; } else if(globus_gass_transfer_request_get_type(request) == GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT) { flags = O_CREAT | O_WRONLY | O_TRUNC; } switch(globus_gass_transfer_request_get_type(request)) { case GLOBUS_GASS_TRANSFER_REQUEST_TYPE_APPEND: case GLOBUS_GASS_TRANSFER_REQUEST_TYPE_PUT: /* Check to see if this is a request we are allowed to handle */ if(((s->options & GLOBUS_GASS_SERVER_EZ_WRITE_ENABLE) == 0UL) && ((s->options & GLOBUS_GASS_SERVER_EZ_STDOUT_ENABLE) == 0UL) && ((s->options & GLOBUS_GASS_SERVER_EZ_STDERR_ENABLE) == 0UL) && ((s->options & GLOBUS_GASS_SERVER_EZ_CLIENT_SHUTDOWN_ENABLE) == 0UL)) { goto deny; } /* Expand ~ and ~user prefix if enaabled in options */ rc = globus_l_gass_server_ez_tilde_expand(s->options, parsed_url.url_path, &path); if(strncmp(path, "/dev/saga", 9) == 0 && (s->options & GLOBUS_GASS_SERVER_EZ_STDOUT_ENABLE)) { rc = s->fd; // the pipe handle! goto authorize; } else if(strncmp(path, "/dev/saga/", 9) == 0) { goto deny; } else if(strcmp(path, "/dev/globus_gass_client_shutdown") == 0) { if(s->options & GLOBUS_GASS_SERVER_EZ_CLIENT_SHUTDOWN_ENABLE && s->callback != GLOBUS_NULL) { s->callback(); } goto deny; } #ifdef TARGET_ARCH_WIN32 // The call to open() in Windows defaults to text mode, so // we to override it. flags |= O_BINARY; #endif rc = globus_libc_open(path, flags, 0600); if(rc < 0) { goto deny; } authorize: globus_gass_transfer_authorize(request, 0); if(s->options & GLOBUS_GASS_SERVER_EZ_LINE_BUFFER) { r=(globus_gass_server_ez_request_t *)globus_malloc( sizeof(globus_gass_server_ez_request_t)); r->fd=rc; r->line_buffer=globus_malloc(80); r->line_buffer_used= 0UL; r->line_buffer_length = 80UL; r->linebuffer = GLOBUS_TRUE; globus_gass_transfer_receive_bytes(request, globus_malloc(1024), 1024, 1, globus_gass_server_ez_put_memory_done, r); } else { globus_gass_transfer_receive_bytes(request, globus_malloc(1024), 1024, 1, globus_l_gass_server_ez_put_callback, (void *) rc); } break; case GLOBUS_GASS_TRANSFER_REQUEST_TYPE_GET: flags = O_RDONLY; /* Expand ~ and ~user prefix if enaabled in options */ rc = globus_l_gass_server_ez_tilde_expand(s->options, parsed_url.url_path, &path); if((s->options & GLOBUS_GASS_SERVER_EZ_READ_ENABLE) == 0UL) { goto deny; } if(stat(path, &statstruct)==0) { #ifdef TARGET_ARCH_WIN32 // The call to open() in Windows defaults to text mode, // so we to override it. flags |= O_BINARY; #endif rc = globus_libc_open(path, flags, 0600); fstat(rc, &statstruct); } else { globus_gass_transfer_deny(request, 404, "File Not Found"); globus_gass_transfer_request_destroy(request); goto reregister; } buf = globus_malloc(1024); amt = read(rc, buf, 1024); if(amt == -1) { globus_free(buf); goto deny; } globus_gass_transfer_authorize(request, statstruct.st_size); globus_gass_transfer_send_bytes(request, buf, amt, GLOBUS_FALSE, globus_l_gass_server_ez_get_callback, (void *) rc); break; default: deny: globus_gass_transfer_deny(request, 400, "Bad Request"); globus_gass_transfer_request_destroy(request); } reregister: globus_url_destroy(&parsed_url); reregister_nourl: globus_gass_transfer_register_listen( (globus_gass_transfer_listener_t) listener, globus_l_gass_server_ez_listen_callback, s->reqattr); if (path != GLOBUS_NULL) globus_free(path); } /*globus_l_gass_server_ez_register_accept_callback*/
/****************************************************************************** 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; }