/** * 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; }
/** * 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; }
/** * 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_i_xio_http_handle_reinit( globus_i_xio_http_handle_t * http_handle, globus_i_xio_http_attr_t * http_attr, globus_i_xio_http_target_t * http_target) { globus_result_t result; GlobusXIOName(globus_i_xio_http_handle_reinit); if (http_target && http_target->is_client && http_attr != NULL) { globus_i_xio_http_request_destroy(&http_handle->request_info); result = globus_i_xio_http_request_copy( &http_handle->request_info, &http_attr->request); } else { globus_i_xio_http_request_destroy(&http_handle->request_info); result = globus_i_xio_http_request_init(&http_handle->request_info); } if (http_target && http_target->is_client) { http_handle->send_state = GLOBUS_XIO_HTTP_PRE_REQUEST_LINE; } else { http_handle->send_state = GLOBUS_XIO_HTTP_STATUS_LINE; } if (result != GLOBUS_SUCCESS) { goto free_mutex_exit; } globus_i_xio_http_response_destroy(&http_handle->response_info); result = globus_i_xio_http_response_init(&http_handle->response_info); if (result != GLOBUS_SUCCESS) { goto free_request_exit; } globus_i_xio_http_target_destroy_internal(&http_handle->target_info); if (http_target) { result = globus_i_xio_http_target_copy( &http_handle->target_info, http_target); if (result != GLOBUS_SUCCESS) { goto free_response_exit; } } http_handle->header_iovec = NULL; http_handle->header_iovcnt = 0; http_handle->close_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); return result; }