globus_result_t globus_xio_attr_init( globus_xio_attr_t * attr) { globus_result_t res; globus_i_xio_attr_t * xio_attr; GlobusXIOName(globus_xio_attr_init); GlobusXIODebugEnter(); if(attr == NULL) { res = GlobusXIOErrorParameter("attr"); goto err; } /* allocate the attr */ xio_attr = (globus_i_xio_attr_t *) globus_calloc(sizeof(globus_i_xio_attr_t), 1); if(xio_attr == NULL) { res = GlobusXIOErrorMemory("attr"); goto err; } xio_attr->entry = (globus_i_xio_attr_ent_t *) globus_calloc(sizeof(globus_i_xio_attr_ent_t) * GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE, 1); if(xio_attr->entry == NULL) { *attr = GLOBUS_NULL; globus_free(xio_attr); res = GlobusXIOErrorMemory("attr->entry"); goto err; } /* zero it out */ xio_attr->max = GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE; xio_attr->space = GLOBUS_CALLBACK_GLOBAL_SPACE; globus_mutex_lock(&globus_i_xio_mutex); { globus_list_insert(&globus_i_xio_outstanding_attrs_list, xio_attr); } globus_mutex_unlock(&globus_i_xio_mutex); *attr = xio_attr; GlobusXIODebugExit(); return GLOBUS_SUCCESS; err: GlobusXIODebugExitWithError(); return res; }
static globus_result_t globus_l_xio_popen_handle_init( xio_l_popen_handle_t ** handle) { globus_result_t result; GlobusXIOName(globus_l_xio_popen_handle_init); GlobusXIOPOpenDebugEnter(); *handle = (xio_l_popen_handle_t *) globus_calloc(1, sizeof(xio_l_popen_handle_t)); if(!*handle) { result = GlobusXIOErrorMemory("handle"); goto error_handle; } globus_mutex_init(&(*handle)->lock, NULL); GlobusXIOPOpenDebugExit(); return GLOBUS_SUCCESS; error_handle: GlobusXIOPOpenDebugExitWithError(); return result; }
static globus_result_t globus_l_xio_pipe_attr_init( void ** out_attr) { xio_l_pipe_attr_t * attr; globus_result_t result; GlobusXIOName(globus_l_xio_pipe_attr_init); GlobusXIOPipeDebugEnter(); /* * create a file attr structure and intialize its values */ attr = (xio_l_pipe_attr_t *) globus_malloc(sizeof(xio_l_pipe_attr_t)); if(!attr) { result = GlobusXIOErrorMemory("attr"); goto error_attr; } memcpy(attr, &xio_l_pipe_attr_default, sizeof(xio_l_pipe_attr_t)); *out_attr = attr; GlobusXIOPipeDebugExit(); return GLOBUS_SUCCESS; error_attr: GlobusXIOPipeDebugExitWithError(); return result; }
static globus_result_t globus_l_xio_pipe_handle_init( xio_l_pipe_handle_t ** handle, xio_l_pipe_attr_t * attr) { globus_result_t result; GlobusXIOName(globus_l_xio_pipe_handle_init); GlobusXIOPipeDebugEnter(); *handle = (xio_l_pipe_handle_t *) globus_calloc(1, sizeof(xio_l_pipe_handle_t)); if(!*handle) { result = GlobusXIOErrorMemory("handle"); goto error_handle; } globus_mutex_init(&(*handle)->lock, NULL); (*handle)->use_blocking_io = attr->use_blocking_io; (*handle)->infd = attr->infd; (*handle)->outfd = attr->outfd; GlobusXIOPipeDebugExit(); return GLOBUS_SUCCESS; error_handle: GlobusXIOPipeDebugExitWithError(); return result; }
/** * Copy the contents of a header information structure. * @ingroup globus_i_xio_http_header_info * * All values associated with the @a src header information structure will * be copied to the @a dest one. If this function returns a failure, then the * @a dest structure should be considered uninitialized. * * @param dest * Header information structure to initialize. This should not be * initialized before this function is called, or memory may be leaked. * @param src * Header information structure containing valid values. * * @retval GLOBUS_SUCCESS * Structure successfully copied. * @retval GLOBUS_XIO_ERROR_MEMORY * Copy failed due to memory constraints. */ globus_result_t globus_i_xio_http_header_info_copy( globus_i_xio_http_header_info_t * dest, const globus_i_xio_http_header_info_t * src) { int rc; globus_result_t result = GLOBUS_SUCCESS; GlobusXIOName(globus_i_xio_http_header_info_init); rc = globus_hashtable_copy( &dest->headers, (globus_hashtable_t *) &src->headers, globus_i_xio_http_header_copy); if (rc != GLOBUS_SUCCESS) { result = GlobusXIOErrorMemory("hashtable"); goto error_exit; } dest->content_length = src->content_length; dest->transfer_encoding = src->transfer_encoding; dest->flags = src->flags; return result; error_exit: return result; }
/* * copy an attribute structure */ static globus_result_t globus_l_xio_pipe_attr_copy( void ** dst, void * src) { xio_l_pipe_attr_t * attr; xio_l_pipe_attr_t * src_attr; globus_result_t result; GlobusXIOName(globus_l_xio_pipe_attr_copy); GlobusXIOPipeDebugEnter(); src_attr = (xio_l_pipe_attr_t *) src; attr = (xio_l_pipe_attr_t *) globus_malloc(sizeof(xio_l_pipe_attr_t)); if(!attr) { result = GlobusXIOErrorMemory("attr"); goto error_attr; } memcpy(attr, src_attr, sizeof(xio_l_pipe_attr_t)); *dst = attr; GlobusXIOPipeDebugExit(); return GLOBUS_SUCCESS; error_attr: GlobusXIOPipeDebugExitWithError(); return result; }
globus_result_t globus_i_xio_win32_complete( globus_callback_func_t callback, void * user_arg) { globus_l_xio_win32_poll_entry_t * entry; globus_result_t result; GlobusXIOName(globus_i_xio_win32_complete); GlobusXIOSystemDebugEnter(); if (! globus_i_am_only_thread()) { return globus_callback_register_oneshot( 0, 0, callback, user_arg); } win32_mutex_lock(&globus_l_xio_win32_poll_lock); { if(globus_l_xio_win32_poll_free) { entry = globus_l_xio_win32_poll_free; globus_l_xio_win32_poll_free = entry->next; } else { entry = (globus_l_xio_win32_poll_entry_t *) globus_malloc(sizeof(globus_l_xio_win32_poll_entry_t)); if(!entry) { result = GlobusXIOErrorMemory("entry"); goto error_malloc; } } entry->callback = callback; entry->user_arg = user_arg; GlobusLWin32PollQueueEnqueue(entry); if(globus_l_xio_win32_poll_event_sleeping && !globus_l_xio_win32_poll_event_pending) { SetEvent(globus_l_xio_win32_poll_event); globus_l_xio_win32_poll_event_pending = GLOBUS_TRUE; } } win32_mutex_unlock(&globus_l_xio_win32_poll_lock); GlobusXIOSystemDebugExit(); return GLOBUS_SUCCESS; error_malloc: return result; }
globus_result_t globus_xio_system_socket_register_connect( globus_xio_operation_t op, globus_xio_system_socket_handle_t handle, globus_sockaddr_t * addr, globus_xio_system_callback_t callback, void * user_arg) { globus_result_t result; int error; globus_i_xio_system_op_info_t * op_info; GlobusXIOName(globus_xio_system_socket_register_connect); GlobusXIOSystemDebugEnterFD(handle->socket); if(connect( handle->socket, (const struct sockaddr *) addr, GlobusLibcSockaddrLen(addr)) == SOCKET_ERROR && (error = WSAGetLastError()) != WSAEWOULDBLOCK) { result = GlobusXIOErrorSystemError("connect", error); goto error_connect; } GlobusIXIOSystemAllocOperation(op_info); if(!op_info) { result = GlobusXIOErrorMemory("op_info"); goto error_op_info; } op_info->type = GLOBUS_I_XIO_SYSTEM_OP_CONNECT; op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW; op_info->op = op; op_info->handle = handle; op_info->user_arg = user_arg; op_info->sop.non_data.callback = callback; result = globus_l_xio_win32_socket_register_write(handle, op_info); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_win32_socket_register_write", result); goto error_register; } GlobusXIOSystemDebugExitFD(handle->socket); return GLOBUS_SUCCESS; error_register: GlobusIXIOSystemFreeOperation(op_info); error_op_info: error_connect: GlobusXIOSystemDebugExitWithErrorFD(handle->socket); return result; }
/* * copy an attribute structure */ static globus_result_t globus_l_xio_popen_attr_copy( void ** dst, void * src) { xio_l_popen_attr_t * attr; xio_l_popen_attr_t * src_attr; globus_result_t result; int i; GlobusXIOName(globus_l_xio_popen_attr_copy); GlobusXIOPOpenDebugEnter(); src_attr = (xio_l_popen_attr_t *) src; attr = (xio_l_popen_attr_t *) globus_malloc(sizeof(xio_l_popen_attr_t)); if(!attr) { result = GlobusXIOErrorMemory("attr"); goto error_attr; } memcpy(attr, src_attr, sizeof(xio_l_popen_attr_t)); if(src_attr->program_name != NULL) { attr->program_name = strdup(src_attr->program_name); } if(src_attr->argc > 0) { attr->argv = (char **)globus_calloc(attr->argc+1, sizeof(char*)); for(i = 0; i < attr->argc; i++) { attr->argv[i] = strdup(src_attr->argv[i]); } attr->argv[i] = NULL; } if(src_attr->env_count > 0) { attr->env = (char **)globus_calloc(attr->env_count+1, sizeof(char*)); for(i = 0; i < attr->env_count; i++) { attr->env[i] = strdup(src_attr->env[i]); } attr->env[i] = NULL; } *dst = attr; GlobusXIOPOpenDebugExit(); return GLOBUS_SUCCESS; error_attr: GlobusXIOPOpenDebugExitWithError(); return result; }
/** Copy an HTTP attribute * @ingroup globus_i_xio_http_attr * * Copies all values associated with the @a src http attribute to * a newly allocated attribute in @a dst. If this function returns a * failure, then the @a dst should be considered uninitiailized. This is * called by the XIO driver via globus_xio_attr_copy(). * * @param dst * Void ** which will be set to point to a newly allocated attribute * with equivalent values to those in @a src. * @param src * Void * pointing to a #globus_i_xio_http_attr_t which contains the * attributes we want to copy. * * @return * This function returns GLOBUS_SUCCESS or GLOBUS_XIO_ERROR_MEMORY itself. * Other errors generated by globus_i_xio_http_request_copy() may be * returned as well. * * @retval GLOBUS_SUCCESS * Attribute successfully copied. * @retval GLOBUS_XIO_ERROR_MEMORY * Attribute copy failed due to memory constraints. */ globus_result_t globus_i_xio_http_attr_copy( void ** dst, void * src) { globus_result_t result; globus_i_xio_http_attr_t * http_dst; globus_i_xio_http_attr_t * http_src = src; GlobusXIOName(globus_i_xio_http_attr_copy); /* * Don't use globus_i_xio_http_request_init() here or the call to * globus_i_xio_http_request_copy() below will leak. */ http_dst = globus_libc_malloc(sizeof(globus_i_xio_http_attr_t)); if (http_dst == NULL) { result = GlobusXIOErrorMemory(dst); goto error_exit; } /* Copy request attrs */ result = globus_i_xio_http_request_copy( &http_dst->request, &http_src->request); if (result != GLOBUS_SUCCESS) { goto free_http_dst_exit; } /* Copy response attrs */ result = globus_i_xio_http_response_copy( &http_dst->response, &http_src->response); if (result != GLOBUS_SUCCESS) { goto free_http_dst_request_exit; } http_dst->delay_write_header = http_src->delay_write_header; *dst = http_dst; return GLOBUS_SUCCESS; free_http_dst_request_exit: globus_i_xio_http_request_destroy(&http_dst->request); free_http_dst_exit: globus_libc_free(http_dst); error_exit: return result; }
globus_result_t globus_xio_stack_copy( globus_xio_stack_t * dst, globus_xio_stack_t src) { globus_i_xio_stack_t * xio_stack_src; globus_i_xio_stack_t * xio_stack_dst; globus_result_t res; GlobusXIOName(globus_xio_stack_push_driver); GlobusXIODebugEnter(); if(dst == NULL) { res = GlobusXIOErrorParameter("dst"); goto err; } if(src == NULL) { res = GlobusXIOErrorParameter("src"); goto err; } xio_stack_src = src; xio_stack_dst = (globus_i_xio_stack_t *) globus_calloc(1, sizeof(globus_i_xio_stack_t)); /* check for memory alloc failure */ if(xio_stack_dst == NULL) { res = GlobusXIOErrorMemory("xio_stack_dst"); goto err; } xio_stack_dst->size = xio_stack_src->size; xio_stack_dst->driver_stack = globus_list_copy( xio_stack_src->driver_stack); *dst = xio_stack_dst; GlobusXIODebugExit(); return GLOBUS_SUCCESS; err: GlobusXIODebugExitWithError(); return res; }
globus_result_t globus_xio_system_socket_register_accept( globus_xio_operation_t op, globus_xio_system_socket_handle_t listener_handle, globus_xio_system_socket_t * out_handle, globus_xio_system_callback_t callback, void * user_arg) { globus_result_t result; globus_i_xio_system_op_info_t * op_info; GlobusXIOName(globus_xio_system_socket_register_accept); GlobusXIOSystemDebugEnterFD(listener_handle->socket); GlobusIXIOSystemAllocOperation(op_info); if(!op_info) { result = GlobusXIOErrorMemory("op_info"); goto error_op_info; } op_info->type = GLOBUS_I_XIO_SYSTEM_OP_ACCEPT; op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW; op_info->op = op; op_info->handle = listener_handle; op_info->user_arg = user_arg; op_info->sop.non_data.callback = callback; op_info->sop.non_data.out_fd = out_handle; op_info->waitforbytes = 1; result = globus_l_xio_win32_socket_register_read(listener_handle, op_info); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_win32_socket_register_read", result); goto error_register; } GlobusXIOSystemDebugExitFD(listener_handle->socket); return GLOBUS_SUCCESS; error_register: GlobusIXIOSystemFreeOperation(op_info); error_op_info: GlobusXIOSystemDebugExitWithErrorFD(listener_handle->socket); return result; }
/** * Copy the contents of an HTTP response * @ingroup globus_i_xio_http_response * * All values associated with the @a src response will be copied * to the corresponding fields of the @a dest response. If this function * returns a failure, then the @a dest should be considered uninitialized. * * @param dest * Response to be initialized with values from src. This should * not be initialized before this is called, or memory may be * leaked. * @param src * Response containing known values. * * @retval GLOBUS_SUCCESS * Response successfully copied. * @retval GLOBUS_XIO_ERROR_MEMORY * Response copy failed due to memory constraints. */ globus_result_t globus_i_xio_http_response_copy( globus_i_xio_http_response_t * dest, const globus_i_xio_http_response_t *src) { globus_result_t res = GLOBUS_SUCCESS; GlobusXIOName(globus_i_xio_http_response_copy); dest->status_code = src->status_code; if (src->reason_phrase == NULL) { dest->reason_phrase = NULL; } else { dest->reason_phrase = globus_libc_strdup(src->reason_phrase); if (dest->reason_phrase == NULL) { res = GlobusXIOErrorMemory("reason_phrase"); goto error_exit; } } dest->http_version = src->http_version; res = globus_i_xio_http_header_info_copy( &dest->headers, &src->headers); if (res != GLOBUS_SUCCESS) { goto free_reason_phrase_exit; } return res; free_reason_phrase_exit: if (dest->reason_phrase != NULL) { globus_libc_free(dest->reason_phrase); dest->reason_phrase = NULL; } error_exit: return res; }
/** * Allocate and initialize an HTTP attribute * @ingroup globus_i_xio_http_attr * * Creates a new attribute with default values. This is called by the XIO * driver via globus_xio_attr_init(). * * @param out_attr * Pointer value will be set to point to a * newly allocated and initilized #globus_i_xio_http_attr_t * structure. * * @retval GLOBUS_SUCCESS * Attribute successfully initialized. * @retval GLOBUS_XIO_ERROR_MEMORY * Initialization failed due to memory constraints. * * @see globus_i_xio_http_attr_destroy() */ globus_result_t globus_i_xio_http_attr_init( void ** out_attr) { globus_result_t res; globus_i_xio_http_attr_t * attr; GlobusXIOName(globus_i_xio_http_attr_init); attr = globus_libc_malloc(sizeof(globus_i_xio_http_attr_t)); if (attr == NULL) { res = GlobusXIOErrorMemory("attr"); goto error_exit; } res = globus_i_xio_http_request_init(&attr->request); if (res != GLOBUS_SUCCESS) { goto free_attr_exit; } res = globus_i_xio_http_response_init(&attr->response); if (res != GLOBUS_SUCCESS) { goto free_request_exit; } attr->delay_write_header = GLOBUS_FALSE; *out_attr = attr; return GLOBUS_SUCCESS; free_request_exit: globus_i_xio_http_request_destroy(&attr->request); free_attr_exit: globus_libc_free(attr); error_exit: return res; }
/** * Accept callback * @ingroup globus_i_xio_http_server * * Callback function called when the transport completes accepting * a connection for the request. Generates a new target to associate with * the result of this accept. This target will be passed to * globus_xio_open() or globus_xio_register_open() to begin processing the * request. * * @param op * XIO Data structure passed through to globus_xio_driver_finished_accept(). * @param result * Result from the transport's attempt to accept a new connection. * @param user_arg * Not used. * * @return void * * @todo When implemented in the XIO driver framework, parse the request * header before returning from this, so the target is populated with * meaningful information for the user. This will help enable persistent * connections. */ static void globus_l_xio_http_accept_callback( globus_xio_operation_t op, globus_result_t result, void * user_arg) { globus_i_xio_http_target_t * target_info = NULL; GlobusXIOName(globus_l_xio_http_accept_callback); if (result == GLOBUS_SUCCESS) { target_info = globus_i_xio_http_target_new(); if (target_info == NULL) { result = GlobusXIOErrorMemory("target"); } } globus_xio_driver_finished_accept(op, target_info, result); }
static globus_result_t globus_l_xio_win32_blocking_init( globus_l_xio_win32_blocking_info_t ** u_blocking_info) { globus_l_xio_win32_blocking_info_t * blocking_info; globus_result_t result; GlobusXIOName(globus_l_xio_win32_blocking_init); GlobusXIOSystemDebugEnter(); blocking_info = (globus_l_xio_win32_blocking_info_t *) globus_calloc(1, sizeof(globus_l_xio_win32_blocking_info_t)); if(!blocking_info) { result = GlobusXIOErrorMemory("blocking_info"); goto error_info; } blocking_info->event = CreateEvent(0, FALSE, FALSE, 0); if(blocking_info->event == 0) { result = GlobusXIOErrorSystemError( "CreateEvent", GetLastError()); goto error_create; } *u_blocking_info = blocking_info; GlobusXIOSystemDebugExit(); return GLOBUS_SUCCESS; error_create: globus_free(blocking_info); error_info: *u_blocking_info = 0; GlobusXIOSystemDebugExitWithError(); return result; }
/** * Initialize an HTTP header info structure * @ingroup globus_i_xio_http_header_info * * All fields of the @a header_info structure will be initialized to their * default values. If this function returns a failre, the header_info * should be considered uninitialized. * * @param header_info * Header information structure to initialize. * * @retval GLOBUS_SUCCESS * Header initialized successfully. * @retval GLOBUS_XIO_ERROR_MEMORY * Initialization failed due to memory constraints. */ globus_result_t globus_i_xio_http_header_info_init( globus_i_xio_http_header_info_t * header_info) { int rc; globus_result_t result = GLOBUS_SUCCESS; GlobusXIOName(globus_i_xio_http_header_info_init); memset(header_info, '\0', sizeof(globus_i_xio_http_header_info_t)); rc = globus_hashtable_init( &header_info->headers, 16, globus_hashtable_string_hash, globus_hashtable_string_keyeq); if (rc != GLOBUS_SUCCESS) { result = GlobusXIOErrorMemory("hashtable"); } return result; }
static globus_result_t globus_l_xio_telnet_attr_init( void ** out_driver_attr) { globus_l_xio_telnet_attr_t * attr; globus_result_t res; GlobusXIOName(globus_l_xio_telnet_attr_init); attr = (globus_l_xio_telnet_attr_t *) globus_calloc(sizeof(globus_l_xio_telnet_attr_t), 1); if(!attr) { res = GlobusXIOErrorMemory("attr"); goto error; } *out_driver_attr = attr; return GLOBUS_SUCCESS; error: return res; }
/** * Modify the state of an HTTP attribute * @ingroup globus_i_xio_http_attr * * Modify the state of an attribute. This is called by the XIO driver via * globus_xio_attr_cntl(). * * @param driver_attr * Void pointer to a #globus_i_xio_http_attr_t structure containing * the attribute's values. * @param cmd * Integer value indicating which attribute will be changed. Valid * commands values are in the set defined by #globus_xio_http_attr_cmd_t * @param ap * Variable-length argument list containing any cmd-specific parameters. * * @retval GLOBUS_SUCCESS * Attribute successfully modified. * @retval GLOBUS_XIO_ERROR_MEMORY * Attribute control failed due to memory constraints. * @retval GLOBUS_XIO_ERROR_PARAMETER * Invalid @a cmd parameter or invalid value for cmd-specific parameters * in @a ap. */ globus_result_t globus_i_xio_http_attr_cntl( void * driver_attr, int cmd, va_list ap) { globus_result_t res = GLOBUS_SUCCESS; globus_i_xio_http_attr_t * attr = driver_attr; char * in_string; char * save_string; globus_xio_http_version_t in_http_version; char * in_header_name; char * in_header_value; char ** out_method; char ** out_uri; globus_xio_http_version_t * out_http_version; globus_hashtable_t * out_headers; int * out_status_code; char ** out_reason_phrase; GlobusXIOName(globus_i_xio_http_attr_cntl); switch (cmd) { case GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_METHOD: save_string = attr->request.method; in_string = va_arg(ap, char *); if (in_string == NULL) { res = GlobusXIOErrorParameter("method"); break; } attr->request.method = globus_libc_strdup(in_string); if (attr->request.method == NULL) { attr->request.method = save_string; res = GlobusXIOErrorMemory("method"); break; } if (save_string != NULL) { globus_libc_free(save_string); } break; case GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HTTP_VERSION: in_http_version = va_arg(ap, globus_xio_http_version_t); if (in_http_version != GLOBUS_XIO_HTTP_VERSION_1_0 && in_http_version != GLOBUS_XIO_HTTP_VERSION_1_1) { res = GlobusXIOErrorParameter("version"); break; } attr->request.http_version = in_http_version; break; case GLOBUS_XIO_HTTP_ATTR_SET_REQUEST_HEADER: in_header_name = va_arg(ap, char *); if (in_header_name == NULL) { res = GlobusXIOErrorParameter("name"); break; } in_header_value = va_arg(ap, char *); if (in_header_value == NULL) { res = GlobusXIOErrorParameter("value"); break; } res = globus_i_xio_http_header_info_set_header( &attr->request.headers, in_header_name, in_header_value, GLOBUS_FALSE); break; case GLOBUS_XIO_HTTP_ATTR_DELAY_WRITE_HEADER: attr->delay_write_header = 1; break; case GLOBUS_XIO_HTTP_GET_REQUEST: out_method = va_arg(ap, char **); out_uri = va_arg(ap, char **); out_http_version = va_arg(ap, globus_xio_http_version_t *); out_headers = va_arg(ap, globus_hashtable_t *); if (out_method != NULL) { *out_method = attr->request.method; } if (out_uri != NULL) { *out_uri = attr->request.uri; } if (out_http_version != NULL) { *out_http_version = attr->request.http_version; } if (out_headers != NULL) { *out_headers = attr->request.headers.headers; } break; case GLOBUS_XIO_HTTP_GET_RESPONSE: out_status_code = va_arg(ap, int *); out_reason_phrase = va_arg(ap, char **); out_http_version = va_arg(ap, globus_xio_http_version_t *); out_headers = va_arg(ap, globus_hashtable_t *); if (out_status_code != NULL) { *out_status_code = attr->response.status_code; } if (out_reason_phrase != NULL) { *out_reason_phrase = attr->response.reason_phrase; } if (out_http_version != NULL) { *out_http_version = attr->response.http_version; } if (out_headers != NULL) { *out_headers = attr->response.headers.headers; } break; default: res = GlobusXIOErrorParameter("cmd"); } return res; }
/** * Set the value of a header in a hashtable * @ingroup globus_i_xio_http_header * * Adds a new header to a header info structure, or updates the value of an * existing header. Copies of the name and value will be stored in a * #globus_xio_http_header_t in a hashtable in the header info structure. * * @param headers * Pointer to the header info structure. * @param header_name * Name of the header. * @param header_value * Value of the header. * * @retval GLOBUS_SUCCESS * Header successfully added to the hashtable. * @retval GLOBUS_XIO_ERROR_MEMORY * Unable to add header due to memory constraints. */ globus_result_t globus_i_xio_http_header_info_set_header( globus_i_xio_http_header_info_t * headers, const char * header_name, const char * header_value) { char * save_header; globus_result_t result = GLOBUS_SUCCESS; globus_xio_http_header_t * header; int rc; unsigned long length; GlobusXIOName(globus_l_xio_http_header_set); /* Special cases for entity-body handling headers */ if (strcmp(header_name, "Content-Length") == 0) { rc = sscanf(header_value, "%lu", &length); if (rc < 1) { result = GlobusXIOHttpErrorInvalidHeader(header_name, header_value); goto error_exit; } headers->content_length = length; headers->flags |= GLOBUS_I_XIO_HTTP_HEADER_CONTENT_LENGTH_SET; } else if (strcmp(header_name, "Transfer-Encoding") == 0) { if (strcmp(header_value, "identity") == 0) { headers->transfer_encoding = GLOBUS_XIO_HTTP_TRANSFER_ENCODING_IDENTITY; } else if (strcmp(header_value, "chunked") == 0) { headers->transfer_encoding = GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED; } else { result = GlobusXIOHttpErrorInvalidHeader(header_name, header_value); goto error_exit; } } else if (strcmp(header_name, "Connection") == 0) { if (strcmp(header_value, "close") == 0) { headers->flags |= GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE; } else if (strcmp(header_value, "keep-alive") == 0) { headers->flags &= ~GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE; } else { result = GlobusXIOHttpErrorInvalidHeader(header_name, header_value); goto error_exit; } } else { /* * Either modify the header's value in the hashtable, if it's a * duplicate, or create a new entry in the hashtable */ header = globus_hashtable_lookup( &headers->headers, (void *) header_name); if (header != NULL) { /* Replace current header's value */ save_header = header->value; header->value = globus_libc_strdup(header_value); if (header->value == NULL) { header->value = save_header; result = GlobusXIOErrorMemory("header"); goto error_exit; } globus_libc_free(save_header); } else { header = globus_libc_malloc(sizeof(globus_xio_http_header_t)); if (header == NULL) { result = GlobusXIOErrorMemory("header"); goto error_exit; } header->name = globus_libc_strdup(header_name); if (header->name == NULL) { result = GlobusXIOErrorMemory("header"); goto free_header_exit; } header->value = globus_libc_strdup(header_value); if (header->value == NULL) { result = GlobusXIOErrorMemory("header"); goto free_header_name_exit; } rc = globus_hashtable_insert( &headers->headers, header->name, header); if (rc != GLOBUS_SUCCESS) { result = GlobusXIOErrorMemory("header"); goto free_header_value_exit; } } } return result; free_header_value_exit: globus_libc_free(header->value); free_header_name_exit: globus_libc_free(header->name); free_header_exit: globus_libc_free(header); error_exit: return result; }
/** * Modify the state of an HTTP handle * @ingroup globus_i_xio_http_handle * * Modify the state of an HTTP handle. This is called by the XIO driver via * globus_xio_handle_cntl(). * * @param handle * Void pointer to a #globus_i_xio_http_handle_t structure containing * information an HTTP request/response transaction. * @param cmd * Integer value indicating what command will be executed on the handle. * Valid command values are in the set defined by * #globus_xio_http_handle_cmd_t. * @param ap * Variable-length argument list containing any cmd-specific parameters. * * @retval GLOBUS_SUCCESS * The command was sucessfully executed. * @retval GLOBUS_XIO_ERROR_MEMORY * The command failed due to memory constraints. * @retval GLOBUS_XIO_ERROR_PARAMETER * Invalid @a cmd parameter or invlaid value of cmd-specific parameters * in @a ap */ globus_result_t globus_i_xio_http_handle_cntl( void * handle, int cmd, va_list ap) { char * in_header_name; char * in_header_value; globus_result_t result = GLOBUS_SUCCESS; globus_i_xio_http_handle_t * http_handle = handle; char * in_str; char * in_str2; char * save_str; int in_int; GlobusXIOName(globus_i_xio_http_handle_cntl); globus_mutex_lock(&http_handle->mutex); switch (cmd) { case GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HEADER: if (http_handle->target_info.is_client) { result = GlobusXIOErrorParameter("handle"); break; } if (http_handle->send_state != GLOBUS_XIO_HTTP_STATUS_LINE) { result = GlobusXIOErrorParameter("handle"); break; } in_str = va_arg(ap, char *); in_str2 = va_arg(ap, char *); result = globus_i_xio_http_header_info_set_header( &http_handle->response_info.headers, in_str, in_str2); break; case GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_STATUS_CODE: if (http_handle->target_info.is_client) { result = GlobusXIOErrorParameter("handle"); break; } if (http_handle->send_state != GLOBUS_XIO_HTTP_STATUS_LINE) { result = GlobusXIOErrorParameter("handle"); break; } in_int = va_arg(ap, int); if (in_int < 100 || in_int > 599) { result = GlobusXIOErrorParameter("status_code"); break; } http_handle->response_info.status_code = in_int; break; case GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_REASON_PHRASE: if (http_handle->target_info.is_client) { result = GlobusXIOErrorParameter("handle"); break; } if (http_handle->send_state != GLOBUS_XIO_HTTP_STATUS_LINE) { result = GlobusXIOErrorParameter("handle"); break; } in_str = va_arg(ap, char *); if (in_str == NULL) { result = GlobusXIOErrorParameter("reason_phrase"); } save_str = http_handle->response_info.reason_phrase; http_handle->response_info.reason_phrase = globus_libc_strdup(in_str); if (http_handle->response_info.reason_phrase == NULL) { result = GlobusXIOErrorMemory("reason_phrase"); break; } if (save_str) { globus_libc_free(save_str); } break; case GLOBUS_XIO_HTTP_HANDLE_SET_RESPONSE_HTTP_VERSION: if (http_handle->target_info.is_client) { result = GlobusXIOErrorParameter("handle"); break; } if (http_handle->send_state != GLOBUS_XIO_HTTP_STATUS_LINE) { result = GlobusXIOErrorParameter("handle"); break; } http_handle->response_info.http_version = va_arg(ap, globus_xio_http_version_t); break; case GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY: result = globus_i_xio_http_set_end_of_entity(http_handle); break; case GLOBUS_XIO_HTTP_HANDLE_SET_REQUEST_HEADER: in_header_name = va_arg(ap, char *); if (in_header_name == NULL) { result = GlobusXIOErrorParameter("name"); break; } in_header_value = va_arg(ap, char *); if (in_header_value == NULL) { result = GlobusXIOErrorParameter("value"); break; } result = globus_i_xio_http_header_info_set_header( &http_handle->request_info.headers, in_header_name, in_header_value); break; default: result = GlobusXIOErrorParameter("cmd"); break; } globus_mutex_unlock(&http_handle->mutex); return result; }
static globus_result_t globus_l_xio_telnet_open( const globus_xio_contact_t * contact_info, void * driver_link, void * driver_attr, globus_xio_operation_t op) { globus_result_t res; globus_l_xio_telnet_attr_t * attr; globus_l_xio_telnet_handle_t * handle; GlobusXIOName(globus_l_xio_telnet_open); /* decide what attr to use */ if(driver_attr != NULL) { attr = (globus_l_xio_telnet_attr_t *) driver_attr; } else if(driver_link != NULL) { attr = (globus_l_xio_telnet_attr_t *) driver_link; } else { /* default */ attr = NULL; } handle = (globus_l_xio_telnet_handle_t *) globus_calloc( sizeof(globus_l_xio_telnet_handle_t), 1); if(handle == NULL) { res = GlobusXIOErrorMemory("handle"); goto error_handle_alloc; } if(attr != NULL && attr->force_server) { handle->client = GLOBUS_FALSE; } else { handle->client = driver_link ? GLOBUS_FALSE : GLOBUS_TRUE; } handle->read_buffer_length = GLOBUS_L_XIO_TELNET_DEFAULT_BUFFER_SIZE; handle->read_buffer = globus_malloc(handle->read_buffer_length); if(handle->read_buffer == NULL) { res = GlobusXIOErrorMemory("buffer"); goto error_buffer_alloc; } globus_mutex_init(&handle->mutex, NULL); globus_fifo_init(&handle->write_q); handle->create_buffer_mode = attr ? attr->create_buffer_mode : GLOBUS_FALSE; res = globus_xio_driver_pass_open( op, contact_info, globus_l_xio_telnet_open_cb, handle); if(res != GLOBUS_SUCCESS) { goto error_pass; } return GLOBUS_SUCCESS; error_pass: globus_free(handle->read_buffer); globus_mutex_destroy(&handle->mutex); globus_fifo_destroy(&handle->write_q); error_buffer_alloc: globus_free(handle); error_handle_alloc: return res; }
/* if waitforbytes == 0 and iov[0].iov_len == 0 * behave like select()... ie notify when data ready */ globus_result_t globus_l_xio_system_socket_register_read( globus_xio_operation_t op, globus_xio_system_socket_handle_t handle, const globus_xio_iovec_t * u_iov, int u_iovc, globus_size_t waitforbytes, globus_size_t nbytes, int flags, globus_sockaddr_t * out_from, globus_xio_system_data_callback_t callback, void * user_arg) { globus_result_t result; globus_i_xio_system_op_info_t * op_info; struct iovec * iov; int iovc; GlobusXIOName(globus_l_xio_system_socket_register_read); GlobusXIOSystemDebugEnterFD(handle->socket); GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Waiting for %ld bytes\n", _xio_name, (long) waitforbytes)); GlobusIXIOSystemAllocOperation(op_info); if(!op_info) { result = GlobusXIOErrorMemory("op_info"); goto error_op_info; } GlobusIXIOSystemAllocIovec(u_iovc, iov); if(!iov) { result = GlobusXIOErrorMemory("iov"); goto error_iovec; } GlobusIXIOUtilTransferIovec(iov, u_iov, u_iovc); iovc = u_iovc; op_info->type = GLOBUS_I_XIO_SYSTEM_OP_READ; op_info->sop.data.start_iov = iov; op_info->sop.data.start_iovc = iovc; GlobusIXIOUtilAdjustIovec(iov, iovc, nbytes); op_info->sop.data.iov = iov; op_info->sop.data.iovc = iovc; op_info->sop.data.addr = out_from; op_info->sop.data.flags = flags; op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW; op_info->op = op; op_info->handle = handle; op_info->user_arg = user_arg; op_info->sop.data.callback = callback; op_info->waitforbytes = waitforbytes; op_info->nbytes = nbytes; result = globus_l_xio_win32_socket_register_read(handle, op_info); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_win32_socket_register_read", result); goto error_register; } GlobusXIOSystemDebugExitFD(handle->socket); return GLOBUS_SUCCESS; error_register: GlobusIXIOSystemFreeIovec(u_iovc, op_info->sop.data.start_iov); error_iovec: GlobusIXIOSystemFreeOperation(op_info); error_op_info: GlobusXIOSystemDebugExitWithErrorFD(handle->socket); return result; }
/** * Write the response to an HTTP request * @ingroup globus_i_xio_http_server * * Generates an HTTP response line from a handle, and passes it to the * transport. The globus_l_xio_http_server_write_response_callback() will * be called once the transport has sent the response. * * This call may be triggered by either the first write on a server handle, * or by calling the #GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY handle * control function. * * Called with my mutex lock. * * @param http_handle * Handle associated with this HTTP stream. * @param iovec * Array of globus_xio_iovec_t structs associated with the user's write. * @param iovec_count * Length of the @a iovec array. If this is zero, we assume that the * response is being generated by the * #GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY control. * @param op * Operation associated with the write. If this is NULL (in the case * of the GLOBUS_XIO_HTTP_HANDLE_SET_END_OF_ENTITY control), one * will be created in this function. * * This function returns GLOBUS_SUCCESS, GLOBUS_XIO_ERROR_MEMORY, or an * error result from globus_xio_driver_operation_create(), or * globus_xio_driver_pass_write(). * * @retval GLOBUS_SUCCESS * Response was passed to the transport for writing. If this was generated * by a user writing data, then the write will occur after the * globus_l_xio_http_server_write_response_callback() has been called. * @retval GLOBUS_XIO_ERROR_MEMORY * Unable to compose the response due to memory constraints. */ globus_result_t globus_i_xio_http_server_write_response( globus_i_xio_http_handle_t * http_handle, const globus_xio_iovec_t * iovec, int iovec_count, globus_xio_operation_t op) { globus_result_t result; globus_fifo_t iovecs; const char * str; char code_str[5]; globus_xio_iovec_t * iov; int rc; int i; int send_size; char * size_buffer = NULL; globus_bool_t free_op = GLOBUS_FALSE; globus_xio_http_header_t * current_header; GlobusXIOName(globus_i_xio_server_write_response); globus_assert(http_handle->send_state == GLOBUS_XIO_HTTP_STATUS_LINE); rc = globus_fifo_init(&iovecs); if (rc != GLOBUS_SUCCESS) { result = GlobusXIOErrorMemory("iovecs"); goto error_exit; } /* Compose HTTP Response: * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ if (http_handle->response_info.http_version == GLOBUS_XIO_HTTP_VERSION_1_0) { str = "HTTP/1.0 "; } else { http_handle->response_info.http_version = GLOBUS_XIO_HTTP_VERSION_1_1; str = "HTTP/1.1 "; } GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, str, 9, free_iovecs_error); sprintf(code_str, "%d ", http_handle->response_info.status_code); GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, code_str, 4, free_iovecs_error); if (http_handle->response_info.reason_phrase != NULL) { str = http_handle->response_info.reason_phrase; } else { str = globus_i_xio_http_lookup_reason( http_handle->response_info.status_code); } GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, str, strlen(str), free_iovecs_error); GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "\r\n", 2, free_iovecs_error); current_header = globus_hashtable_first( &http_handle->response_info.headers.headers); while (current_header) { GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, current_header->name, strlen(current_header->name), free_iovecs_error); GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, ": ", 2, free_iovecs_error); GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, current_header->value, strlen(current_header->value), free_iovecs_error); GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "\r\n", 2, free_iovecs_error); current_header = globus_hashtable_next( &http_handle->response_info.headers.headers); } /* * Special headers we generate. */ if (GLOBUS_I_XIO_HTTP_HEADER_IS_CONNECTION_CLOSE( &http_handle->response_info.headers) || (http_handle->request_info.http_version == GLOBUS_XIO_HTTP_VERSION_1_0) || (http_handle->response_info.headers.transfer_encoding == GLOBUS_XIO_HTTP_TRANSFER_ENCODING_IDENTITY && GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET( &http_handle->response_info.headers))) { http_handle->response_info.headers.flags |= GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE; GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "Connection: close\r\n", 19, free_iovecs_error); } if (iovec_count > 0) { /* * We are sending a body, so we'll set the appropriate entity-related * headers */ if (http_handle->request_info.http_version == GLOBUS_XIO_HTTP_VERSION_1_0 || (http_handle->response_info.headers.transfer_encoding == GLOBUS_XIO_HTTP_TRANSFER_ENCODING_IDENTITY && GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET( &http_handle->response_info.headers))) { http_handle->response_info.headers.transfer_encoding = GLOBUS_XIO_HTTP_TRANSFER_ENCODING_IDENTITY; /* Transfer-Encoding mustn't be sent to a HTTP/1.0 client */ if (http_handle->request_info.http_version != GLOBUS_XIO_HTTP_VERSION_1_0) { GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "Transfer-Encoding: identity\r\n", 29, free_iovecs_error); } /* * When we know the content-length beforehand we can set it here, * otherwise, we will use the connection: close header */ if (GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET( &http_handle->response_info.headers)) { GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "Content-Length: ", 16, free_iovecs_error); size_buffer = globus_common_create_string( "%lu\r\n", (unsigned long) http_handle->response_info.headers.content_length); if (size_buffer == NULL) { result = GlobusXIOErrorMemory("iovec.iov_base"); goto free_iovecs_error; } GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, size_buffer, strlen(size_buffer), free_iovecs_error); free(size_buffer); size_buffer = NULL; } } else { http_handle->response_info.headers.transfer_encoding = GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED; GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "Transfer-Encoding: chunked\r\n", 28, free_iovecs_error); } } GLOBUS_XIO_HTTP_COPY_BLOB(&iovecs, "\r\n", 2, free_iovecs_error); http_handle->header_iovcnt = globus_fifo_size(&iovecs); http_handle->header_iovec = globus_libc_malloc( http_handle->header_iovcnt * sizeof(globus_xio_iovec_t)); if (http_handle->header_iovec == NULL) { goto free_iovecs_error; } /* Convert fifo to iovec array, counting up size for wait_for_nbytes * parameter to globus_xio_driver_pass_write. */ for (i = 0, send_size = 0; i < http_handle->header_iovcnt; i++) { iov = globus_fifo_dequeue(&iovecs); globus_assert(iov != NULL); http_handle->header_iovec[i].iov_base = iov->iov_base; http_handle->header_iovec[i].iov_len = iov->iov_len; send_size += iov->iov_len; globus_libc_free(iov); } if (op == NULL) { result = globus_xio_driver_operation_create( &op, http_handle->handle); free_op = GLOBUS_TRUE; if (result != GLOBUS_SUCCESS) { goto free_headers_exit; } } /* Stash user buffer info until we've sent response headers */ http_handle->write_operation.operation = op; http_handle->write_operation.iov = (globus_xio_iovec_t *) iovec; http_handle->write_operation.iovcnt = iovec_count; http_handle->write_operation.wait_for = 0; result = globus_xio_driver_pass_write( http_handle->write_operation.operation, http_handle->header_iovec, http_handle->header_iovcnt, send_size, globus_l_xio_http_server_write_response_callback, http_handle); if (result != GLOBUS_SUCCESS) { goto free_operation_exit; } globus_fifo_destroy(&iovecs); if (iovec_count == 0) { http_handle->send_state = GLOBUS_XIO_HTTP_EOF; } else if (http_handle->response_info.headers.transfer_encoding == GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED) { http_handle->send_state = GLOBUS_XIO_HTTP_CHUNK_BODY; } else { http_handle->send_state = GLOBUS_XIO_HTTP_IDENTITY_BODY; } return GLOBUS_SUCCESS; free_operation_exit: if (free_op) { globus_xio_driver_operation_destroy( http_handle->write_operation.operation); } free_headers_exit: http_handle->write_operation.operation = NULL; http_handle->write_operation.driver_handle = NULL; http_handle->write_operation.iov = NULL; http_handle->write_operation.iovcnt = 0; http_handle->write_operation.wait_for = 0; for (i = 0; i < http_handle->header_iovcnt; i++) { globus_libc_free(http_handle->header_iovec[i].iov_base); } globus_libc_free(http_handle->header_iovec); http_handle->header_iovec = NULL; http_handle->header_iovcnt = 0; free_iovecs_error: while (!globus_fifo_empty(&iovecs)) { iov = globus_fifo_dequeue(&iovecs); globus_libc_free(iov->iov_base); globus_libc_free(iov); } globus_fifo_destroy(&iovecs); if (size_buffer != NULL) { free(size_buffer); } error_exit: return result; }
/** * Parse an HTTP request * @ingroup globus_i_xio_http_server * * Parses the HTTP request line and then uses globus_i_xio_http_header_parse() * to parse the header bock .If the entire request header section is reqad, the * boolean pointed to by @a done will be modified to be GLOBUS_TRUE * * Called with mutex locked. * * @param http_handle * @param done * * @return * This function returns GLOBUS_SUCCESS, GLOBUS_XIO_HTTP_ERROR_PARSE, or * GLOBUS_XIO_ERROR_MEMORY. Other errors may be generated from * globus_i_xio_http_header_parse() * * @retval GLOBUS_SUCCESS * No parsing errors occurred while parsing the status line or headers. * Parsing may still be incomplete, depending on the final value of @a * done. * @retval <driver>::GLOBUS_XIO_HTTP_ERROR_PARSE * Parse error reading the HTTP request line * @retval GLOBUS_XIO_ERROR_MEMORY * Parsing failed because of memory constraints. */ static globus_result_t globus_l_xio_http_server_parse_request( globus_i_xio_http_handle_t * http_handle, globus_bool_t * done) { globus_result_t result; char * eol; char * current_offset; int parsed; int rc; int http_major; int http_minor; GlobusXIOName(globus_l_xio_http_server_parse_request); if (http_handle->parse_state == GLOBUS_XIO_HTTP_REQUEST_LINE) { /* * Make sure any old request info has been freed so we don't leak here * when reusing a handle (or have old headers around) */ globus_i_xio_http_request_destroy(&http_handle->request_info); result = globus_i_xio_http_request_init(&http_handle->request_info); if (result != GLOBUS_SUCCESS) { goto error_exit_init; } /* Parse the request line: * * Method SP Request-URI SP HTTP-Version CRLF */ current_offset = ((char *) (http_handle->read_buffer.iov_base)) + http_handle->read_buffer_offset; eol = globus_i_xio_http_find_eol( current_offset, http_handle->read_buffer_valid); if (eol == NULL) { *done = GLOBUS_FALSE; return GLOBUS_SUCCESS; } *eol = '\0'; rc = sscanf(current_offset, "%*s %n", &parsed); if (rc < 0) { result = GlobusXIOHttpErrorParse("Method", current_offset); goto error_exit; } http_handle->request_info.method = globus_libc_malloc(parsed+1); if (http_handle->request_info.method == NULL) { result = GlobusXIOErrorMemory("method"); goto error_exit; } rc = sscanf(current_offset, "%s ", http_handle->request_info.method); globus_assert(rc == 1); current_offset += parsed; rc = sscanf(current_offset, "%*s %n", &parsed); if (rc < 0) { result = GlobusXIOHttpErrorParse("Request-URI", current_offset); goto error_exit; } http_handle->request_info.uri = globus_libc_malloc(parsed+1); if (http_handle->request_info.uri == NULL) { result = GlobusXIOErrorMemory("uri"); goto error_exit; } rc = sscanf(current_offset, "%s ", http_handle->request_info.uri); globus_assert(rc == 1); current_offset += parsed; rc = sscanf(current_offset, "HTTP/%d.%d", &http_major, &http_minor); if (rc < 2) { result = GlobusXIOHttpErrorParse("Http-Version", current_offset); goto error_exit; } http_handle->request_info.http_version = globus_i_xio_http_guess_version(http_major, http_minor); /* Set current offset to end of CRLF at the end of this line */ current_offset = eol+2; parsed = current_offset - ((char *) http_handle->read_buffer.iov_base + http_handle->read_buffer_offset); http_handle->read_buffer_valid -= parsed; http_handle->read_buffer_offset += parsed; http_handle->parse_state = GLOBUS_XIO_HTTP_HEADERS; } return globus_i_xio_http_header_parse(http_handle, done); error_exit: parsed = current_offset - ((char *) http_handle->read_buffer.iov_base + http_handle->read_buffer_offset); /* Chop of what we managed to parse from the buffer */ http_handle->read_buffer_valid -= parsed; http_handle->read_buffer_offset += parsed; error_exit_init: return result; }
globus_result_t globus_xio_data_descriptor_init( globus_xio_data_descriptor_t * data_desc, globus_xio_handle_t handle) { globus_result_t res = GLOBUS_SUCCESS; globus_i_xio_op_t * op; globus_i_xio_context_t * context; GlobusXIOName(globus_xio_data_descriptor_init); GlobusXIODebugEnter(); if(data_desc == NULL) { res = GlobusXIOErrorParameter("data_desc"); goto err_parm; } if(handle == NULL) { res = GlobusXIOErrorParameter("handle"); goto err; } context = handle->context; globus_mutex_lock(&context->mutex); { GlobusXIOOperationCreate(op, context); if(op != NULL) { op->type = GLOBUS_XIO_OPERATION_TYPE_DD; handle->ref++; GlobusXIODebugPrintf( GLOBUS_XIO_DEBUG_INFO_VERBOSE, (_XIOSL("[globus_xio_data_descriptor_init] :: handle ref at %d.\n"), handle->ref)); op->_op_handle = handle; op->ref = 1; op->is_user_dd = GLOBUS_TRUE; } else { res = GlobusXIOErrorMemory("xio_dd"); } } globus_mutex_unlock(&context->mutex); if(res != GLOBUS_SUCCESS) { goto err; } *data_desc = op; globus_mutex_lock(&globus_i_xio_mutex); { globus_list_insert(&globus_i_xio_outstanding_dds_list, op); } globus_mutex_unlock(&globus_i_xio_mutex); GlobusXIODebugExit(); return GLOBUS_SUCCESS; err: *data_desc = NULL; err_parm: GlobusXIODebugExitWithError(); return res; }
void globus_i_xio_http_server_read_request_callback( globus_xio_operation_t op, globus_result_t result, globus_size_t nbytes, void * user_arg) { globus_i_xio_http_handle_t * http_handle = user_arg; globus_bool_t done; globus_result_t eof_result = GLOBUS_SUCCESS; globus_i_xio_http_attr_t * descriptor; globus_bool_t registered_again = GLOBUS_FALSE; GlobusXIOName(globus_i_xio_http_server_read_request_callback); globus_mutex_lock(&http_handle->mutex); if (result != GLOBUS_SUCCESS) { if (globus_xio_error_is_eof(result)) { eof_result = result; } else { goto error_exit; } } /* Haven't parsed request and headers yet */ http_handle->read_buffer_valid += nbytes; result = globus_l_xio_http_server_parse_request(http_handle, &done); if (result == GLOBUS_SUCCESS && !done) { goto reregister_read; } else if (result != GLOBUS_SUCCESS) { goto error_exit; } /* Determine whether we should expect an entity along with the * request */ if ((http_handle->request_info.http_version == GLOBUS_XIO_HTTP_VERSION_1_1) && (http_handle->request_info.headers.transfer_encoding == GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED)) { http_handle->parse_state = GLOBUS_XIO_HTTP_CHUNK_LINE; } else if (GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET( &http_handle->request_info.headers)) { http_handle->parse_state = GLOBUS_XIO_HTTP_IDENTITY_BODY; } if (GLOBUS_I_XIO_HTTP_HEADER_IS_CONNECTION_CLOSE( &http_handle->request_info.headers)) { http_handle->response_info.headers.flags |= GLOBUS_I_XIO_HTTP_HEADER_CONNECTION_CLOSE; } http_handle->send_state = GLOBUS_XIO_HTTP_STATUS_LINE; descriptor = globus_xio_operation_get_data_descriptor(op, GLOBUS_TRUE); if (descriptor == NULL) { result = GlobusXIOErrorMemory("descriptor"); goto error_exit; } globus_i_xio_http_request_destroy(&descriptor->request); result = globus_i_xio_http_request_copy( &descriptor->request, &http_handle->request_info); if (result != GLOBUS_SUCCESS) { goto error_exit; } result = globus_i_xio_http_parse_residue(http_handle, ®istered_again); if ((http_handle->read_operation.wait_for <= 0 && !registered_again) || result != GLOBUS_SUCCESS) { if (http_handle->response_info.headers.transfer_encoding != GLOBUS_XIO_HTTP_TRANSFER_ENCODING_CHUNKED && GLOBUS_I_XIO_HTTP_HEADER_IS_CONTENT_LENGTH_SET( &http_handle->response_info.headers) && http_handle->response_info.headers.content_length == 0) { /* Synthesize EOF if we've read all of the entity content */ result = GlobusXIOErrorEOF(); } /* * Either we've read enough, hit end of chunk, no entity was present, * or pass to transport failed. Call finished_read */ nbytes = http_handle->read_operation.nbytes; globus_libc_free(http_handle->read_operation.iov); http_handle->read_operation.iov = NULL; http_handle->read_operation.iovcnt = 0; http_handle->read_operation.operation = NULL; http_handle->read_operation.driver_handle = NULL; http_handle->read_operation.nbytes = 0; globus_mutex_unlock(&http_handle->mutex); globus_xio_driver_finished_read(op, result, nbytes); return; } else if (registered_again) { globus_mutex_unlock(&http_handle->mutex); return; } /* FALLSTHROUGH */ reregister_read: globus_assert(op == http_handle->read_operation.operation); if (eof_result != GLOBUS_SUCCESS) { /* Header block wasn't complete before eof */ result = eof_result; goto error_exit; } result = globus_i_xio_http_clean_read_buffer(http_handle); if (result != GLOBUS_SUCCESS) { goto error_exit; } result = globus_xio_driver_pass_read( op, &http_handle->read_iovec, 1, 1, globus_i_xio_http_server_read_request_callback, http_handle); if (result != GLOBUS_SUCCESS) { goto error_exit; } globus_mutex_unlock(&http_handle->mutex); return; error_exit: globus_libc_free(http_handle->read_operation.iov); http_handle->read_operation.iov = NULL; http_handle->read_operation.iovcnt = 0; http_handle->read_operation.operation = NULL; http_handle->read_operation.driver_handle = NULL; http_handle->read_operation.nbytes = 0; globus_mutex_unlock(&http_handle->mutex); globus_xio_driver_finished_read(op, result, 0); }
/** * Allocate and initialize an HTTP handle * @ingroup globus_i_xio_http_handle * * Creates a new handle with values derived from the attr and target. This * is called internally by the HTTP driver's open implementation. * * @param http_handle * Pointer to an uninitialized handle. * @param attr * HTTP attributes associated with open operation. * @param target * Target which is being opened. * * This function may return GLOBUS_SUCCESS, or an error generated by * globus_i_xio_http_response_init(), globus_i_xio_http_request_copy(), * or globus_i_xio_http_target_copy(). */ globus_result_t globus_i_xio_http_handle_init( globus_i_xio_http_handle_t * http_handle, globus_i_xio_http_attr_t * attr, globus_i_xio_http_target_t * target) { globus_result_t result; int rc; GlobusXIOName(globus_i_xio_http_handle_init); rc = globus_mutex_init(&http_handle->mutex, NULL); if (rc != 0) { result = GlobusXIOErrorMemory("mutex"); goto error_exit; } if (target->is_client && attr != NULL) { result = globus_i_xio_http_request_copy( &http_handle->request_info, &attr->request); } else { result = globus_i_xio_http_request_init(&http_handle->request_info); } if (target->is_client) { http_handle->parse_state = GLOBUS_XIO_HTTP_STATUS_LINE; http_handle->send_state = GLOBUS_XIO_HTTP_PRE_REQUEST_LINE; } else { http_handle->parse_state = GLOBUS_XIO_HTTP_PRE_REQUEST_LINE; http_handle->send_state = GLOBUS_XIO_HTTP_STATUS_LINE; } if (result != GLOBUS_SUCCESS) { goto free_mutex_exit; } result = globus_i_xio_http_response_init(&http_handle->response_info); if (result != GLOBUS_SUCCESS) { goto free_request_exit; } result = globus_i_xio_http_target_copy(&http_handle->target_info, target); if (result != GLOBUS_SUCCESS) { goto free_response_exit; } http_handle->header_iovec = NULL; http_handle->header_iovcnt = 0; http_handle->read_buffer.iov_base = NULL; http_handle->read_buffer.iov_len = 0; http_handle->close_operation = NULL; http_handle->response_read_operation = NULL; http_handle->read_operation.iov = NULL; http_handle->read_operation.iovcnt = 0; http_handle->read_operation.operation = NULL; http_handle->read_operation.driver_handle = NULL; http_handle->read_operation.nbytes = 0; http_handle->write_operation.iov = NULL; http_handle->write_operation.iovcnt = 0; http_handle->write_operation.operation = NULL; http_handle->write_operation.driver_handle = NULL; http_handle->write_operation.nbytes = 0; http_handle->user_close = GLOBUS_FALSE; http_handle->read_response = GLOBUS_FALSE; return GLOBUS_SUCCESS; free_response_exit: globus_i_xio_http_response_destroy(&http_handle->response_info); free_request_exit: globus_i_xio_http_request_destroy(&http_handle->request_info); free_mutex_exit: globus_mutex_destroy(&http_handle->mutex); error_exit: return result; }
globus_result_t globus_xio_system_socket_init( globus_xio_system_socket_handle_t * uhandle, globus_xio_system_socket_t socket, globus_xio_system_type_t type) { globus_result_t result; globus_l_xio_win32_socket_t * handle; unsigned long flag; GlobusXIOName(globus_xio_system_socket_init); GlobusXIOSystemDebugEnterFD(socket); handle = (globus_l_xio_win32_socket_t *) globus_calloc(1, sizeof(globus_l_xio_win32_socket_t)); if(!handle) { result = GlobusXIOErrorMemory("handle"); goto error_alloc; } handle->socket = socket; win32_mutex_init(&handle->lock, 0); handle->ready_events = FD_READ; /* to avoid winsock fd_close bug */ handle->event = WSACreateEvent(); if(handle->event == 0) { result = GlobusXIOErrorSystemError( "WSACreateEvent", WSAGetLastError()); goto error_create; } flag = 1; if(ioctlsocket(socket, FIONBIO, &flag) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError( "ioctlsocket", WSAGetLastError()); goto error_ioctl; } result = globus_i_xio_win32_event_register( &handle->event_entry, handle->event, globus_l_xio_win32_socket_event_cb, handle); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_i_xio_win32_event_register", result); goto error_register; } GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] Registered event handle=%lu\n", _xio_name, (unsigned long) handle->event)); *uhandle = handle; GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_register: flag = 0; ioctlsocket(socket, FIONBIO, &flag); error_ioctl: WSACloseEvent(handle->event); error_create: win32_mutex_destroy(&handle->lock); globus_free(handle); error_alloc: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
globus_result_t globus_xio_attr_copy( globus_xio_attr_t * dst, globus_xio_attr_t src) { globus_i_xio_attr_t * xio_attr_src; globus_i_xio_attr_t * xio_attr_dst; globus_result_t res; int ctr; int ctr2; GlobusXIOName(globus_xio_attr_copy); GlobusXIODebugEnter(); if(dst == NULL) { res = GlobusXIOErrorParameter("dst"); goto err; } if(src == NULL) { res = GlobusXIOErrorParameter("src"); goto err; } xio_attr_src = src; xio_attr_dst = (globus_i_xio_attr_t *) globus_malloc(sizeof(globus_i_xio_attr_t)); /* check for memory alloc failure */ if(xio_attr_dst == NULL) { res = GlobusXIOErrorMemory("xio_attr_dst"); goto err; } memset(xio_attr_dst, 0, sizeof(globus_i_xio_attr_t)); xio_attr_dst->entry = (globus_i_xio_attr_ent_t *) globus_malloc(sizeof(globus_i_xio_attr_ent_t) * GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE); if(xio_attr_dst->entry == NULL) { globus_free(xio_attr_dst); res = GlobusXIOErrorMemory("xio_attr_dst->entry"); goto err; } memset(xio_attr_dst->entry, 0, sizeof(globus_i_xio_attr_ent_t) * GLOBUS_XIO_ATTR_ARRAY_BASE_SIZE); /* copy all general attrs */ xio_attr_dst->max = xio_attr_src->max; xio_attr_dst->ndx = xio_attr_src->ndx; xio_attr_dst->space = xio_attr_src->space; globus_callback_space_reference(xio_attr_dst->space); xio_attr_dst->open_timeout_cb = xio_attr_src->open_timeout_cb; xio_attr_dst->open_timeout_period = xio_attr_src->open_timeout_period; xio_attr_dst->read_timeout_cb = xio_attr_src->read_timeout_cb; xio_attr_dst->read_timeout_period = xio_attr_src->read_timeout_period; xio_attr_dst->write_timeout_cb = xio_attr_src->write_timeout_cb; xio_attr_dst->write_timeout_period = xio_attr_src->write_timeout_period; xio_attr_dst->close_timeout_cb = xio_attr_src->close_timeout_cb; xio_attr_dst->close_timeout_period = xio_attr_src->close_timeout_period; xio_attr_dst->accept_timeout_cb = xio_attr_src->accept_timeout_cb; xio_attr_dst->accept_timeout_period = xio_attr_src->accept_timeout_period; xio_attr_dst->cancel_open = xio_attr_src->cancel_open; xio_attr_dst->cancel_close = xio_attr_src->cancel_close; xio_attr_dst->cancel_read = xio_attr_src->cancel_read; xio_attr_dst->cancel_write = xio_attr_src->cancel_write; xio_attr_dst->no_cancel = xio_attr_src->no_cancel; xio_attr_dst->timeout_arg = xio_attr_src->timeout_arg; for(ctr = 0; ctr < xio_attr_dst->ndx; ctr++) { xio_attr_dst->entry[ctr].driver = xio_attr_src->entry[ctr].driver; res = xio_attr_dst->entry[ctr].driver->attr_copy_func( &xio_attr_dst->entry[ctr].driver_data, xio_attr_src->entry[ctr].driver_data); if(res != GLOBUS_SUCCESS) { for(ctr2 = 0; ctr2 < ctr; ctr2++) { /* ignore result here */ xio_attr_dst->entry[ctr].driver->attr_destroy_func( xio_attr_dst->entry[ctr].driver_data); } globus_free(xio_attr_dst->entry); globus_free(xio_attr_dst); goto err; } } globus_mutex_lock(&globus_i_xio_mutex); { globus_list_insert(&globus_i_xio_outstanding_attrs_list, xio_attr_dst); } globus_mutex_unlock(&globus_i_xio_mutex); *dst = xio_attr_dst; GlobusXIODebugExit(); return GLOBUS_SUCCESS; err: GlobusXIODebugExitWithError(); return res; }