diff options
author | gmcdonald | 2010-02-13 01:32:03 +0000 |
---|---|---|
committer | gmcdonald | 2010-02-13 01:32:03 +0000 |
commit | 0425aadc78680e53000fd0108b540d6eca048516 (patch) | |
tree | 8ec7ab8e015d454c5ec586dfc91e05a2dce1cfc0 /src/core/transport/http/server | |
download | axis2c-0425aadc78680e53000fd0108b540d6eca048516.tar.gz axis2c-0425aadc78680e53000fd0108b540d6eca048516.tar.bz2 |
Moving axis svn, part of TLP move INFRA-2441
git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/core/transport/http/server')
30 files changed, 6429 insertions, 0 deletions
diff --git a/src/core/transport/http/server/CGI/Makefile.am b/src/core/transport/http/server/CGI/Makefile.am new file mode 100644 index 0000000..fafb8bf --- /dev/null +++ b/src/core/transport/http/server/CGI/Makefile.am @@ -0,0 +1,31 @@ +prgbindir=$(bindir) +prgbin_PROGRAMS = axis2.cgi +SUBDIRS = +AM_CFLAGS = -g -pthread +axis2_cgi_SOURCES = axis2_cgi_main.c \ + axis2_cgi_out_transport_info.c \ + axis2_cgi_stream.c + +axis2_cgi_LDADD = $(LDFLAGS) \ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la \ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la \ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la \ + $(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/axiom/src/parser/$(WRAPPER_DIR)/libaxis2_parser.la \ + $(top_builddir)/src/core/description/libaxis2_description.la \ + $(top_builddir)/src/core/deployment/libaxis2_deployment.la \ + $(top_builddir)/src/core/context/libaxis2_context.la \ + $(top_builddir)/src/core/clientapi/libaxis2_clientapi.la \ + $(top_builddir)/src/core/engine/libaxis2_engine.la \ + $(top_builddir)/src/core/transport/http/sender/libaxis2_http_sender.la \ + $(top_builddir)/src/core/transport/http/receiver/libaxis2_http_receiver.la \ + -lpthread + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/description\ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/deployment\ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/server/CGI/axis2_cgi_main.c b/src/core/transport/http/server/CGI/axis2_cgi_main.c new file mode 100644 index 0000000..6f9a59d --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_main.c @@ -0,0 +1,280 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "axis2_cgi_out_transport_info.h" +#include "axis2_cgi_stream.h" + +#include <stdio.h> +#include <stdlib.h> +#include <axutil_error_default.h> +#include <axutil_log_default.h> +#include <axutil_thread_pool.h> +#include <axutil_types.h> +#include <axutil_version.h> +#include <axutil_file_handler.h> +#include <axutil_url.h> +#include <axutil_string.h> +#include <platforms/axutil_platform_auto_sense.h> + +#include <axis2_engine.h> +#include <axis2_conf_init.h> +#include <axis2_http_transport_utils.h> + +axis2_char_t *axis2_cgi_default_url_prefix = "/cgi-bin/axis2.cgi/"; + +/***************************** Function headers *******************************/ + +void +axis2_cgi_system_exit( + axutil_env_t * env, + int status); + +void +axis2_cgi_set_request_vars( + axis2_cgi_request_t *cgi_request); + +axis2_status_t +axis2_cgi_write_response( + const void *buffer, + unsigned int length); + +/***************************** End of function headers ************************/ + +int +main( + int argc, + char *argv[]) +{ + axutil_allocator_t *allocator = NULL; + axutil_env_t *env = NULL; + const axis2_char_t *repo_path; + axis2_conf_ctx_t *conf_ctx; + axis2_cgi_request_t *cgi_request = NULL; + int content_length = 0; + axis2_char_t *request_url = NULL; + /* axutil_stream_t *request_body_stream = NULL; */ + axutil_stream_t *out_stream = NULL; + axis2_transport_in_desc_t *in_desc = NULL; + axis2_transport_out_desc_t *out_desc = NULL; + /* axis2_msg_ctx_t *msg_ctx = NULL; */ + /* axis2_bool_t processed = AXIS2_FALSE; */ + axis2_http_transport_in_t request; + axis2_http_transport_out_t response; + /*axis2_http_header_t* http_header = NULL; */ + /*axutil_hash_t *headers = NULL; */ + /* axis2_char_t *axis2_cgi_url_prefix = NULL; */ + + if(!(repo_path = AXIS2_GETENV("AXIS2C_HOME"))) + { + fprintf(stderr, "Error: AXIS2C_HOME environment variable not set!"); + axis2_cgi_system_exit(env, -1); + } + + allocator = axutil_allocator_init(NULL); + env = axutil_env_create(allocator); + + if(axutil_file_handler_access(repo_path, AXIS2_R_OK) != AXIS2_SUCCESS) + { + fprintf(stderr, "Error reading repository: %s\nPlease check AXIS2C_HOME var", repo_path); + axis2_cgi_system_exit(env, -1); + } + + /* Set configuration */ + + conf_ctx = axis2_build_conf_ctx(env, repo_path); + if(!conf_ctx) + { + fprintf(stderr, "Error: Configuration not builded propertly\n"); + axis2_cgi_system_exit(env, -1); + } + + axis2_http_transport_utils_transport_out_init(&response, env); + axis2_http_transport_utils_transport_in_init(&request, env); + + /* Get input info */ + + cgi_request = AXIS2_MALLOC(allocator, sizeof(axis2_cgi_request_t)); + axis2_cgi_set_request_vars(cgi_request); + + request_url = (axis2_char_t *)AXIS2_MALLOC(allocator, (7 + /* "http:" */ + strlen(cgi_request->server_name) + ((strlen(cgi_request->server_port)) ? 1 : 0) + /* ":"*/ + strlen(cgi_request->server_port) + strlen(cgi_request->script_name) + strlen( + cgi_request->path_info) + ((strlen(cgi_request->path_info)) ? 1 : 0) + /* "?" */ + strlen(cgi_request->query_string)) * sizeof(axis2_char_t)); + + request_url[0] = '\0'; + + strcat(request_url, "http://"); + strcat(request_url, cgi_request->server_name); + if(strlen(cgi_request->server_port)) + strcat(request_url, ":"); + strcat(request_url, cgi_request->server_port); + strcat(request_url, cgi_request->script_name); + strcat(request_url, cgi_request->path_info); + if(strlen(cgi_request->query_string)) + strcat(request_url, "?"); + strcat(request_url, cgi_request->query_string); + + if(cgi_request->content_length) + content_length = axutil_atoi(cgi_request->content_length); + else + content_length = 0; + + /* Set streams */ + + out_stream = axutil_stream_create_basic(env); + + /* Set message contexts */ + + out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + + request.msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc); + + axis2_msg_ctx_set_server_side(request.msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_transport_out_stream(request.msg_ctx, env, out_stream); + axis2_msg_ctx_set_transport_headers(request.msg_ctx, env, NULL); + + /* Set request parameters */ + + request.soap_action = cgi_request->soap_action; + request.in_stream = axutil_stream_create_cgi(env, content_length); + request.remote_ip = cgi_request->remote_addr; + request.content_length = content_length; + request.content_type = cgi_request->content_type; + request.request_uri = request_url; + request.svr_port = cgi_request->server_port; + request.accept_header = AXIS2_GETENV("HTTP_ACCEPT"); + request.accept_language_header = AXIS2_GETENV("HTTP_ACCEPT_LANGUAGE"); + request.accept_charset_header = AXIS2_GETENV("HTTP_ACCEPT_CHARSET"); + request.request_url_prefix = (AXIS2_GETENV("AXIS2C_URL_PREFIX")) ? AXIS2_GETENV( + "AXIS2C_URL_PREFIX") : axis2_cgi_default_url_prefix; + + if(axutil_strcasecmp(cgi_request->request_method, "POST") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_POST; + } + else if(axutil_strcasecmp(cgi_request->request_method, "GET") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_GET; + } + else if(axutil_strcasecmp(cgi_request->request_method, "HEAD") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_HEAD; + } + else if(axutil_strcasecmp(cgi_request->request_method, "PUT") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_PUT; + } + else if(axutil_strcasecmp(cgi_request->request_method, "DELETE") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_DELETE; + } + + request.out_transport_info = axis2_cgi_out_transport_info_create(env, cgi_request); + + /*Process request */ + fprintf(stderr, "ok\n"); + axis2_http_transport_utils_process_request(env, conf_ctx, &request, &response); + fprintf(stderr, "ok\n"); + /*Send status */ + + fprintf(stdout, "Status: %d %s \r\n", response.http_status_code, response.http_status_code_name); + + if(response.content_type) + { + fprintf(stdout, "Content-type: %s \r\n", response.content_type); + } + else if(strlen(axis2_cgi_out_transport_get_content(request.out_transport_info)) + && axis2_cgi_out_transport_get_content(request.out_transport_info)) + { + fprintf(stdout, "Content-type: %s \r\n", axis2_cgi_out_transport_get_content( + request.out_transport_info)); + } + + fprintf(stdout, "\r\n"); /* End of headers for server */ + + /* Write data body */ + if(!axis2_cgi_write_response(response.response_data, response.response_data_length)) + { + fprintf(stderr, "Error writing output data\n"); + } + + axis2_http_transport_utils_transport_in_uninit(&request, env); + axis2_http_transport_utils_transport_out_uninit(&response, env); + + return 0; +} + +axis2_status_t +axis2_cgi_write_response( + const void *buffer, + unsigned int length) +{ + if(buffer && length) + { + unsigned int completed = 0; + unsigned int written = 0; + + while(completed < length) + { + written = fwrite(buffer, sizeof(char), length - completed, stdout); + if(written < 0) + return AXIS2_FALSE; + completed += written; + } + } + return AXIS2_TRUE; +} + +void +axis2_cgi_set_request_vars( + axis2_cgi_request_t *cgi_request) +{ + cgi_request->server_name = (AXIS2_GETENV("SERVER_NAME")) ? AXIS2_GETENV("SERVER_NAME") : ""; + cgi_request->script_name = (AXIS2_GETENV("SCRIPT_NAME")) ? AXIS2_GETENV("SCRIPT_NAME") : ""; + cgi_request->path_info = (AXIS2_GETENV("PATH_INFO")) ? AXIS2_GETENV("PATH_INFO") : ""; + cgi_request->server_port = (AXIS2_GETENV("SERVER_PORT")) ? AXIS2_GETENV("SERVER_PORT") : ""; + cgi_request->server_protocol = (AXIS2_GETENV("SERVER_PROTOCOL")) ? AXIS2_GETENV( + "SERVER_PROTOCOL") : ""; + cgi_request->content_length = (AXIS2_GETENV("CONTENT_LENGTH")) ? AXIS2_GETENV("CONTENT_LENGTH") + : ""; + cgi_request->content_type = (AXIS2_GETENV("CONTENT_TYPE")) ? AXIS2_GETENV("CONTENT_TYPE") : ""; + cgi_request->request_method = (AXIS2_GETENV("REQUEST_METHOD")) ? AXIS2_GETENV("REQUEST_METHOD") + : ""; + cgi_request->remote_addr = (AXIS2_GETENV("REMOTE_ADDR")) ? AXIS2_GETENV("REMOTE_ADDR") : ""; + cgi_request->soap_action = (AXIS2_GETENV("HTTP_SOAPACTION")) ? AXIS2_GETENV("HTTP_SOAPACTION") + : NULL; + cgi_request->query_string = (AXIS2_GETENV("QUERY_STRING")) ? AXIS2_GETENV("QUERY_STRING") : ""; +} + +void +axis2_cgi_system_exit( + axutil_env_t * env, + int status) +{ + axutil_allocator_t *allocator = NULL; + + if(env) + { + allocator = env->allocator; + axutil_env_free(env); + } + exit(status); +} diff --git a/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c new file mode 100644 index 0000000..59e6820 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "axis2_cgi_out_transport_info.h" +#include <axutil_string.h> +#include <axis2_http_transport.h> + +/** + * @brief CIG Out transport info impl structure + * Axis2 cgi_out_transport_info_impl + */ + +typedef struct axis2_cgi_out_transport_info_s +{ + axis2_http_out_transport_info_t out_transport_info; + axis2_cgi_request_t *request; + axis2_char_t *encoding; +} axis2_cgi_out_transport_info_t; + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_cgi_out_transport_info_t *)(out_transport_info)) + +void AXIS2_CALL +axis2_cgi_out_transport_info_free( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + AXIS2_ENV_CHECK(env, void); + + info_impl = AXIS2_INTF_TO_IMPL(info); + + info_impl->request = NULL; /* doesn't belong here so no need to free it here */ + if(info_impl->encoding) + { + AXIS2_FREE(env->allocator, info_impl->encoding); + info_impl->encoding = NULL; + } + + AXIS2_FREE(env->allocator, info_impl); + return; +} + +void AXIS2_CALL +axis2_cgi_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + AXIS2_ENV_CHECK(env, void); + transport_info_l = (axis2_http_out_transport_info_t *)transport_info; + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +axis2_status_t AXIS2_CALL +axis2_cgi_out_transport_info_set_content_type( + axis2_http_out_transport_info_t *info, + const axutil_env_t *env, + const axis2_char_t *content_type) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + + axis2_char_t *temp1 = NULL; + axis2_char_t *temp2 = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + info_impl = AXIS2_INTF_TO_IMPL(info); + if(info_impl->encoding) + { + temp1 = axutil_stracat(env, content_type, ";charset="); + temp2 = axutil_stracat(env, temp1, info_impl->encoding); + info_impl->request->content_type = axutil_strdup(env, temp2); + AXIS2_FREE(env->allocator, temp1); + AXIS2_FREE(env->allocator, temp2); + } + else + { + info_impl->request->content_type = axutil_strdup(env, content_type); + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_cgi_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + + info_impl = AXIS2_INTF_TO_IMPL(info); + + if(info_impl->encoding) + { + AXIS2_FREE(env->allocator, info_impl->encoding); + } + info_impl->encoding = axutil_strdup(env, encoding); + + return AXIS2_SUCCESS; +} + +axis2_http_out_transport_info_t *AXIS2_CALL +axis2_cgi_out_transport_info_create( + const axutil_env_t * env, + axis2_cgi_request_t * request) +{ + axis2_cgi_out_transport_info_t *info = NULL; + axis2_http_out_transport_info_t *out_transport_info = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + info = (axis2_cgi_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_cgi_out_transport_info_t)); + + if(!info) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + info->request = request; + info->encoding = NULL; + + out_transport_info = &(info->out_transport_info); + + axis2_http_out_transport_info_set_char_encoding_func(out_transport_info, env, + axis2_cgi_out_transport_info_set_char_encoding); + axis2_http_out_transport_info_set_content_type_func(out_transport_info, env, + axis2_cgi_out_transport_info_set_content_type); + + return out_transport_info; +} + +axis2_char_t * +axis2_cgi_out_transport_get_content( + axis2_http_out_transport_info_t * info) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + info_impl = AXIS2_INTF_TO_IMPL(info); + return info_impl->request->content_type; +} + diff --git a/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h new file mode 100644 index 0000000..bc0f526 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h @@ -0,0 +1,62 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_CGI_OUT_TRANSPORT_INFO_H +#define AXIS2_CGI_OUT_TRANSPORT_INFO_H + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_cgi_out_transport_info.h + * @brief axis2 CGI Out Transport Info + */ + +#include "axis2_cgi_types.h" +#include <axis2_http_out_transport_info.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + axis2_http_out_transport_info_t *AXIS2_CALL + + axis2_cgi_out_transport_info_create( + const axutil_env_t * env, + axis2_cgi_request_t * request); + + /** + * Free http_out_transport_info passed as void pointer. This will be + * cast into appropriate type and then pass the cast object + * into the http_out_transport_info structure's free method + */ + void AXIS2_CALL + axis2_cgi_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env); + + axis2_char_t *axis2_cgi_out_transport_get_content( + axis2_http_out_transport_info_t * out_transport_info); + +#ifdef __cplusplus +} +#endif +#endif /* AXIS2_SGI_OUT_TRANSPORT_INFO_H */ diff --git a/src/core/transport/http/server/CGI/axis2_cgi_stream.c b/src/core/transport/http/server/CGI/axis2_cgi_stream.c new file mode 100644 index 0000000..68ad19f --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_stream.c @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string.h> +#include <stdlib.h> +#include "axis2_cgi_stream.h" + +/** + * @brief Stream struct impl + * Streaming mechanisms for cgi + */ + +typedef struct cgi_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + unsigned int cur_pos; + unsigned int content_length; +} cgi_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((cgi_stream_impl_t *)(stream)) + +axutil_stream_type_t AXIS2_CALL +cgi_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL cgi_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL cgi_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL cgi_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL cgi_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +axutil_stream_t *AXIS2_CALL +axutil_stream_create_cgi( + const axutil_env_t * env, + unsigned int content_length) +{ + cgi_stream_impl_t *stream_impl = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, content_length, NULL); + + stream_impl = (cgi_stream_impl_t *)AXIS2_MALLOC(env->allocator, sizeof(cgi_stream_impl_t)); + + if(!stream_impl) + { + return NULL; + } + stream_impl->cur_pos = 0; + stream_impl->content_length = content_length; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, cgi_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, cgi_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, cgi_stream_skip); + + return &(stream_impl->stream); +} +int AXIS2_CALL +cgi_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + /*void *temp_buff = NULL;*/ + /*unsigned int data_to_read = 0;*/ + unsigned int read_bytes = 0; + /*axis2_bool_t ret_ok = AXIS2_TRUE;*/ + + cgi_stream_impl_t *stream_impl = NULL; + /*char *temp = NULL;*/ + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = (cgi_stream_impl_t *)stream; + + if(count < stream_impl->content_length) + { + read_bytes = fread(buffer, sizeof(char), count, stdin); + } + else + { + read_bytes = fread(buffer, sizeof(char), stream_impl->content_length, stdin); + } + + return read_bytes; +} + +int AXIS2_CALL +cgi_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + /* Cannot write on cgi stdin, explicitly an input stream */ + + return -1; +} + +int AXIS2_CALL +cgi_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + cgi_stream_impl_t *stream_impl = NULL; + int skipped = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + if(fseek(stdin, count, SEEK_CUR) == 0) + skipped = count; + return skipped; +} + +int AXIS2_CALL +cgi_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +cgi_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} diff --git a/src/core/transport/http/server/CGI/axis2_cgi_stream.h b/src/core/transport/http/server/CGI/axis2_cgi_stream.h new file mode 100644 index 0000000..9a6af34 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_stream.h @@ -0,0 +1,44 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CGI_STREAM_H +#define CGI_STREAM_H + +#include <axis2_const.h> +#include <axis2_defines.h> +#include <axutil_env.h> +#include <axutil_stream.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** brief Constructor for creating CGI stream + * @return axutil_stream (CGI) + */ + axutil_stream_t *AXIS2_CALL + axutil_stream_create_cgi( + const axutil_env_t * env, + unsigned int content_length); + +#ifdef __cplusplus +} +#endif + +#endif /* CGI_STREAM_H */ diff --git a/src/core/transport/http/server/CGI/axis2_cgi_types.h b/src/core/transport/http/server/CGI/axis2_cgi_types.h new file mode 100644 index 0000000..af184a1 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_types.h @@ -0,0 +1,34 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <axis2_const.h> + +typedef struct axis2_cgi_request +{ + axis2_char_t *server_name; + axis2_char_t *server_port; + axis2_char_t *script_name; + axis2_char_t *path_info; + axis2_char_t *server_protocol; + axis2_char_t *content_length; + axis2_char_t *content_type; + axis2_char_t *request_method; + axis2_char_t *remote_addr; + axis2_char_t *soap_action; + axis2_char_t *query_string; +} axis2_cgi_request_t; diff --git a/src/core/transport/http/server/IIS/README b/src/core/transport/http/server/IIS/README new file mode 100644 index 0000000..1a47cc4 --- /dev/null +++ b/src/core/transport/http/server/IIS/README @@ -0,0 +1,61 @@ +How to Configure IIS Module for Axis2C
+________________________________________
+
+Use the Axis2/C VC project or makefile to build the component.
+
+In this document it is assumed that the mod_axis2_IIS.dll is in the directory
+c:\axis2c\lib\mod_axis2_IIS.dll and axis2c_home is c:\axis2c
+
+Add the following key to the registry.
+
+HKEY_LOCAL_MACHINE\SOFTWARE\Apache Axis2c\IIS ISAPI Redirector
+
+Add a string value with the name axis2c_home and a value of c:\axis2c
+
+Add a string value with the name log_file and a value of c:\axis2c\logs\axis2.log
+
+Add a string value with the name log_level. The value can be one of trace, error, info, critical, debug, warning
+
+You can add a string value with the name services_url_prefix. This is optional and defaults to "/services".
+As an example, if you have "/web_services" as the prefix, then all the services hosted would have the endpoint prefix of :
+http://localhost/axis2/web_services.
+Note: don't forget the / at the begining.
+
+If you wish, you can also change the location as well by adding a string value with the name axis2_location.
+This is also optional and defaults to /axis2. If you have /myserser as the value you can access your web
+services with a url like http://localhost/myserver/services.
+Note: Don't forget the / at the beginning.
+
+Now you can do all the registry editing using the JScript file axis2_iis_regedit.js
+provided with the distribution. When you build axis2/C with the IIS module the file
+is copied to the root directory of the binary distribution. Just double click it and
+everything will be set to the defaults. The axis2c_home is taken as the current directory,
+so make sure you run the file in the Axis2/C repository location (or root of the binary distribution).
+If you want to change the values you can manually edit the the .js file or give it as command line arguments
+to the script when running the script. To run the jscript from the command line use the command
+:\cscript axis2_iis_regedit.js optional arguments.
+We recomend the manual editing as it is the easiest way to specify the values
+
+IIS 5.1 or Below
+
+Using the IIS management console, add a new virtual directory to your IIS/PWS Web site.
+The name of the virtual directory must be axis2. Its physical path should be the directory
+where you placed mod_axis2_IIS.dll (in our example it is c:\axis2c\lib). When creating this new
+virtual directory, assign execute access to it.
+
+By Using the IIS management console, add mod_axis2_IIS.dll as a filter in your IIS/PWS web site and restart the IIS admin service.
+
+
+IIS 6 & 7
+
+Using the IIS management console, add the mod_axis2_IIS.dll as a Wildcard Script Map.
+ Executable should be the complete path to the mod_axis2_IIS.dll
+ You can put any name as the name of the Wildcard Script Map
+
+Please don't add the mod_axis2_IIS.dll as a filter to IIS as in the IIS 5.1 case.
+
+Note: If the Axis2/C failed to load, verify that Axis2/C and its dependent DLLs are in the System Path (not the user path).
+
+
+
+
diff --git a/src/core/transport/http/server/IIS/axis2_iis_constants.h b/src/core/transport/http/server/IIS/axis2_iis_constants.h new file mode 100644 index 0000000..fb6929b --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_constants.h @@ -0,0 +1,51 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_IIS_CONSTANTS_H +#define AXIS2_IIS_CONSTANTS_H + +#define INTERNET_MAX_PATH_LENGTH 2048 +#define INTERNET_MAX_SCHEME_LENGTH 32 /* longest protocol name length */ +#define INTERNET_MAX_URL_LENGTH (INTERNET_MAX_SCHEME_LENGTH +sizeof("://") +INTERNET_MAX_PATH_LENGTH) + +#define URI_MATCHED 1 +#define URI_UN_MATCHED 2 + +#define EXTENSION_URL "/axis2/mod_axis2_IIS.dll\? " +#define EXTENSION_URL_AXIS2 "/axis2/" +#define EXTENSION_URL_MODIIS "mod_axis2_IIS.dll\? " + + +#define MAX_SERVERNAME 128 +#define MAX_PORT_LEN 8 + +#define MAX_HTTP_VERSION_LEN 16 +#define MAX_HTTP_CONTENT_TYPE_LEN 2048 +#define MAX_CONTENT_ENCODING_LEN 16 +#define MAX_HTTP_METHOD_LEN 8 +#define MAX_TCP_PORT_LEN 8 +#define MAX_CONTENT_LEN 16 + +#define OK 200 +#define HTTP_INTERNAL_SERVER_ERROR 500 +#define HTTP_ACCEPTED 202 + +#define AXIS2_STRICMP _stricmp + +#endif /*AXIS2_IIS_CONSTANTS_H*/ + diff --git a/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c new file mode 100644 index 0000000..fb7693b --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "axis2_iis_out_transport_info.h" +#include <axutil_string.h> +#include <axis2_http_transport.h> +#include <axutil_string.h> + +#include "axis2_iis_constants.h" + +/** + * @brief IIS Out transport info impl structure + * Axis2 iis_out_transport_info_impl + */ + +typedef struct axis2_iis_out_transport_info_s +{ + axis2_http_out_transport_info_t out_transport_info; + axis2_char_t *encoding; + axis2_char_t content_type[MAX_HTTP_CONTENT_TYPE_LEN]; +} axis2_iis_out_transport_info_t; + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_iis_out_transport_info_t *)(out_transport_info)) + +void AXIS2_CALL +axis2_iis_out_transport_info_free( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env) +{ + axis2_iis_out_transport_info_t *info = NULL; + AXIS2_ENV_CHECK(env, void); + + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + if(info->encoding) + { + AXIS2_FREE(env->allocator, info->encoding); + info->encoding = NULL; + } + + AXIS2_FREE(env->allocator, info); + return; +} + +void AXIS2_CALL +axis2_iis_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + AXIS2_ENV_CHECK(env, void); + transport_info_l = (axis2_http_out_transport_info_t *)transport_info; + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +axis2_status_t AXIS2_CALL +axis2_iis_out_transport_info_set_content_type( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_iis_out_transport_info_t *info_impl = NULL; + + info_impl = AXIS2_INTF_TO_IMPL(info); + info_impl->content_type[0] = '\0'; + if(info_impl->encoding) + { + sprintf(info_impl->content_type, "%s%s%s", content_type, ";charser:", info_impl->encoding); + } + else + { + strcat(info_impl->content_type, content_type); + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_iis_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + axis2_iis_out_transport_info_t *info_impl = NULL; + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + + info_impl = AXIS2_INTF_TO_IMPL(info); + + if(info_impl->encoding) + { + AXIS2_FREE(env->allocator, info_impl->encoding); + } + info_impl->encoding = axutil_strdup(env, encoding); + + return AXIS2_SUCCESS; +} + +axis2_http_out_transport_info_t *AXIS2_CALL +axis2_iis_out_transport_info_create( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + axis2_iis_out_transport_info_t *info = NULL; + axis2_http_out_transport_info_t *http_out_info = NULL; + AXIS2_ENV_CHECK(env, NULL); + + info = (axis2_iis_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_iis_out_transport_info_t)); + + if(!info) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + info->encoding = NULL; + + http_out_info = &(info->out_transport_info); + + axis2_http_out_transport_info_set_content_type_func(http_out_info, env, + axis2_iis_out_transport_info_set_content_type); + axis2_http_out_transport_info_set_char_encoding_func(http_out_info, env, + axis2_iis_out_transport_info_set_char_encoding); + axis2_http_out_transport_info_set_free_func(http_out_info, env, + axis2_iis_out_transport_info_free); + + return http_out_info; +} + +axis2_char_t * +axis2_iis_out_transport_get_content( + axis2_http_out_transport_info_t * info) +{ + axis2_iis_out_transport_info_t *info_impl = NULL; + info_impl = AXIS2_INTF_TO_IMPL(info); + return info_impl->content_type; +} diff --git a/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h new file mode 100644 index 0000000..893ffdf --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h @@ -0,0 +1,61 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_IIS_OUT_TRANSPORT_INFO_H +#define AXIS2_IIS_OUT_TRANSPORT_INFO_H + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_iis_out_transport_info.h + * @brief axis2 IIS Out Transport Info + */ + +#include <axis2_http_out_transport_info.h> +#include <httpext.h> +#ifdef __cplusplus +extern "C" +{ +#endif + + axis2_http_out_transport_info_t *AXIS2_CALL + + axis2_iis_out_transport_info_create( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB); + + /** + * Free http_out_transport_info passed as void pointer. This will be + * cast into appropriate type and then pass the cast object + * into the http_out_transport_info structure's free method + */ + void AXIS2_CALL + axis2_iis_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env); + + axis2_char_t *axis2_iis_out_transport_get_content( + axis2_http_out_transport_info_t * out_transport_info); + +#ifdef __cplusplus +} +#endif +#endif /* AXIS2_IIS_OUT_TRANSPORT_INFO_H */ diff --git a/src/core/transport/http/server/IIS/axis2_iis_regedit.js b/src/core/transport/http/server/IIS/axis2_iis_regedit.js new file mode 100644 index 0000000..3889c1e --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_regedit.js @@ -0,0 +1,84 @@ +var WshShell = WScript.CreateObject("WScript.Shell");
+
+/* You can change the following values to suite your requirements */
+/* Axis2/C repo location. axis2.xml, modules folder and services folder should be in this dir */
+var axis2c_home = WshShell.CurrentDirectory;
+/* Log level. Possible values are trace, error, info, critical, user, debug and warning */
+var log_level = "debug";
+/* Full path to the log file */
+var log_file = axis2c_home + "/logs/axis2.log";
+/* Services URL prefix. This is the folder where services are hosted. Optional */
+var services_url_prefix;
+/* Max log file size */
+var max_log_file_size;
+/* Axis2 location */
+var axis2_location;
+
+/* Don't change anything below */
+var axis2c_home_str = "axis2c_home";
+var log_level_str = "log_level";
+var log_file_str = "log_file";
+var services_url_prefix_str = "services_url_prefix";
+var max_log_file_size_str = "max_log_file_size";
+var axis2_location_str = "axis2_location"
+
+var reg_location = "HKLM\\Software\\Apache Axis2C\\IIS ISAPI Redirector\\"
+/* If specified get the values from the command prompt */
+var args = WScript.Arguments;
+if (args.length > 0) {
+ axis2c_home = args.Item(0);
+ if (axis2c_home) {
+ log_file = axis2c_home + "/logs/axis2.log";
+ }
+}
+if (args.length > 1) {
+ log_level = args.Item(1);
+}
+if (args.length > 2) {
+ log_file = args.Item(2);
+}
+if (args.length > 3) {
+ services_url_prefix = args.Item(3);
+}
+if (args.length > 4) {
+ max_log_file_size = args.Item(4);
+}
+if (args.length > 5) {
+ axis2_location = args.Item(5);
+}
+/* Write the axis2c_home entry. This is used by Axis2/C to find the repo location */
+WshShell.RegWrite (reg_location + axis2c_home_str, axis2c_home, "REG_SZ");
+/* Write the log_level registry entry */
+WshShell.RegWrite (reg_location + log_level_str, log_level, "REG_SZ");
+/* Write the log file name */
+WshShell.RegWrite (reg_location + log_file_str, log_file, "REG_SZ");
+/* Write the services url prefix. We write this only if specified */
+try {
+ var services_url_prefix_key = WshShell.RegRead (reg_location + services_url_prefix_str);
+ if (services_url_prefix_key) {
+ WshShell.RegDelete (reg_location + services_url_prefix_str);
+ }
+} catch (e) {}
+if (services_url_prefix) {
+ WshShell.RegWrite (reg_location + services_url_prefix_str, services_url_prefix, "REG_SZ");
+}
+/* We write max_log_file_size only if specified */
+try {
+ var max_log_file_size_key = WshShell.RegRead (reg_location + max_log_file_size_str);
+ if (max_log_file_size_key) {
+ WshShell.RegDelete (reg_location + max_log_file_size_str);
+ }
+} catch (e) {}
+if (max_log_file_size) {
+ WshShell.RegWrite (reg_location + max_log_file_size_str, max_log_file_size, "REG_SZ");
+}
+
+try{
+ var axis2_location_key = WshShell.RegRead (reg_location + axis2_location_str);
+ if (axis2_location_key) {
+ WshShell.RegDelete (reg_location + axis2_location_str);
+ }
+} catch (e) {}
+if (axis2_location) {
+ WshShell.RegWrite (reg_location + axis2_location_str, axis2_location, "REG_SZ");
+}
\ No newline at end of file diff --git a/src/core/transport/http/server/IIS/axis2_iis_stream.c b/src/core/transport/http/server/IIS/axis2_iis_stream.c new file mode 100644 index 0000000..90fc8ba --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_stream.c @@ -0,0 +1,313 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string.h> +#include <stdlib.h> +#include "axis2_iis_stream.h" +#include <httpext.h> + +/** + * @brief Stream struct impl + * Streaming mechanisms for iis web server + */ + +typedef struct iis_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + LPEXTENSION_CONTROL_BLOCK lpECB; + unsigned int cur_pos; + void *cur_position; +} iis_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((iis_stream_impl_t *)(stream)) + +axutil_stream_type_t AXIS2_CALL +iis_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL iis_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL iis_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL iis_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL iis_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +axutil_stream_t *AXIS2_CALL +axutil_stream_create_iis( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + iis_stream_impl_t *stream_impl = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, lpECB, NULL); + + stream_impl = (iis_stream_impl_t *)AXIS2_MALLOC(env->allocator, sizeof(iis_stream_impl_t)); + + if(!stream_impl) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + stream_impl->cur_pos = 0; + stream_impl->cur_position = NULL; + stream_impl->lpECB = lpECB; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, iis_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, iis_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, iis_stream_skip); + + return &(stream_impl->stream); +} + +int AXIS2_CALL +iis_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + void *temp_buff = NULL; + unsigned int data_to_read = 0; + DWORD ret_val = TRUE; + DWORD read_bytes = (DWORD)count; + iis_stream_impl_t *stream_impl = NULL; + char *temp = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = (iis_stream_impl_t *)stream; + + if(stream_impl->cur_pos == 0) + stream_impl->cur_position = stream_impl->lpECB->lpbData; + + /* If this is the case all the bytes are in the lpECB->lpbData buffer*/ + if(stream_impl->lpECB->cbAvailable == stream_impl->lpECB->cbTotalBytes) + { + /* Cannot read more than in the buffer.*/ + if(count + stream_impl->cur_pos <= stream_impl->lpECB->cbAvailable) + data_to_read = (unsigned)count; + else + data_to_read = stream_impl->lpECB->cbTotalBytes - stream_impl->cur_pos; + + memcpy(buffer, stream_impl->cur_position, data_to_read); + temp = (char *)(stream_impl->cur_position); + temp += data_to_read; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += data_to_read; + read_bytes = data_to_read; + } + else if(stream_impl->lpECB->cbAvailable == -1) + { + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, buffer, &read_bytes); + } + else if(stream_impl->lpECB->cbAvailable < stream_impl->lpECB->cbTotalBytes) + { + if(stream_impl->cur_pos > stream_impl->lpECB->cbAvailable) + { + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, buffer, + &read_bytes); + } + else if(stream_impl->cur_pos + count > stream_impl->lpECB->cbAvailable + && stream_impl->cur_pos < stream_impl->lpECB->cbAvailable) + { + int read_length = 0; + if(count + stream_impl->cur_pos <= stream_impl->lpECB->cbAvailable) + read_length = (unsigned)count; + else + read_length = stream_impl->lpECB->cbTotalBytes - stream_impl->cur_pos; + data_to_read = stream_impl->lpECB->cbAvailable - stream_impl->cur_pos; + memcpy(buffer, stream_impl->cur_position, data_to_read); + + read_bytes = stream_impl->cur_pos + read_length - stream_impl->lpECB->cbAvailable; + temp_buff = malloc(read_bytes); + + if(temp_buff == NULL) + return data_to_read; + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, + &read_bytes); + memcpy(((char *)buffer + data_to_read), temp_buff, read_bytes); + read_bytes += data_to_read; + temp = (char *)(stream_impl->cur_position); + temp += read_bytes; + stream_impl->cur_position = temp; + stream_impl->cur_pos += (unsigned)read_bytes; + } + else + { + memcpy(buffer, stream_impl->cur_position, count); + temp = (char *)(stream_impl->cur_position); + temp += count; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += (unsigned)count; + read_bytes = (int)count; + } + } + if(ret_val == TRUE) + return read_bytes; + else + return -1; +} + +int AXIS2_CALL +iis_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + DWORD ret_val = NO_ERROR; + unsigned long bytes_sent = 0; + iis_stream_impl_t *stream_impl = NULL; + axis2_char_t *buffer = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + buffer = (axis2_char_t *)buf; + bytes_sent = (unsigned)strlen(buffer); + + if(count <= 0) + { + return (int)count; + } + /* assume that buffer is not null terminated */ + ret_val = stream_impl->lpECB->WriteClient(stream_impl->lpECB->ConnID, buffer, &bytes_sent, + HSE_IO_SYNC); + if(ret_val == TRUE) + return (int)bytes_sent; + else + return -1; +} + +int AXIS2_CALL +iis_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + DWORD ret_val = TRUE; + iis_stream_impl_t *stream_impl = NULL; + void *temp_buff = NULL; + int data_to_read = 0; + DWORD read_bytes = (DWORD)count; + char *temp = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = (iis_stream_impl_t *)stream; + + if(stream_impl->cur_pos == 0) + stream_impl->cur_position = stream_impl->lpECB->lpbData; + + if(stream_impl->lpECB->cbAvailable == stream_impl->lpECB->cbTotalBytes) + { + if(count + stream_impl->cur_pos <= stream_impl->lpECB->cbAvailable) + data_to_read = count; + else + data_to_read = stream_impl->lpECB->cbAvailable - stream_impl->cur_pos; + + temp = (char *)(stream_impl->cur_position); + temp += data_to_read; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += data_to_read; + read_bytes = data_to_read; + } + else if(stream_impl->lpECB->cbAvailable == -1) + { + temp_buff = malloc(read_bytes); + ret_val + = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, &read_bytes); + free(temp_buff); + } + else if(stream_impl->lpECB->cbAvailable < stream_impl->lpECB->cbTotalBytes) + { + if(stream_impl->cur_pos > stream_impl->lpECB->cbAvailable) + { + temp_buff = malloc(read_bytes); + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, + &read_bytes); + free(temp_buff); + } + else if(stream_impl->cur_pos + count > stream_impl->lpECB->cbAvailable + && stream_impl->cur_pos < stream_impl->lpECB->cbAvailable) + { + data_to_read = stream_impl->lpECB->cbAvailable - stream_impl->cur_pos; + read_bytes = stream_impl->cur_pos + count - stream_impl->lpECB->cbAvailable; + temp_buff = malloc(read_bytes); + + if(temp_buff == NULL) + return data_to_read; + + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, + &read_bytes); + read_bytes += data_to_read; + free(temp_buff); + } + else + { + temp = (char *)(stream_impl->cur_position); + temp += count; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += count; + read_bytes = count; + } + } + if(ret_val == FALSE) + { + return -1; + } + return read_bytes; +} + +int AXIS2_CALL +iis_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +iis_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} diff --git a/src/core/transport/http/server/IIS/axis2_iis_stream.h b/src/core/transport/http/server/IIS/axis2_iis_stream.h new file mode 100644 index 0000000..091edb0 --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_stream.h @@ -0,0 +1,45 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IIS_STREAM_H +#define IIS_STREAM_H + +#include <axis2_const.h> +#include <axis2_defines.h> +#include <axutil_env.h> +#include <axutil_stream.h> +#include <httpext.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** brief Constructor for creating IIS stream + * @return axutil_stream (IIS) + */ + axutil_stream_t *AXIS2_CALL + axutil_stream_create_iis( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB); + +#ifdef __cplusplus +} +#endif + +#endif /* IIS_STREAM_H */ diff --git a/src/core/transport/http/server/IIS/axis2_iis_worker.c b/src/core/transport/http/server/IIS/axis2_iis_worker.c new file mode 100644 index 0000000..51a6cc8 --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_worker.c @@ -0,0 +1,607 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <axis2_http_transport.h> +#include <axis2_conf.h> +#include <axutil_string.h> +#include <axis2_msg_ctx.h> +#include <axis2_http_out_transport_info.h> +#include <axis2_http_transport_utils.h> +#include <axis2_op_ctx.h> +#include <axis2_engine.h> +#include <axutil_uuid_gen.h> +#include <axis2_conf_init.h> +#include <axutil_url.h> +#include <axiom_soap.h> +#include "axis2_iis_out_transport_info.h" +#include "axis2_iis_stream.h" +#include "axis2_iis_worker.h" + +/* Files from iis */ +#include <httpfilt.h> +#include <httpext.h> + +#include "axis2_iis_constants.h" + +#define READ_SIZE 2048 + +axis2_status_t AXIS2_CALL +axis2_worker_get_original_url( + char url[], + char ret_url[]); + +axis2_char_t * AXIS2_CALL +axis2_iis_worker_get_bytes( + const axutil_env_t * env, + axutil_stream_t * stream); + +axis2_status_t AXIS2_CALL +start_response( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB, + int status, + const char *reason, + axutil_array_list_t *headers); + +axis2_status_t +write_response( + LPEXTENSION_CONTROL_BLOCK lpECB, + const void *b, + unsigned int l); + +axutil_hash_t * +axis2_iis_worker_read_http_headers( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB); + +AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + +static struct reasons +{ + axis2_char_t * status_code; + int status_len; +} reasons[] = { { "200 OK", 6 }, { "202 Accepted", 12 }, { "500 Internal Server Error", 25 } }; + +struct axis2_iis_worker +{ + axis2_conf_ctx_t * conf_ctx; +}; + +char * +status_reason( + int status); + +axis2_iis_worker_t * AXIS2_CALL +axis2_iis_worker_create( + const axutil_env_t * env, + axis2_char_t * repo_path) +{ + axis2_iis_worker_t * iis_worker = NULL; + + iis_worker = (axis2_iis_worker_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_iis_worker_t)); + if(!iis_worker) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + iis_worker->conf_ctx = axis2_build_conf_ctx(env, repo_path); + if(!iis_worker->conf_ctx) + { + axis2_iis_worker_free((axis2_iis_worker_t *)iis_worker, env); + return NULL; + } + return iis_worker; +} + +void AXIS2_CALL +axis2_iis_worker_free( + axis2_iis_worker_t * iis_worker, + const axutil_env_t * env) +{ + if(iis_worker->conf_ctx) + { + axis2_conf_ctx_free(iis_worker->conf_ctx, env); + iis_worker->conf_ctx = NULL; + } + AXIS2_FREE(env->allocator, iis_worker); + return; +} + +int AXIS2_CALL +axis2_iis_worker_process_request( + axis2_iis_worker_t * iis_worker, + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + axis2_conf_ctx_t * conf_ctx = NULL; + axutil_stream_t * out_stream = NULL; + axis2_transport_out_desc_t * out_desc = NULL; + axis2_transport_in_desc_t * in_desc = NULL; + axis2_char_t soap_action[INTERNET_MAX_URL_LENGTH]; + axis2_char_t original_url[INTERNET_MAX_URL_LENGTH]; + axis2_char_t req_url[INTERNET_MAX_URL_LENGTH]; + DWORD cbSize = 0; + CHAR server_name[MAX_SERVERNAME]; + axis2_char_t port[MAX_TCP_PORT_LEN]; + axis2_char_t redirect_url[INTERNET_MAX_PATH_LENGTH]; + axis2_char_t accept_language[INTERNET_MAX_PATH_LENGTH]; + axutil_hash_t *headers = NULL; + axis2_char_t peer_ip[50]; + axis2_char_t accept_header[INTERNET_MAX_URL_LENGTH]; + axis2_char_t accept_charset[INTERNET_MAX_URL_LENGTH]; + /*axutil_property_t *peer_property = NULL;*/ + + axis2_http_header_t *content_type_header = NULL; + axis2_http_header_t *content_length_header = NULL; + + /* New Code variables */ + axis2_http_transport_in_t request; + axis2_http_transport_out_t response; + + /* initialize tranport in structure */ + axis2_http_transport_utils_transport_in_init(&request, env); + + /* initialize tranport out structure */ + axis2_http_transport_utils_transport_out_init(&response, env); + + soap_action[0] = '\0'; + + /*Check the parameters*/ + if(!lpECB) + { + AXIS2_ERROR_SET_ERROR_NUMBER(env->error, AXIS2_ERROR_INVALID_NULL_PARAM); + return AXIS2_FAILURE; + } + conf_ctx = iis_worker->conf_ctx; + if(!conf_ctx) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_CONFIGURATION_CONTEXT, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "SERVER_NAME", server_name, &cbSize) == FALSE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get server name from IIS."); + return AXIS2_FAILURE; + } + cbSize = MAX_TCP_PORT_LEN; + if(lpECB->GetServerVariable(lpECB->ConnID, "SERVER_PORT", port, &cbSize) == FALSE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get server port from IIS."); + return AXIS2_FAILURE; + } + request.svr_port = port; + + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_URL", redirect_url, &cbSize) == FALSE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get server port from IIS."); + return AXIS2_FAILURE; + } + + /* We have a mapped URL only when the server version is 5 or less than that. */ + if(server_version <= 5) + { + axis2_worker_get_original_url(redirect_url, original_url); + /* create the url using the above variables */ + sprintf(req_url, "%s%s%s%s%s", "http://", server_name, ":", port, original_url); + } + else + { + sprintf(req_url, "%s%s%s%s%s", "http://", server_name, ":", port, redirect_url); + } + /* Set the request url */ + request.request_uri = req_url; + + out_stream = axutil_stream_create_basic(env); + out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(iis_worker->conf_ctx, env), + env, AXIS2_TRANSPORT_ENUM_HTTP); + in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(iis_worker->conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + + /* Create the in message context */ + request.msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc); + axis2_msg_ctx_set_server_side(request.msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_transport_out_stream(request.msg_ctx, env, out_stream); + + /* Get the SOAPAction Header */ + cbSize = INTERNET_MAX_URL_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_SOAPAction", soap_action, &cbSize)) + { + request.soap_action = soap_action; + } + + /* Create the in stream */ + request.in_stream = axutil_stream_create_iis(env, lpECB); + if(!request.in_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occured in creating input stream."); + return AXIS2_FAILURE; + } + + /* Get the Remote Adrress */ + if(lpECB->GetServerVariable(lpECB->ConnID, "REMOTE_ADDR", peer_ip, &cbSize)) + { + request.remote_ip = peer_ip; + } + + /* Set the http headers into the message context */ + headers = axis2_iis_worker_read_http_headers(env, lpECB); + if(axis2_msg_ctx_set_transport_headers(request.msg_ctx, env, headers) == AXIS2_FAILURE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "IIS: Error occured in setting transport headers."); + } + /* Set the content length */ + request.content_length = lpECB->cbTotalBytes; + /* Set the HTTP method */ + if(axutil_strcasecmp(lpECB->lpszMethod, "POST") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_POST; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "GET") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_GET; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "HEAD") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_HEAD; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "PUT") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_PUT; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "DELETE") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_DELETE; + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "IIS: Unsupported HTTP Method."); + return AXIS2_FAILURE; + } + /* Set the URL prefix. axis2_request_url_prefix is a global variable set at the init time */ + request.request_url_prefix = axis2_request_url_prefix; + /* Create the transport out info */ + request.out_transport_info = axis2_iis_out_transport_info_create(env, lpECB); + /* Set the content type */ + request.content_type = lpECB->lpszContentType; + + /* Get accept headaer */ + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_Accept", accept_header, &cbSize)) + { + request.accept_header = accept_header; + } + + /* Get the accept langauge */ + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_Accept-Language", accept_language, &cbSize)) + { + request.accept_language_header = accept_language; + } + + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_Accept-Charset", accept_charset, &cbSize)) + { + request.accept_charset_header = accept_charset; + } + + /* Now we have set everything. We can call process method to process the request */ + if(axis2_http_transport_utils_process_request(env, conf_ctx, &request, &response) + == AXIS2_FAILURE) + { + return AXIS2_FAILURE; + } + + /* Write the response */ + if(response.response_data && response.response_data_length > 0) + { + axis2_char_t content_length_str[16] = { 0 }; + axis2_bool_t is_out_headers_created = AXIS2_FALSE; + if(!response.output_headers) + { + response.output_headers = axutil_array_list_create(env, 2); + is_out_headers_created = AXIS2_TRUE; + } + sprintf(content_length_str, "%d", response.response_data_length); + if(!response.content_type) + { + content_type_header = axis2_http_header_create(env, "Content-Type", + axis2_iis_out_transport_get_content(request.out_transport_info)); + } + else + { + content_type_header = axis2_http_header_create(env, "Content-Type", + response.content_type); + } + content_length_header = axis2_http_header_create(env, "Content-Length", content_length_str); + axutil_array_list_add(response.output_headers, env, content_length_header); + axutil_array_list_add(response.output_headers, env, content_type_header); + /* Write the headers */ + start_response(env, lpECB, response.http_status_code, response.http_status_code_name, + response.output_headers); + /* Write the response body */ + if(write_response(lpECB, response.response_data, response.response_data_length) + == AXIS2_FAILURE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "IIS: Writing data to IIS"); + return AXIS2_FAILURE; + } + if(is_out_headers_created) + { + if(content_length_header) + { + axis2_http_header_free(content_length_header, env); + } + if(content_type_header) + { + axis2_http_header_free(content_type_header, env); + } + axutil_array_list_free(response.output_headers, env); + } + } + else + { + /* If we don't have a body we should write the HTTP headers */ + start_response(env, lpECB, response.http_status_code, response.http_status_code_name, + response.output_headers); + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Response is NULL"); + } + + /* Do some cleaning */ + axis2_http_transport_utils_transport_in_uninit(&request, env); + axis2_http_transport_utils_transport_out_uninit(&response, env); + return AXIS2_SUCCESS; +} + +axis2_status_t +write_response( + LPEXTENSION_CONTROL_BLOCK lpECB, + const void *b, + unsigned int l) +{ + if(lpECB && b) + { + if(l) + { + unsigned int written = 0; + char *buf = (char *)b; + /* If couldn't write the data at onece try again until all the data is written.*/ + while(written < l) + { + DWORD try_to_write = l - written; + if(!lpECB-> WriteClient(lpECB->ConnID, buf + written, &try_to_write, 0)) + { + return AXIS2_FAILURE; + } + written += try_to_write; + } + } + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +axis2_status_t AXIS2_CALL +start_response( + const axutil_env_t *env, + LPEXTENSION_CONTROL_BLOCK lpECB, + int status, + const char *reason, + axutil_array_list_t *headers) +{ + static char crlf[3] = { (char)13, (char)10, '\0' }; + unsigned int num_of_headers = 0; + + if(status < 100 || status > 1000) + { + return AXIS2_FAILURE; + } + if(lpECB) + { + size_t len_of_status; + char *status_str; + char *headers_str; + + /* + * Create the status line + */ + if(reason) + { + status_str = (char *)_alloca((6 + strlen(reason)) * sizeof(char)); + sprintf(status_str, "%d %s", status, reason); + len_of_status = strlen(status_str); + } + else + { + switch(status) + { + case 200: + status_str = reasons[0].status_code; + len_of_status = reasons[0].status_len; + break; + case 202: + status_str = reasons[1].status_code; + len_of_status = reasons[1].status_len; + break; + case 500: + status_str = reasons[2].status_code; + len_of_status = reasons[2].status_len; + break; + default: + status_str = reasons[0].status_code; + len_of_status = reasons[0].status_len; + break; + } + } + /* + * Create response headers string + */ + if(headers && (num_of_headers = axutil_array_list_size(headers, env)) > 0) + { + size_t i, len_of_headers; + axis2_http_header_t *header = NULL; + for(i = 0, len_of_headers = 0; i < num_of_headers; i++) + { + header = axutil_array_list_get(headers, env, (int)i); + len_of_headers += strlen(axis2_http_header_get_name(header, env)); + len_of_headers += strlen(axis2_http_header_get_value(header, env)); + len_of_headers += 4; /* extra for colon, space and crlf */ + } + len_of_headers += 3; /* crlf and terminating null char */ + headers_str = (char *)_alloca(len_of_headers * sizeof(char)); + headers_str[0] = '\0'; + for(i = 0; i < num_of_headers; i++) + { + header = axutil_array_list_get(headers, env, (int)i); + strcat(headers_str, axis2_http_header_get_name(header, env)); + strcat(headers_str, ": "); + strcat(headers_str, axis2_http_header_get_value(header, env)); + strcat(headers_str, "\r\n"); + } + strcat(headers_str, "\r\n"); + } + else + { + headers_str = crlf; + } + if(!lpECB-> ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, status_str, + (LPDWORD) & len_of_status, (LPDWORD)headers_str)) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +axis2_status_t AXIS2_CALL +axis2_worker_get_original_url( + char url[], + char ret_url[]) +{ + extern axis2_char_t *axis2_location; + strcpy(ret_url, axis2_location); + strcat(ret_url, &url[25]); + return URI_MATCHED; +} + +axis2_char_t * AXIS2_CALL +axis2_iis_worker_get_bytes( + const axutil_env_t * env, + axutil_stream_t * stream) +{ + axutil_stream_t * tmp_stream = NULL; + int return_size = -1; + axis2_char_t * buffer = NULL; + axis2_bool_t loop_state = AXIS2_TRUE; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, stream, NULL); + + tmp_stream = axutil_stream_create_basic(env); + while(loop_state) + { + int read = 0; + int write = 0; + char buf[READ_SIZE]; + + read = axutil_stream_read(stream, env, buf, READ_SIZE); + if(read < 0) + { + break; + } + write = axutil_stream_write(tmp_stream, env, buf, read); + if(read < (READ_SIZE - 1)) + { + break; + } + } + return_size = axutil_stream_get_len(tmp_stream, env); + if(return_size > 0) + { + buffer = (char *)AXIS2_MALLOC(env->allocator, sizeof(char) * (return_size + 2)); + return_size = axutil_stream_read(tmp_stream, env, buffer, return_size + 1); + buffer[return_size + 1] = '\0'; + } + axutil_stream_free(tmp_stream, env); + return buffer; +} + +/** Read all HTTP headers. + */ +axutil_hash_t * +axis2_iis_worker_read_http_headers( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + const char szHTTP_[] = "HTTP_"; + char szBuffer[4096]; + DWORD dwBufferSize = sizeof szBuffer; + axutil_hash_t *headers = NULL; + axis2_http_header_t* http_header = NULL; + + BOOL bGet = lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", szBuffer, &dwBufferSize); + if(bGet) + { + /* Find lines, split key/data pair and write them as output */ + LPTSTR pOpts = NULL; + LPTSTR pEnd = NULL; + LPTSTR pChar = NULL; + char szTmpBuf[512]; + char szTmpName[256]; + + headers = axutil_hash_make(env); + szTmpBuf[0] = 0; + for(pChar = szBuffer; '\0' != *pChar;) + { + if(*pChar == '\r' || *pChar == '\n') + { + pChar++; + continue; + } + pOpts = strchr(pChar, ':');/* findseparator */ + if(pOpts && *pOpts) + { + pEnd = pOpts; + while(*pEnd && *pEnd != '\r' && *pEnd != '\n') + { + pEnd++; + } + *pOpts = '\0'; /* split the strings */ + *pEnd = '\0'; + if(0 == strncmp(pChar, szHTTP_, strlen(szHTTP_))) + { + pChar += strlen(szHTTP_); + } + strcpy(szTmpName, pChar); + axutil_string_replace(szTmpName, '_', '-'); + http_header = axis2_http_header_create(env, szTmpName, pOpts + 1); + axutil_hash_set(headers, axutil_strdup(env, szTmpName), AXIS2_HASH_KEY_STRING, + http_header); + pChar = pEnd + 1; + } + } + } + else + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "axis2_iis_worker_read_http_headers: no http headers"); + } + return headers; +} + diff --git a/src/core/transport/http/server/IIS/axis2_iis_worker.h b/src/core/transport/http/server/IIS/axis2_iis_worker.h new file mode 100644 index 0000000..f9b6292 --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_worker.h @@ -0,0 +1,62 @@ +
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AXIS2_APACHE2_WORKER_H
+#define AXIS2_APACHE2_WORKER_H
+
+#include <axis2_const.h>
+#include <axis2_defines.h>
+#include <axutil_env.h>
+#include <axis2_conf_ctx.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+
+#endif /*
+ */
+
+typedef struct axis2_iis_worker axis2_iis_worker_t;
+
+int server_version;
+
+int AXIS2_CALL
+ axis2_iis_worker_process_request(
+ axis2_iis_worker_t * iis_worker,
+ const axutil_env_t * env,
+ void *r);
+
+
+void AXIS2_CALL
+ axis2_iis_worker_free(
+ axis2_iis_worker_t * iis_worker,
+ const axutil_env_t * env);
+
+
+axis2_iis_worker_t * AXIS2_CALL
+ axis2_iis_worker_create(
+ const axutil_env_t * env,
+ axis2_char_t * repo_path);
+
+
+#ifdef __cplusplus
+}
+#endif /*
+ */
+
+#endif /* AXIS2_IIS_WORKER_H */
diff --git a/src/core/transport/http/server/IIS/axis2_isapi_plugin.c b/src/core/transport/http/server/IIS/axis2_isapi_plugin.c new file mode 100644 index 0000000..eccfd1c --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_isapi_plugin.c @@ -0,0 +1,476 @@ +
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <httpfilt.h>
+#include <httpext.h>
+
+#include "axis2_iis_constants.h"
+#include "axis2_iis_worker.h"
+
+/* Axis headers */ +#include <axutil_error_default.h> +#include <axutil_log_default.h> +#include <axutil_thread_pool.h> +#include <axiom_xml_reader.h> +#include <axutil_log.h>
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
+#define AXIS2_IIS_LOG_FILE_TAG "log_file" +#define AXIS2_IIS_LOG_LEVEL_TAG "log_level" +#define AXIS2_IIS_REPO_PATH_TAG "axis2c_home" +#define AXIS2_IIS_EXTENSION_URI_TAG "extension_uri" +#define AXIS2_IIS_REDIRECT_WORD_TAG "redirect_uri" +#define AXIS2_IIS_AXIS2_LOCATION "axis2_location" +#define AXIS2_IIS_SERVICE_URL_PREFIX "services_url_prefix" + +#define AXIS2_IIS_LOG_TRACE_VERB "trace" +#define AXIS2_IIS_LOG_ERROR_VERB "error" +#define AXIS2_IIS_LOG_INFO_VERB "info" +#define AXIS2_IIS_LOG_USER_VERB "user" +#define AXIS2_IIS_LOG_CRITICAL_VERB "critical" +#define AXIS2_IIS_LOG_WARN_VERB "warning" +#define AXIS2_IIS_LOG_DEBUG_VERB "debug" + +#define MAX_FILE_PATH 256 +#define REGISTRY_LOCATION "Software\\Apache Axis2c\\IIS ISAPI Redirector" + +static int is_inited = FALSE; +static axis2_iis_worker_t *axis2_worker = NULL; +static const axutil_env_t *axutil_env = NULL; + +/* Configuration parameters */ +axis2_char_t *axis2_location = "/axis2"; +static axis2_char_t *axis2_service_url_prefix= "/services"; +static axis2_char_t repo_path[MAX_FILE_PATH]; +static axis2_char_t log_file[MAX_FILE_PATH]; +static axutil_log_levels_t log_level = AXIS2_LOG_LEVEL_CRITICAL; + +/* Path variables */ +static char szOriginalPath[_MAX_PATH + 1];
+static char szPath[_MAX_PATH + 1]; + +axis2_char_t general_error[] = "<html>\r\n"
+ "<head><title> An IIS server error occurred. </title></head>\r\n"
+ "<h1> An IIS server error occurred </h1>\r\n"
+ "<hr>\r\n"
+ "An error occurred in IIS while processing this request.</hr></html>"; + +axis2_char_t initializing_error[] = "<html>\r\n"
+ "<head><title> An IIS server error occurred. </title></head>\r\n"
+ "<h1> An IIS server error occurred </h1>\r\n"
+ "<hr>\r\n"
+ "An error occurred while initilizing Axis2/C.</hr></html>"; + + +/* + * This is a utility functipn for reading configuration data from the registery. + */ +static axis2_status_t AXIS2_CALL +read_registery_init_data(); + +/* + * Utility function for reading + */ +static axis2_status_t AXIS2_CALL get_registry_config_parameter( + HKEY hkey, + const char *tag, + char *b, + DWORD sz); + +/* + * Parse the given string and return the corresponding log_level + */ +axutil_log_levels_t AXIS2_CALL axis2_iis_parse_log_level(char level[]); +
+/*
+ * Initialize axis. This function is called in the begining of the module loading.
+ * It initializes the axis by reading values from the configuration and creating the
+ * required structures for the axis2c
+*/
+axis2_status_t AXIS2_CALL init_axis2();
+
+/*
+ * This is the function to be called after the processing
+ * is over for non Axis2 requets
+ */
+VOID
+WINAPI
+ExecUrlCompletion (
+ EXTENSION_CONTROL_BLOCK * pecb,
+ PVOID pContext,
+ DWORD cbIO,
+ DWORD dwError
+ );
+
+/*
+ * If somethign went wrong in the IIS server when
+ * we are proccessing we send this
+ */
+BOOL
+send_error(
+ EXTENSION_CONTROL_BLOCK * pecb,
+ CHAR error[]);
+
+axis2_status_t AXIS2_CALL init_axis2();
+
+BOOL
+WINAPI
+GetExtensionVersion(HSE_VERSION_INFO * pVer)
+{
+ pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR,
+ HSE_VERSION_MAJOR);
+ strncpy( pVer->lpszExtensionDesc,
+ "WildCardMap Sample ISAPI Extension", HSE_MAX_EXT_DLL_NAME_LEN );
+
+ pVer->lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN-1] = '\0';
+ server_version = 5;
+ return TRUE;
+}
+
+DWORD
+WINAPI
+HttpExtensionProc(EXTENSION_CONTROL_BLOCK * pecb)
+
+{
+ HSE_EXEC_URL_INFO ExecUrlInfo;
+ DWORD cbData = INTERNET_MAX_URL_LENGTH;
+ char url[INTERNET_MAX_URL_LENGTH];
+ axis2_bool_t is_for_us = AXIS2_TRUE;
+
+ /* Get the URL */
+ if ( pecb->GetServerVariable( pecb->ConnID,
+ "URL",
+ url,
+ &cbData ) == FALSE )
+ {
+ return HSE_STATUS_ERROR;
+ }
+
+ if (!is_inited)
+ {
+ DWORD dwBufferSize = 0;
+ axis2_char_t server_software[256];
+ axis2_char_t *version = NULL;
+
+ ZeroMemory(szOriginalPath, sizeof szOriginalPath);
+ dwBufferSize = sizeof szOriginalPath;
+
+#if _WIN32_WINNT >= 0x0502
+ GetDllDirectory( dwBufferSize, szOriginalPath );
+#else
+ GetCurrentDirectory( dwBufferSize, szOriginalPath );
+#endif
+ ZeroMemory(szPath, sizeof szPath);
+ dwBufferSize = sizeof szPath;
+ /* Get the current physical paht */
+ if (pecb->GetServerVariable(pecb->ConnID, "APPL_PHYSICAL_PATH", szPath, &dwBufferSize) == FALSE)
+ {
+ send_error(pecb, initializing_error);
+ return HSE_STATUS_ERROR;
+ }
+ /* Retrieve the server version */
+ dwBufferSize = 32;
+ if (pecb->GetServerVariable(pecb->ConnID, "SERVER_SOFTWARE", server_software, &dwBufferSize) == FALSE)
+ {
+ send_error(pecb, initializing_error);
+ return HSE_STATUS_ERROR;
+ }
+ version = axutil_strchr(server_software, '/');
+ if (version)
+ {
+ server_version = atoi(version + 1);
+ }
+#if _WIN32_WINNT >= 0x0502
+ SetDllDirectory( szPath );
+#else
+ SetCurrentDirectory( szPath );
+#endif
+ /* If we haven't initialized axis2/c before initialization failed */
+ if (AXIS2_FAILURE == init_axis2())
+ {
+ send_error(pecb, initializing_error);
+ return HSE_STATUS_ERROR;
+ }
+#if _WIN32_WINNT >= 0x0502
+ SetDllDirectory( szOriginalPath );
+#else
+ SetCurrentDirectory( szOriginalPath );
+#endif
+ }
+
+ /* Check weather we have a request for Axis2/C */
+ if (server_version >= 6 && strlen(url) >= strlen(axis2_location))
+ {
+ int i = 0;
+ is_for_us = AXIS2_TRUE;
+ while (axis2_location[i] != '\0')
+ {
+ if (axis2_location[i] != (url)[i]) {
+ is_for_us = AXIS2_FALSE;
+ break;
+ }
+ i++;
+ }
+ if (url[i] != '/' && url[i] != '\0')
+ {
+ is_for_us = AXIS2_FALSE;
+ }
+ }
+
+ if (is_for_us)
+ {
+ /* Windows cannot find the correct dlls unless the path is set*/
+#if _WIN32_WINNT >= 0x0502
+ SetDllDirectory( szPath );
+#else
+ SetCurrentDirectory( szPath );
+#endif
+ pecb->dwHttpStatusCode = HTTP_INTERNAL_SERVER_ERROR;
+ /* We are sure that worker is not NULL since it is NULL init_axis2 would have failed */
+ axis2_iis_worker_process_request(axis2_worker, axutil_env, pecb);
+
+ /* Windows cannot find the correct dlls unless the dir is set
+ but we want to reset to previous dir after the load */
+#if _WIN32_WINNT >= 0x0502
+ SetDllDirectory( szOriginalPath );
+#else
+ SetCurrentDirectory( szOriginalPath );
+#endif
+ return HSE_STATUS_SUCCESS;
+ }
+ else if (server_version >= 6)
+ {
+ /* For IIS 5.1 or earlier this code is never executed. Since the URL is
+ redirected to Axis2/C by the Filter */
+
+ /* If not for Axis2/C let the request go to who ever wants it */
+ ExecUrlInfo.pszUrl = NULL; /* Use original request URL */
+ ExecUrlInfo.pszMethod = NULL; /* Use original request method */
+ ExecUrlInfo.pszChildHeaders = NULL; /* Use original request headers */
+ ExecUrlInfo.pUserInfo = NULL; /* Use original request user info */
+ ExecUrlInfo.pEntity = NULL; /* Use original request entity */
+
+ /* Provent recursion */
+ ExecUrlInfo.dwExecUrlFlags = HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR;
+
+ /* Associate the completion routine and the current URL with this request. */
+ if ( pecb->ServerSupportFunction( pecb->ConnID,
+ HSE_REQ_IO_COMPLETION,
+ ExecUrlCompletion,
+ NULL,
+ NULL) == FALSE )
+ {
+ return HSE_STATUS_ERROR;
+ }
+
+ /* Ok, now that everything is set up, let's call the child request */
+ if ( pecb->ServerSupportFunction( pecb->ConnID,
+ HSE_REQ_EXEC_URL,
+ &ExecUrlInfo,
+ NULL,
+ NULL ) == FALSE )
+ {
+ return HSE_STATUS_ERROR;
+ }
+ /* Return pending and let the completion clean up */
+ return HSE_STATUS_PENDING;
+ }
+ return HSE_STATUS_ERROR;
+}
+
+VOID
+WINAPI
+ExecUrlCompletion (
+ EXTENSION_CONTROL_BLOCK * pecb,
+ PVOID pContext,
+ DWORD cbIO,
+ DWORD dwError
+ )
+{
+ /* We are done so notify */
+ pecb->ServerSupportFunction(
+ pecb->ConnID,
+ HSE_REQ_DONE_WITH_SESSION,
+ NULL,
+ NULL,
+ NULL);
+}
+
+
+BOOL
+send_error(
+ EXTENSION_CONTROL_BLOCK * pecb,
+ axis2_char_t error[])
+{
+ DWORD cbData;
+ pecb->dwHttpStatusCode = 500;
+ /* Send headers and response */
+ pecb->ServerSupportFunction( pecb->ConnID,
+ HSE_REQ_SEND_RESPONSE_HEADER,
+ "500 Server Error",
+ NULL,
+ (LPDWORD)"Content-Type: text/html\r\n\r\n" );
+
+ cbData = axutil_strlen( error );
+ return pecb->WriteClient( pecb->ConnID,
+ error,
+ &cbData,
+ HSE_IO_SYNC );
+}
+
+axis2_status_t AXIS2_CALL read_registery_init_data() +{ + long rc = 0; + axis2_status_t ok = TRUE; + char tmpbuf[INTERNET_MAX_URL_LENGTH]; + HKEY hkey; + AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD) 0, KEY_READ, &hkey); + if (ERROR_SUCCESS != rc) + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_REPO_PATH_TAG, tmpbuf, sizeof(repo_path))) + { + strcpy(repo_path, tmpbuf); + } + else + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_LOG_FILE_TAG, tmpbuf, sizeof(log_file))) + { + strcpy(log_file, tmpbuf); + } + else + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_LOG_LEVEL_TAG, tmpbuf, sizeof(tmpbuf))) + { + log_level = axis2_iis_parse_log_level(tmpbuf); + } + else + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_SERVICE_URL_PREFIX, tmpbuf, sizeof(tmpbuf))) + { + axis2_request_url_prefix = _strdup(tmpbuf); + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_AXIS2_LOCATION, tmpbuf, sizeof(tmpbuf))) + { + axis2_location = _strdup(tmpbuf); + } + RegCloseKey(hkey); + return ok; +} + +axutil_log_levels_t AXIS2_CALL +axis2_iis_parse_log_level(char level[]) +{ + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_TRACE_VERB)) + { + return AXIS2_LOG_LEVEL_TRACE; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_DEBUG_VERB)) + { + return AXIS2_LOG_LEVEL_DEBUG; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_INFO_VERB)) + { + return AXIS2_LOG_LEVEL_INFO; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_USER_VERB)) + { + return AXIS2_LOG_LEVEL_USER; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_WARN_VERB)) + { + return AXIS2_LOG_LEVEL_WARNING; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_ERROR_VERB)) + { + return AXIS2_LOG_LEVEL_ERROR; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_CRITICAL_VERB)) + { + return AXIS2_LOG_LEVEL_CRITICAL; + } + return AXIS2_LOG_LEVEL_DEBUG; +} + +axis2_status_t AXIS2_CALL +get_registry_config_parameter(HKEY hkey, const char *tag, char *b, DWORD sz) +{ + DWORD type = 0; + LONG lrc; + + lrc = RegQueryValueEx(hkey, tag, (LPDWORD) 0, &type, (LPBYTE) b, &sz); + if ((ERROR_SUCCESS != lrc) || (type != REG_SZ)) + { + return FALSE; + } + b[sz] = '\0'; + return TRUE; +} + +/** + * This method initializes the axis2 engine. All the required variables are set to + * their initial values in this method. +*/ +axis2_status_t AXIS2_CALL init_axis2() +{ + /* + * These are the varibles required to initialize axis. + */ + axis2_status_t status = FALSE; + /* We need to init xml readers before we go into threaded env */ + if (!is_inited) + { + axiom_xml_reader_init(); + status = read_registery_init_data(); + if (status == AXIS2_FAILURE) + { + return AXIS2_FAILURE; + } + axutil_error_init(); + /* Initialize the environement */ + axutil_env = axutil_env_create_all(log_file, log_level); + if (!axutil_env) + { + return AXIS2_FAILURE; + } + axis2_worker = axis2_iis_worker_create(axutil_env, repo_path); + if (!axis2_worker) + { + return AXIS2_FAILURE; + } + is_inited = AXIS2_TRUE; + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} diff --git a/src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c b/src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c new file mode 100644 index 0000000..49cd6d9 --- /dev/null +++ b/src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c @@ -0,0 +1,153 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <httpfilt.h>
+
+#include <axis2_const.h>
+#include <axis2_defines.h>
+#include <axutil_env.h>
+#include <axutil_stream.h>
+
+#include "..\\axis2_iis_constants.h"
+
+#define REGISTRY_LOC "Software\\Apache Axis2c\\IIS ISAPI Redirector"
+#define AXIS2_IIS_AXIS2_LOC "axis2_location"
+static char *axis2_loc = "/axis2";
+
+static axis2_char_t redirect_word[INTERNET_MAX_URL_LENGTH] = "/axis2/mod_axis2_IIS.dll\?";
+/*
+ * Search a given uri to find weather it matches a uri for the axis2
+ * The uri format for axis2 is of the form
+ * scheme://server:port/axis2/other_parts
+ * This function search a give uri for the /axis2/. If a match
+ * is found it will replace the /axis2 part of the url with /axis2/mod_iis.dll?
+ */
+axis2_bool_t AXIS2_CALL
+get_extension_url(
+ char url[],
+ char ret_url[]);
+
+/*
+ * This function is called by the IIS server at the server
+ * initialization. So this is the ideal plcae for initializing
+ * axis2c.
+ */
+BOOL WINAPI
+GetFilterVersion(
+ PHTTP_FILTER_VERSION pVer)
+{
+ DWORD type = 0, size = 0;
+ LONG lrc = 0;
+ char tmpbuf[INTERNET_MAX_URL_LENGTH];
+ HKEY hkey;
+ ULONG http_filter_revision = HTTP_FILTER_REVISION;
+ pVer->dwFilterVersion = pVer->dwServerFilterVersion;
+ if(pVer->dwFilterVersion > http_filter_revision)
+ {
+ pVer->dwFilterVersion = http_filter_revision;
+ }
+
+ /*
+ Receive notifictions when
+ 1. Server preprocessed the headers.
+ 2. Log
+ 3. All the request coming in secure and none secure ports.
+ */
+ pVer->dwFlags = (SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_PREPROC_HEADERS | SF_NOTIFY_SECURE_PORT
+ | SF_NOTIFY_NONSECURE_PORT | SF_NOTIFY_AUTH_COMPLETE);
+
+ /* Give a short discription about the module.*/
+ strcpy(pVer->lpszFilterDesc, "axis2c filter");
+ /* Get the axis2 location from the registry configuration */
+ lrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOC, (DWORD)0, KEY_READ, &hkey);
+ if(ERROR_SUCCESS != lrc)
+ {
+ return FALSE;
+ }
+ size = INTERNET_MAX_URL_LENGTH;
+ lrc = RegQueryValueEx(hkey, AXIS2_IIS_AXIS2_LOC, (LPDWORD)0, &type, (LPBYTE)tmpbuf, &size);
+ if((ERROR_SUCCESS == lrc) && (type == REG_SZ))
+ {
+ tmpbuf[size] = '\0';
+ axis2_loc = _strdup(tmpbuf);
+ }
+ RegCloseKey(hkey);
+ return TRUE;
+}
+
+/*
+ When a notification happens this function is called by the IIS.
+ */
+DWORD WINAPI
+HttpFilterProc(
+ PHTTP_FILTER_CONTEXT pfc,
+ DWORD notificationType,
+ LPVOID pvNotification)
+{
+ DWORD bufferLength = INTERNET_MAX_URL_LENGTH;
+ char url[INTERNET_MAX_URL_LENGTH];
+ char modified_url[INTERNET_MAX_URL_LENGTH];
+
+ if(notificationType == SF_NOTIFY_PREPROC_HEADERS)
+ {
+ pfc->GetServerVariable(pfc, "HTTP_URL", url, &bufferLength);
+ if(get_extension_url(url, modified_url))
+ {
+ ((PHTTP_FILTER_PREPROC_HEADERS)pvNotification)->SetHeader(pfc, "url", modified_url);
+ return SF_STATUS_REQ_HANDLED_NOTIFICATION;
+ }
+ }
+ return SF_STATUS_REQ_NEXT_NOTIFICATION;
+}
+
+axis2_bool_t AXIS2_CALL
+get_extension_url(
+ char url[],
+ char ret_url[])
+{
+ axis2_bool_t is_for_us = AXIS2_FALSE;
+ int i = 0;
+ /* Should contain "/axis2/"*/
+ ret_url[0] = '\0';
+ if(strlen(url) >= strlen(axis2_loc))
+ {
+ is_for_us = AXIS2_TRUE;
+ while(axis2_loc[i] != '\0')
+ {
+ if(axis2_loc[i] != (url)[i])
+ {
+ is_for_us = AXIS2_FALSE;
+ break;
+ }
+ i++;
+ }
+ if(url[i] != '/' && url[i] != '\0')
+ {
+ is_for_us = AXIS2_FALSE;
+ }
+ }
+ if(is_for_us)
+ {
+ strcpy(ret_url, redirect_word);
+ strcat(ret_url, &url[i]);
+ }
+ return is_for_us;
+}
diff --git a/src/core/transport/http/server/IIS/mod_axis2.def b/src/core/transport/http/server/IIS/mod_axis2.def new file mode 100644 index 0000000..22205e7 --- /dev/null +++ b/src/core/transport/http/server/IIS/mod_axis2.def @@ -0,0 +1,7 @@ +LIBRARY "mod_axis2_IIS"
+
+EXPORTS
+ GetExtensionVersion
+ HttpExtensionProc
+ GetFilterVersion
+ HttpFilterProc
\ No newline at end of file diff --git a/src/core/transport/http/server/Makefile.am b/src/core/transport/http/server/Makefile.am new file mode 100644 index 0000000..07cf1e9 --- /dev/null +++ b/src/core/transport/http/server/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS=@APACHE2BUILD@ simple_axis2_server ${CGI_DIR} +EXTRA_DIST=IIS CGI diff --git a/src/core/transport/http/server/apache2/Makefile.am b/src/core/transport/http/server/apache2/Makefile.am new file mode 100644 index 0000000..d5f6bd8 --- /dev/null +++ b/src/core/transport/http/server/apache2/Makefile.am @@ -0,0 +1,40 @@ +lib_LTLIBRARIES = libmod_axis2.la +libmod_axis2_la_SOURCES = mod_axis2.c\ + apache2_stream.c\ + apache2_out_transport_info.c\ + apache2_worker.c + +AM_CFLAGS = -DLINUX=2 -D_REENTRANT -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_SVID_SOURCE -D_GNU_SOURCE + +libmod_axis2_la_LIBADD = $(LDFLAGS) \ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la \ + $(top_builddir)/src/core/engine/libaxis2_engine.la\ + $(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la\ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la\ + $(top_builddir)/axiom/src/parser/$(WRAPPER_DIR)/libaxis2_parser.la\ + -lpthread + +libmod_axis2_la_LDFLAGS = -version-info $(VERSION_NO) + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/transport/http \ + -I$(top_builddir)/src/core/description \ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/src/core/deployment \ + -I$(top_builddir)/axiom/include\ + -I$(top_builddir)/util/include\ + @APACHE2INC@ \ + @APRINC@ + +EXTRA_DIST=axis2_apache2_worker.h apache2_stream.h axis2_apache2_out_transport_info.h + + + + + + + + diff --git a/src/core/transport/http/server/apache2/apache2_out_transport_info.c b/src/core/transport/http/server/apache2/apache2_out_transport_info.c new file mode 100644 index 0000000..9deaa56 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_out_transport_info.c @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "axis2_apache2_out_transport_info.h" +#include <axutil_string.h> +#include <axis2_http_transport.h> +#include <axutil_string.h> +#include <apr_strings.h> + +typedef struct axis2_apache2_out_transport_info +{ + axis2_http_out_transport_info_t out_transport_info; + request_rec *request; + axis2_char_t *encoding; +} axis2_apache2_out_transport_info_t; + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_apache2_out_transport_info_t *)(out_transport_info)) + +void AXIS2_CALL +axis2_apache2_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + AXIS2_ENV_CHECK(env, void); + transport_info_l = (axis2_http_out_transport_info_t *)transport_info; + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_free( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env) +{ + axis2_apache2_out_transport_info_t *info = NULL; + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + info->request = NULL; /* request doesn't belong to info */ + if(info->encoding) + { + AXIS2_FREE(env->allocator, info->encoding); + info->encoding = NULL; + } + + AXIS2_FREE(env->allocator, info); + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_content_type( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_apache2_out_transport_info_t *info = NULL; + + axis2_char_t *tmp1 = NULL; + axis2_char_t *tmp2 = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + if(info->encoding) + { + + tmp1 = axutil_stracat(env, content_type, ";charset="); + tmp2 = axutil_stracat(env, tmp1, info->encoding); + info->request->content_type = apr_pstrdup(info->request->pool, tmp2); + AXIS2_FREE(env->allocator, tmp1); + AXIS2_FREE(env->allocator, tmp2); + } + else + { + info->request->content_type = apr_pstrdup(info->request->pool, content_type); + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + + if(info->encoding) + { + AXIS2_FREE(env->allocator, info->encoding); + } + info->encoding = axutil_strdup(env, encoding); + + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_cookie_header( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * cookie_header) +{ + axis2_apache2_out_transport_info_t *info = NULL; + + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, cookie_header, AXIS2_FAILURE); + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + apr_table_set(info->request->headers_out, AXIS2_HTTP_HEADER_SET_COOKIE, cookie_header); + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_session( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * session_id, + const axis2_char_t * session_value) +{ + axis2_apache2_out_transport_info_t *info = NULL; + axis2_status_t status = AXIS2_SUCCESS; + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, session_id, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, session_value, AXIS2_FAILURE); + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + status = env->set_session_fn(info->request, session_id, session_value); + + return status; +} + +axis2_http_out_transport_info_t *AXIS2_CALL +axis2_apache2_out_transport_info_create( + const axutil_env_t * env, + request_rec * request) +{ + axis2_apache2_out_transport_info_t *info = NULL; + axis2_http_out_transport_info_t *out_transport_info = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + info = (axis2_apache2_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_apache2_out_transport_info_t)); + + if(!info) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + info->request = request; + info->encoding = NULL; + + out_transport_info = &(info->out_transport_info); + out_transport_info->encoding = NULL; + out_transport_info->response = NULL; + + axis2_http_out_transport_info_set_char_encoding_func(out_transport_info, env, + axis2_apache_out_transport_info_set_char_encoding); + axis2_http_out_transport_info_set_content_type_func(out_transport_info, env, + axis2_apache_out_transport_info_set_content_type); + axis2_http_out_transport_info_set_cookie_header_func(out_transport_info, env, + axis2_apache_out_transport_info_set_cookie_header); + axis2_http_out_transport_info_set_session_func(out_transport_info, env, + axis2_apache_out_transport_info_set_session); + + return out_transport_info; +} + + diff --git a/src/core/transport/http/server/apache2/apache2_stream.c b/src/core/transport/http/server/apache2/apache2_stream.c new file mode 100644 index 0000000..5e189a7 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_stream.c @@ -0,0 +1,292 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string.h> +#include <stdlib.h> +#include "apache2_stream.h" +#include <http_protocol.h> + +typedef struct apache2_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + request_rec *request; +} apache2_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((apache2_stream_impl_t *)(stream)) + +axutil_stream_type_t AXIS2_CALL +apache2_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL apache2_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL apache2_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +static int AXIS2_CALL +apache2_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL apache2_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +static apr_size_t +apache2_ap_get_client_block( + request_rec *r, + char* buffer, + apr_size_t bufsiz); + +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axutil_stream_create_apache2( + const axutil_env_t * env, + request_rec * request) +{ + apache2_stream_impl_t *stream_impl = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, request, NULL); + + stream_impl = (apache2_stream_impl_t *)AXIS2_MALLOC(env->allocator, + sizeof(apache2_stream_impl_t)); + + if(!stream_impl) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset(&(stream_impl->stream), 0, sizeof(axutil_stream_t)); + + stream_impl->request = request; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, apache2_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, apache2_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, apache2_stream_skip); + + return &(stream_impl->stream); +} + +int AXIS2_CALL +apache2_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + apache2_stream_impl_t *stream_impl = NULL; + size_t read = 0; + size_t len = 0; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + while(count - len > 0) + { + read = apache2_ap_get_client_block(stream_impl->request, (char *) buffer + len, + count - len); + if(read > 0) + { + len += read; + } + else + { + break; + } + } + + return (int)len; + /* We are sure that the difference lies within the int range */ +} + +int AXIS2_CALL +apache2_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + apache2_stream_impl_t *stream_impl = NULL; + axis2_char_t *buffer = NULL; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + buffer = (axis2_char_t *)buf; + if(count <= 0) + { + return (int)count; + /* We are sure that the difference lies within the int range */ + } + /* assume that buffer is not null terminated */ + return ap_rwrite(buffer, (int)count, stream_impl->request); + /* We are sure that the difference lies within the int range */ +} + +static int AXIS2_CALL +apache2_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + apache2_stream_impl_t *stream_impl = NULL; + axis2_char_t *tmp_buffer = NULL; + apr_size_t len = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + tmp_buffer = AXIS2_MALLOC(env->allocator, count * sizeof(axis2_char_t)); + if(tmp_buffer == NULL) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return -1; + } + len = apache2_ap_get_client_block(stream_impl->request, tmp_buffer, count); + AXIS2_FREE(env->allocator, tmp_buffer); + return (int)len; + +} + +int AXIS2_CALL +apache2_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +apache2_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} + +/* + * This is a re-write of get_client_block found in http_filters.c in httpd + * which does not work when dealing with compressed payloads (or any other input + * filters that could potentially return 0 bytes of filtered data and not be at + * the end of the stream). + * get_client_block is called in a loop to get the request message body. + * This is quite simple if the client includes a content-length + * (the normal case), but gets messy if the body is chunked. Note that + * r->remaining is used to maintain state across calls and that + * r->read_length is the total number of bytes given to the caller + * across all invocations. It is messy because we have to be careful not + * to read past the data provided by the client, since these reads block. + * Returns 0 on End-of-body, -1 on error or premature chunk end. + * + */ +static apr_size_t +apache2_ap_get_client_block( + request_rec *r, + char *buffer, + apr_size_t bufsiz) +{ + apr_status_t rv; + apr_bucket_brigade *bb; + int loop = 1; + apr_size_t origBufSize = bufsiz; + + if (r->remaining < 0 || (!r->read_chunked && r->remaining == 0)) { + return 0; + } + + bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); + if (bb == NULL) { + r->connection->keepalive = AP_CONN_CLOSE; + return -1; + } + + /* we need to loop until the input filters (if any) give us data */ + while (loop) { + rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, + APR_BLOCK_READ, bufsiz); + + /* We lose the failure code here. This is why ap_get_client_block should + * not be used. + */ + if (rv != APR_SUCCESS) { + /* if we actually fail here, we want to just return and + * stop trying to read data from the client. + */ + r->connection->keepalive = AP_CONN_CLOSE; + apr_brigade_destroy(bb); + return -1; + } + + /* If this fails, it means that a filter is written incorrectly and that + * it needs to learn how to properly handle APR_BLOCK_READ requests by + * returning data when requested. + */ + AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(bb)); + + /* Check to see if EOS in the brigade. + * + * If so, we have to leave a nugget for the *next* ap_get_client_block + * call to return 0. + */ + if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { + if (r->read_chunked) { + r->remaining = -1; + } else { + r->remaining = 0; + } + } + + rv = apr_brigade_flatten(bb, buffer, &bufsiz); + if (rv != APR_SUCCESS) { + apr_brigade_destroy(bb); + return -1; + } + + /* XXX yank me? */ + r->read_length += bufsiz; + + /* it is possible that the entire bucket brigade is exhausted, but no data + * has been produced by the input filter (mod_deflate, for example).... + * in this scenario, we really need to keep looping + */ + if (bufsiz != 0 || r->remaining <= 0) { + loop = 0; + apr_brigade_destroy(bb); + } else { + if (bufsiz == 0) { + bufsiz = origBufSize; + } + } + + } + + return (long)bufsiz; +} diff --git a/src/core/transport/http/server/apache2/apache2_stream.h b/src/core/transport/http/server/apache2/apache2_stream.h new file mode 100644 index 0000000..abbea45 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_stream.h @@ -0,0 +1,46 @@ + +/* + * Copyright 2004,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain count copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APACHE2_STREAM_H +#define APACHE2_STREAM_H + +#include <axis2_const.h> +#include <axis2_defines.h> +#include <axutil_env.h> +#include <axutil_stream.h> +#include <httpd.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** \brief Constructor for creating apche2 stream + * @return axutil_stream (apache2) + */ + AXIS2_EXTERN axutil_stream_t *AXIS2_CALL + axutil_stream_create_apache2( + const axutil_env_t * env, + request_rec * req); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APACHE2_STREAM_H */ diff --git a/src/core/transport/http/server/apache2/apache2_worker.c b/src/core/transport/http/server/apache2/apache2_worker.c new file mode 100644 index 0000000..12b05b2 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_worker.c @@ -0,0 +1,1687 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "axis2_apache2_worker.h"
+#include <axis2_http_transport.h>
+#include <axis2_conf.h>
+#include <axutil_string.h>
+#include <axis2_msg_ctx.h>
+#include <axis2_http_out_transport_info.h>
+#include <axis2_http_transport_utils.h>
+#include <axis2_http_accept_record.h>
+#include <axis2_op_ctx.h>
+#include <axis2_engine.h>
+#include <axutil_uuid_gen.h>
+#include <axis2_conf_init.h>
+#include "axis2_apache2_out_transport_info.h"
+#include <axutil_url.h>
+#include <http_core.h>
+#include <http_protocol.h>
+#include <axiom_soap.h>
+#include <axutil_class_loader.h>
+#include <axutil_string_util.h>
+#include <axiom_mime_part.h>
+#include <axiom_mtom_sending_callback.h>
+
+#define READ_SIZE 2048
+
+static axis2_status_t
+apache2_worker_send_mtom_message(
+ request_rec *request,
+ const axutil_env_t * env,
+ axutil_array_list_t *mime_parts,
+ axis2_char_t *mtom_sending_callback_name);
+
+static axis2_status_t
+apache2_worker_send_attachment_using_file(
+ const axutil_env_t * env,
+ request_rec *request,
+ FILE *fp,
+ axis2_byte_t *buffer,
+ int buffer_size);
+
+static axis2_status_t
+apache2_worker_send_attachment_using_callback(
+ const axutil_env_t * env,
+ request_rec *request,
+ axiom_mtom_sending_callback_t *callback,
+ void *handler,
+ void *user_param);
+
+static axutil_hash_t*
+axis2_apache_worker_get_headers(
+ const axutil_env_t *env,
+ request_rec *request);
+
+
+struct axis2_apache2_worker
+{
+ axis2_conf_ctx_t *conf_ctx;
+};
+
+AXIS2_EXTERN axis2_apache2_worker_t *AXIS2_CALL
+axis2_apache2_worker_create(
+ const axutil_env_t * env,
+ axis2_char_t * repo_path)
+{
+ axis2_apache2_worker_t *apache2_worker = NULL;
+ axutil_hash_t* svc_map = NULL;
+ axis2_conf_t* conf = NULL;
+ axutil_hash_index_t *hi = NULL;
+ void* svc = NULL;
+ AXIS2_ENV_CHECK(env, NULL);
+ AXIS2_LOG_INFO(env->log, "[Axis2] Axis2 worker created");
+ apache2_worker = (axis2_apache2_worker_t *)AXIS2_MALLOC(env->allocator,
+ sizeof(axis2_apache2_worker_t));
+
+ if(!apache2_worker)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ return NULL;
+ }
+ apache2_worker->conf_ctx = axis2_build_conf_ctx(env, repo_path);
+
+ if(!apache2_worker->conf_ctx)
+ {
+ axis2_apache2_worker_free((axis2_apache2_worker_t *)apache2_worker, env);
+ return NULL;
+ }
+
+ /*
+ * we have to load all the services. This is because, before the fork (in linux)
+ * we should have a full code segment. Otherwise, we can't share function pointers of services
+ * between processed. In fork, the code segment will be duplicated across processes
+ */
+ conf = axis2_conf_ctx_get_conf(apache2_worker->conf_ctx, env);
+ if(!conf)
+ {
+ axis2_apache2_worker_free((axis2_apache2_worker_t *)apache2_worker, env);
+ return NULL;
+ }
+
+ svc_map = axis2_conf_get_all_svcs(conf, env);
+ if(!svc_map)
+ {
+ axis2_apache2_worker_free((axis2_apache2_worker_t *)apache2_worker, env);
+ return NULL;
+ }
+
+ for(hi = axutil_hash_first(svc_map, env); hi; hi = axutil_hash_next(env, hi))
+ {
+ void *impl_class = NULL;
+ axis2_msg_recv_t *msg_recv = NULL;
+ axutil_hash_t *ops_hash = NULL;
+
+ axutil_hash_this(hi, NULL, NULL, &svc);
+ if(!svc)
+ continue;
+ impl_class = axis2_svc_get_impl_class(svc, env);
+ if(impl_class)
+ continue;
+ ops_hash = axis2_svc_get_all_ops(svc, env);
+ if(ops_hash)
+ {
+ axutil_hash_index_t *op_hi = NULL;
+ void *op = NULL;
+ op_hi = axutil_hash_first(ops_hash, env);
+ if(op_hi)
+ {
+ axutil_hash_this(op_hi, NULL, NULL, &op);
+ if(op)
+ {
+ msg_recv = axis2_op_get_msg_recv(op, env);
+ if(msg_recv)
+ {
+ axis2_msg_recv_set_conf_ctx(msg_recv, env, apache2_worker->conf_ctx);
+ axis2_msg_recv_load_and_init_svc(msg_recv, env, svc);
+ }
+ }
+ }
+
+ }
+ }
+
+ AXIS2_LOG_INFO(env->log, "[Axis2] Axis2 worker created");
+
+ return apache2_worker;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axis2_apache2_worker_free(
+ axis2_apache2_worker_t * apache2_worker,
+ const axutil_env_t * env)
+{
+ AXIS2_ENV_CHECK(env, void);
+
+ if(apache2_worker->conf_ctx)
+ {
+ axis2_conf_ctx_free(apache2_worker->conf_ctx, env);
+ apache2_worker->conf_ctx = NULL;
+ }
+
+ AXIS2_FREE(env->allocator, apache2_worker);
+
+ return;
+}
+
+AXIS2_EXTERN int AXIS2_CALL
+axis2_apache2_worker_process_request(
+ axis2_apache2_worker_t * apache2_worker,
+ const axutil_env_t * env,
+ request_rec * request)
+{
+ axis2_conf_ctx_t *conf_ctx = NULL;
+ axis2_msg_ctx_t *msg_ctx = NULL;
+ axutil_stream_t *request_body = NULL;
+ axutil_stream_t *out_stream = NULL;
+ axis2_transport_out_desc_t *out_desc = NULL;
+ axis2_transport_in_desc_t *in_desc = NULL;
+ axis2_char_t *http_version = NULL;
+ axutil_string_t *soap_action = NULL;
+ axis2_char_t *soap_action_header_txt = NULL;
+ axis2_bool_t processed = AXIS2_FALSE;
+ int content_length = -1;
+ axis2_char_t *url_external_form = NULL;
+ axis2_char_t *body_string = NULL;
+ unsigned int body_string_len = 0;
+ int send_status = DECLINED;
+ axis2_char_t *content_type = NULL;
+ axis2_http_out_transport_info_t *apache2_out_transport_info = NULL;
+ axis2_char_t *ctx_uuid = NULL;
+ axis2_op_ctx_t *op_ctx = NULL;
+ axis2_char_t *peer_ip = NULL;
+ axutil_property_t *peer_property = NULL;
+ axutil_url_t *request_url = NULL;
+ axis2_char_t *accept_header_value = NULL;
+ axis2_char_t *accept_charset_header_value = NULL;
+ axis2_char_t *accept_language_header_value = NULL;
+ axis2_char_t *content_language_header_value = NULL;
+ axis2_bool_t do_mtom = AXIS2_FALSE;
+ axutil_array_list_t *mime_parts = NULL;
+ axutil_param_t *callback_name_param = NULL;
+ axis2_char_t *mtom_sending_callback_name = NULL;
+ axis2_char_t *cookie = NULL;
+ axis2_char_t *header_value = NULL;
+ axis2_status_t status = AXIS2_FAILURE;
+ axutil_hash_t *headers = NULL;
+
+ AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE);
+ AXIS2_PARAM_CHECK(env->error, request, AXIS2_CRITICAL_FAILURE);
+
+ conf_ctx = apache2_worker->conf_ctx;
+
+ if(!conf_ctx)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_CONFIGURATION_CONTEXT, AXIS2_FAILURE);
+ return AXIS2_CRITICAL_FAILURE;
+ }
+ content_length = (int)request->remaining;
+ /* We are sure that the difference lies within the int range */
+ http_version = request->protocol;
+
+ request_url = axutil_url_create(env, "http", request->hostname, request->parsed_uri.port,
+ request->unparsed_uri);
+ if(request_url)
+ {
+ url_external_form = axutil_url_to_external_form(request_url, env);
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, url_external_form);
+ axutil_url_free(request_url, env);
+ request_url = NULL;
+ }
+ else
+ {
+ send_status = OK;
+ request->status = HTTP_BAD_REQUEST;
+ return send_status;
+ }
+
+ content_type = (axis2_char_t *)apr_table_get(request->headers_in,
+ AXIS2_HTTP_HEADER_CONTENT_TYPE);
+ if(!content_type)
+ {
+ content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN;
+ }
+ request->content_type = content_type;
+
+ out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(apache2_worker->conf_ctx, env),
+ env, AXIS2_TRANSPORT_ENUM_HTTP);
+ in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(apache2_worker->conf_ctx, env),
+ env, AXIS2_TRANSPORT_ENUM_HTTP);
+ {
+ axis2_transport_receiver_t *receiver = NULL;
+ receiver = axis2_transport_in_desc_get_recv(in_desc, env);
+ if(receiver)
+ axis2_transport_receiver_set_server_ip(receiver, env, request->connection->local_ip);
+ }
+
+ msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc);
+ axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE);
+
+ cookie = (axis2_char_t *)apr_table_get(request->headers_in,
+ AXIS2_HTTP_HEADER_COOKIE);
+ if(cookie)
+ {
+ char *session_str = NULL;
+ axis2_char_t *session_id = NULL;
+
+ session_id = axis2_http_transport_utils_get_session_id_from_cookie(env, cookie);
+ if(session_id)
+ session_str = env->get_session_fn((void *) request, session_id);
+ if(session_str)
+ axis2_http_transport_utils_set_session(env, msg_ctx, session_str);
+ }
+
+ if(request->read_chunked == AXIS2_TRUE && 0 == content_length)
+ {
+ content_length = -1;
+ request->chunked = 1;
+ }
+ if(!http_version)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_HTTP_VERSION, AXIS2_FAILURE);
+ return AXIS2_CRITICAL_FAILURE;
+ }
+ out_stream = axutil_stream_create_basic(env);
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Client HTTP version %s", http_version);
+
+ peer_ip = request->connection->remote_ip;
+
+ if(peer_ip)
+ {
+ peer_property = axutil_property_create(env);
+ axutil_property_set_value(peer_property, env, axutil_strdup(env, peer_ip));
+ axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_SVR_PEER_IP_ADDR, peer_property);
+ }
+
+ axis2_msg_ctx_set_transport_out_stream(msg_ctx, env, out_stream);
+
+ ctx_uuid = axutil_uuid_gen(env);
+ if(ctx_uuid)
+ {
+ axutil_string_t *uuid_str = axutil_string_create_assume_ownership(env, &ctx_uuid);
+ axis2_msg_ctx_set_svc_grp_ctx_id(msg_ctx, env, uuid_str);
+ axutil_string_free(uuid_str, env);
+ }
+
+ apache2_out_transport_info = axis2_apache2_out_transport_info_create(env, request);
+ axis2_msg_ctx_set_out_transport_info(msg_ctx, env, &(apache2_out_transport_info->out_transport));
+
+ accept_header_value = (axis2_char_t *)apr_table_get(request->headers_in,
+ AXIS2_HTTP_HEADER_ACCEPT);
+ if(accept_header_value)
+ {
+ axutil_array_list_t *accept_header_field_list = NULL;
+ axutil_array_list_t *accept_record_list = NULL;
+ accept_header_field_list = axutil_tokenize(env, accept_header_value, ',');
+ if(accept_header_field_list && axutil_array_list_size(accept_header_field_list, env) > 0)
+ {
+ axis2_char_t *token = NULL;
+ accept_record_list = axutil_array_list_create(env, axutil_array_list_size(
+ accept_header_field_list, env));
+ do
+ {
+ if(token)
+ {
+ axis2_http_accept_record_t *rec = NULL;
+ rec = axis2_http_accept_record_create(env, token);
+ if(rec)
+ {
+ axutil_array_list_add(accept_record_list, env, rec);
+ }
+ AXIS2_FREE(env->allocator, token);
+ }
+ token = (axis2_char_t *)axutil_array_list_remove(accept_header_field_list, env, 0);
+ }
+ while(token);
+ }
+ if(accept_record_list && axutil_array_list_size(accept_record_list, env) > 0)
+ {
+ axis2_msg_ctx_set_http_accept_record_list(msg_ctx, env, accept_record_list);
+ }
+ }
+
+ accept_charset_header_value = (axis2_char_t *)apr_table_get(request->headers_in,
+ AXIS2_HTTP_HEADER_ACCEPT_CHARSET);
+ if(accept_charset_header_value)
+ {
+ axutil_array_list_t *accept_charset_header_field_list = NULL;
+ axutil_array_list_t *accept_charset_record_list = NULL;
+ accept_charset_header_field_list = axutil_tokenize(env, accept_charset_header_value, ',');
+ if(accept_charset_header_field_list && axutil_array_list_size(
+ accept_charset_header_field_list, env) > 0)
+ {
+ axis2_char_t *token = NULL;
+ accept_charset_record_list = axutil_array_list_create(env, axutil_array_list_size(
+ accept_charset_header_field_list, env));
+ do
+ {
+ if(token)
+ {
+ axis2_http_accept_record_t *rec = NULL;
+ rec = axis2_http_accept_record_create(env, token);
+ if(rec)
+ {
+ axutil_array_list_add(accept_charset_record_list, env, rec);
+ }
+ AXIS2_FREE(env->allocator, token);
+ }
+ token = (axis2_char_t *)axutil_array_list_remove(accept_charset_header_field_list,
+ env, 0);
+ }
+ while(token);
+ }
+ if(accept_charset_record_list && axutil_array_list_size(accept_charset_record_list, env)
+ > 0)
+ {
+ axis2_msg_ctx_set_http_accept_charset_record_list(msg_ctx, env,
+ accept_charset_record_list);
+ }
+ }
+
+ accept_language_header_value = (axis2_char_t *)apr_table_get(request->headers_in,
+ AXIS2_HTTP_HEADER_ACCEPT_LANGUAGE);
+ if(accept_language_header_value)
+ {
+ axutil_array_list_t *accept_language_header_field_list = NULL;
+ axutil_array_list_t *accept_language_record_list = NULL;
+ accept_language_header_field_list = axutil_tokenize(env, accept_language_header_value, ',');
+ if(accept_language_header_field_list && axutil_array_list_size(
+ accept_language_header_field_list, env) > 0)
+ {
+ axis2_char_t *token = NULL;
+ accept_language_record_list = axutil_array_list_create(env, axutil_array_list_size(
+ accept_language_header_field_list, env));
+ do
+ {
+ if(token)
+ {
+ axis2_http_accept_record_t *rec = NULL;
+ rec = axis2_http_accept_record_create(env, token);
+ if(rec)
+ {
+ axutil_array_list_add(accept_language_record_list, env, rec);
+ }
+ AXIS2_FREE(env->allocator, token);
+ }
+ token = (axis2_char_t *)axutil_array_list_remove(accept_language_header_field_list,
+ env, 0);
+ }
+ while(token);
+ }
+ if(accept_language_record_list && axutil_array_list_size(accept_language_record_list, env)
+ > 0)
+ {
+ axis2_msg_ctx_set_http_accept_language_record_list(msg_ctx, env,
+ accept_language_record_list);
+ }
+ }
+
+ soap_action_header_txt = (axis2_char_t *)apr_table_get(request->headers_in,
+ AXIS2_HTTP_HEADER_SOAP_ACTION);
+
+ if(soap_action_header_txt)
+ {
+ soap_action = axutil_string_create(env, soap_action_header_txt);
+ }
+
+ headers = axis2_apache_worker_get_headers(env, request);
+ axis2_msg_ctx_set_transport_headers(msg_ctx, env, headers);
+
+ request_body = axutil_stream_create_apache2(env, request);
+ if(!request_body)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occured in"
+ " creating input stream.");
+ return AXIS2_CRITICAL_FAILURE;
+ }
+ if(M_GET == request->method_number || M_DELETE == request->method_number)
+ {
+ if(M_DELETE == request->method_number)
+ {
+ processed = axis2_http_transport_utils_process_http_delete_request(env, msg_ctx,
+ request_body, out_stream, content_type, soap_action, url_external_form, conf_ctx,
+ axis2_http_transport_utils_get_request_params(env,
+ (axis2_char_t *)url_external_form));
+ }
+ else if(request->header_only)
+ {
+ processed = axis2_http_transport_utils_process_http_head_request(env, msg_ctx,
+ request_body, out_stream, content_type, soap_action, url_external_form, conf_ctx,
+ axis2_http_transport_utils_get_request_params(env,
+ (axis2_char_t *)url_external_form));
+ }
+ else
+ {
+ processed = axis2_http_transport_utils_process_http_get_request(env, msg_ctx,
+ request_body, out_stream, content_type, soap_action, url_external_form, conf_ctx,
+ axis2_http_transport_utils_get_request_params(env,
+ (axis2_char_t *)url_external_form));
+ }
+ if(AXIS2_FALSE == processed)
+ {
+ axis2_char_t *wsdl = NULL;
+ axis2_bool_t is_services_path = AXIS2_FALSE;
+ if(M_DELETE != request->method_number)
+ {
+ axis2_char_t *temp = NULL;
+ temp = strstr(url_external_form, AXIS2_REQUEST_URL_PREFIX);
+ if(temp)
+ {
+ temp += strlen(AXIS2_REQUEST_URL_PREFIX);
+ if(*temp == '/')
+ {
+ temp++;
+ }
+ if(!*temp || *temp == '?' || *temp == '#')
+ {
+ is_services_path = AXIS2_TRUE;
+ }
+ }
+ }
+ wsdl = strstr(url_external_form, AXIS2_REQUEST_WSDL);
+ if(is_services_path)
+ {
+ body_string = axis2_http_transport_utils_get_services_html(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ }
+ else if(M_DELETE != request->method_number && wsdl)
+ {
+ body_string = axis2_http_transport_utils_get_services_static_wsdl(env, conf_ctx,
+ (axis2_char_t *)url_external_form);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML;
+
+ }
+ else if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND)
+ {
+ axutil_array_list_t *method_list = NULL;
+ int size = 0;
+ method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env);
+ size = axutil_array_list_size(method_list, env);
+ if(method_list && size)
+ {
+ axis2_char_t *method_list_str = NULL;
+ axis2_char_t *temp;
+ int i = 0;
+ method_list_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 29);
+ temp = method_list_str;
+ request->allowed_methods->method_mask = 0;
+ for(i = 0; i < size; i++)
+ {
+ if(i)
+ {
+ sprintf(temp, ", ");
+ temp += 2;
+ }
+ sprintf(temp, "%s", (axis2_char_t *)axutil_array_list_get(method_list, env,
+ i));
+ temp += strlen(temp);
+ /* Conditions below is to assist down-stream modules */
+ if(!strcasecmp(AXIS2_HTTP_PUT, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_PUT;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_POST, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_POST;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_GET, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_HEAD, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ /* Apache Can't differentiate between HEAD and GET */
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_DELETE,
+ (axis2_char_t *)axutil_array_list_get(method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_DELETE;
+ }
+ }
+ *temp = '\0';
+ apr_table_set(request->err_headers_out, AXIS2_HTTP_HEADER_ALLOW,
+ method_list_str);
+ AXIS2_FREE(env->allocator, method_list_str);
+ body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx);
+ request->status = HTTP_METHOD_NOT_ALLOWED;
+ }
+ else
+ {
+ body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx);
+ request->status = HTTP_NOT_FOUND;
+ }
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_bad_request(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_BAD_REQUEST;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_request_timeout(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_REQUEST_TIME_OUT;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_conflict(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_CONFLICT;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_GONE_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_gone(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_GONE;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_precondition_failed(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_PRECONDITION_FAILED;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_request_entity_too_large(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_REQUEST_ENTITY_TOO_LARGE;
+ }
+ else if(axis2_msg_ctx_get_status_code(msg_ctx, env)
+ == AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL)
+ {
+ body_string = axis2_http_transport_utils_get_service_unavailable(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_SERVICE_UNAVAILABLE;
+ }
+ else
+ {
+ body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if(body_string)
+ {
+ body_string_len = axutil_strlen(body_string);
+ }
+ send_status = OK;
+ }
+ }
+ else if(M_POST == request->method_number || M_PUT == request->method_number)
+ {
+ /*axis2_status_t status = AXIS2_FAILURE;*/
+ if(M_POST == request->method_number)
+ {
+ status = axis2_http_transport_utils_process_http_post_request(env, msg_ctx,
+ request_body, out_stream, content_type, content_length, soap_action,
+ (axis2_char_t *)url_external_form);
+ }
+ else
+ {
+ status = axis2_http_transport_utils_process_http_put_request(env, msg_ctx,
+ request_body, out_stream, content_type, content_length, soap_action,
+ (axis2_char_t *)url_external_form);
+ }
+ if(AXIS2_FAILURE == status && (M_PUT == request->method_number
+ || axis2_msg_ctx_get_doing_rest(msg_ctx, env)))
+ {
+ if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND)
+ {
+ axutil_array_list_t *method_list = NULL;
+ int size = 0;
+ method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env);
+ size = axutil_array_list_size(method_list, env);
+ if(method_list && size)
+ {
+ axis2_char_t *method_list_str = NULL;
+ axis2_char_t *temp;
+ int i = 0;
+ method_list_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 29);
+ temp = method_list_str;
+ request->allowed_methods->method_mask = 0;
+ for(i = 0; i < size; i++)
+ {
+ if(i)
+ {
+ sprintf(temp, ", ");
+ temp += 2;
+ }
+ sprintf(temp, "%s", (axis2_char_t *)axutil_array_list_get(method_list, env,
+ i));
+ temp += strlen(temp);
+ /* Conditions below is to assist down-stream modules */
+ if(!strcasecmp(AXIS2_HTTP_PUT, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_PUT;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_POST, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_POST;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_GET, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_HEAD, (axis2_char_t *)axutil_array_list_get(
+ method_list, env, i)))
+ {
+ /* Apache Can't differentiate between HEAD and GET */
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET;
+ }
+ else if(!strcasecmp(AXIS2_HTTP_DELETE,
+ (axis2_char_t *)axutil_array_list_get(method_list, env, i)))
+ {
+ request->allowed_methods->method_mask |= AP_METHOD_BIT << M_DELETE;
+ }
+ }
+ *temp = '\0';
+ apr_table_set(request->err_headers_out, AXIS2_HTTP_HEADER_ALLOW,
+ method_list_str);
+ AXIS2_FREE(env->allocator, method_list_str);
+ body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx);
+ request->status = HTTP_METHOD_NOT_ALLOWED;
+ }
+ else
+ {
+ body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx);
+ request->status = HTTP_NOT_FOUND;
+ }
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ }
+ else
+ {
+ body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+ request->status = HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if(body_string)
+ {
+ body_string_len = axutil_strlen(body_string);
+ }
+ send_status = OK;
+ }
+ else if(status == AXIS2_FAILURE)
+ {
+ axis2_msg_ctx_t *fault_ctx = NULL;
+ axis2_char_t *fault_code = NULL;
+ axis2_engine_t *engine = axis2_engine_create(env, conf_ctx);
+ if(!engine)
+ {
+ /* Critical error, cannot proceed, Apache will send default
+ document for 500
+ */
+ return AXIS2_CRITICAL_FAILURE;
+ }
+ if(axis2_msg_ctx_get_is_soap_11(msg_ctx, env))
+ {
+ fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX ":"
+ AXIOM_SOAP11_FAULT_CODE_SENDER;
+ }
+ else
+ {
+ fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX ":"
+ AXIOM_SOAP12_SOAP_FAULT_VALUE_SENDER;
+ }
+ fault_ctx = axis2_engine_create_fault_msg_ctx(engine, env, msg_ctx,
+ fault_code,
+ axutil_error_get_message
+ (env->error));
+ axis2_engine_send_fault(engine, env, fault_ctx);
+ if (out_stream)
+ {
+ body_string = axutil_stream_get_buffer(out_stream, env);
+ body_string_len = axutil_stream_get_len(out_stream, env);
+ }
+
+ /* In case of a SOAP Fault, we have to set the status to 500,
+ but still return OK because the module has handled the error
+ */
+ send_status = OK;
+ request->status = HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+ else
+ {
+ body_string =
+ axis2_http_transport_utils_get_not_implemented(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+
+ if (body_string)
+ {
+ body_string_len = axutil_strlen(body_string);
+ }
+ send_status = OK;
+ request->status = HTTP_NOT_IMPLEMENTED;
+ }
+
+ op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env);
+
+ if (op_ctx)
+ {
+ axis2_msg_ctx_t *out_msg_ctx = NULL;
+ axis2_msg_ctx_t **msg_ctx_map = NULL;
+
+ msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env);
+ out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT];
+ if (out_msg_ctx)
+ {
+ content_language_header_value = axis2_msg_ctx_get_content_language(out_msg_ctx, env);
+ }
+ }
+
+ if (send_status == DECLINED)
+ {
+ axis2_bool_t do_rest = AXIS2_FALSE;
+ if (M_POST != request->method_number ||
+ axis2_msg_ctx_get_doing_rest(msg_ctx, env))
+ {
+ do_rest = AXIS2_TRUE;
+ }
+ if ((accept_header_value || accept_charset_header_value ||
+ accept_language_header_value) && do_rest)
+ {
+ axis2_char_t *content_type_header_value = NULL;
+ axis2_char_t *temp = NULL;
+ axis2_char_t *language_header_value = NULL;
+
+ content_type_header_value = (axis2_char_t *) request->content_type;
+ language_header_value = content_language_header_value;
+ if (content_type_header_value)
+ {
+ temp = axutil_strdup(env, content_type_header_value);
+ }
+ if (temp)
+ {
+ axis2_char_t *content_type = NULL;
+ axis2_char_t *char_set = NULL;
+ axis2_char_t *temp2 = NULL;
+
+ temp2 = strchr(temp, ';');
+ if (temp2)
+ {
+ *temp2 = '\0';
+ temp2++;
+ char_set = axutil_strcasestr(temp2, AXIS2_HTTP_CHAR_SET_ENCODING);
+ }
+ if (char_set)
+ {
+ char_set = axutil_strltrim(env, char_set, " \t=");
+ }
+ if (char_set)
+ {
+ temp2 = strchr(char_set, ';');
+ }
+ if (temp2)
+ {
+ *temp2 = '\0';
+ }
+ content_type = axutil_strtrim(env, temp, NULL);
+
+ if (temp)
+ {
+ AXIS2_FREE(env->allocator, temp);
+ temp = NULL;
+ }
+ if (content_type && accept_header_value &&
+ !axutil_strcasestr(accept_header_value, content_type))
+ {
+ temp2 = strchr(content_type, '/');
+ if (temp2)
+ {
+ *temp2 = '\0';
+ temp = AXIS2_MALLOC(env->allocator,
+ sizeof(axis2_char_t) * ((int)strlen(content_type) + 3));
+ if (!temp)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ return AXIS2_FALSE;
+ }
+ sprintf(temp, "%s/*", content_type);
+ if (!axutil_strcasestr(accept_header_value, temp) &&
+ !strstr(accept_header_value, AXIS2_HTTP_HEADER_ACCEPT_ALL))
+ {
+ body_string =
+ axis2_http_transport_utils_get_not_acceptable(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+
+ if (body_string)
+ {
+ body_string_len = axutil_strlen(body_string);
+ }
+ send_status = OK;
+ request->status = HTTP_NOT_ACCEPTABLE;
+ }
+ AXIS2_FREE(env->allocator, temp);
+ }
+ }
+ if (content_type)
+ {
+ AXIS2_FREE(env->allocator, content_type);
+ }
+ if (char_set && accept_charset_header_value &&
+ !axutil_strcasestr(accept_charset_header_value, char_set))
+ {
+ body_string =
+ axis2_http_transport_utils_get_not_acceptable(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+
+ if (body_string)
+ {
+ body_string_len = axutil_strlen(body_string);
+ }
+ send_status = OK;
+ request->status = HTTP_NOT_ACCEPTABLE;
+ }
+ if (char_set)
+ {
+ AXIS2_FREE(env->allocator, char_set);
+ }
+ }
+ if (language_header_value)
+ {
+ if (accept_language_header_value &&
+ !axutil_strcasestr(accept_language_header_value, language_header_value))
+ {
+ body_string =
+ axis2_http_transport_utils_get_not_acceptable(env, conf_ctx);
+ request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML;
+
+ if (body_string)
+ {
+ body_string_len = axutil_strlen(body_string);
+ }
+ send_status = OK;
+ request->status = HTTP_NOT_ACCEPTABLE;
+ }
+ }
+ }
+ }
+
+ header_value = axis2_http_transport_utils_get_session(env, msg_ctx);
+ if(header_value)
+ {
+ axis2_http_out_transport_info_t *out_info = NULL;
+ out_info = (axis2_http_out_transport_info_t *)axis2_msg_ctx_get_out_transport_info(msg_ctx, env);
+ AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_COOKIE_HEADER(out_info, env, header_value);
+ }
+ if (send_status == DECLINED)
+ {
+ axis2_bool_t do_rest = AXIS2_FALSE;
+ if (M_POST != request->method_number ||
+ axis2_msg_ctx_get_doing_rest(msg_ctx, env))
+ {
+ do_rest = AXIS2_TRUE;
+ }
+ if (op_ctx && axis2_op_ctx_get_response_written(op_ctx, env))
+ {
+ if (do_rest)
+ {
+ axis2_msg_ctx_t *out_msg_ctx = NULL;
+ axis2_msg_ctx_t *in_msg_ctx = NULL;
+ axis2_msg_ctx_t **msg_ctx_map = NULL;
+
+ msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env);
+ out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT];
+ in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN];
+ if (in_msg_ctx)
+ {
+ /* TODO: Add necessary handling */
+ }
+ if (out_msg_ctx)
+ {
+ int size = 0;
+ axutil_array_list_t *output_header_list = NULL;
+ output_header_list = axis2_msg_ctx_get_http_output_headers(out_msg_ctx, env);
+ if (output_header_list)
+ {
+ size = axutil_array_list_size(output_header_list, env);
+ }
+ while (size)
+ {
+ axis2_http_header_t *output_header = NULL;
+ size--;
+ output_header = (axis2_http_header_t *)
+ axutil_array_list_get(output_header_list, env, size);
+ apr_table_set(request->err_headers_out,
+ axis2_http_header_get_name(output_header, env),
+ axis2_http_header_get_value(output_header, env));
+ }
+ if (axis2_msg_ctx_get_status_code(out_msg_ctx, env))
+ {
+ int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env);
+ switch (status_code)
+ {
+ case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL:
+ request->status = HTTP_CONTINUE;
+ break;
+ case AXIS2_HTTP_RESPONSE_ACK_CODE_VAL:
+ request->status = HTTP_ACCEPTED;
+ break;
+ case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL:
+ request->status = HTTP_MULTIPLE_CHOICES;
+ break;
+ case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL:
+ request->status = HTTP_MOVED_PERMANENTLY;
+ break;
+ case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL:
+ request->status = HTTP_SEE_OTHER;
+ break;
+ case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL:
+ request->status = HTTP_NOT_MODIFIED;
+ break;
+ case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL:
+ request->status = HTTP_TEMPORARY_REDIRECT;
+ break;
+ case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL:
+ request->status = HTTP_BAD_REQUEST;
+ break;
+ case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL:
+ request->status = HTTP_REQUEST_TIME_OUT;
+ break;
+ case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL:
+ request->status = HTTP_CONFLICT;
+ break;
+ case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL:
+ request->status = HTTP_GONE;
+ break;
+ case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL:
+ request->status = HTTP_PRECONDITION_FAILED;
+ break;
+ case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL:
+ request->status = HTTP_REQUEST_ENTITY_TOO_LARGE;
+ break;
+ case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL:
+ request->status = HTTP_SERVICE_UNAVAILABLE;
+ break;
+ default:
+ request->status = HTTP_OK;
+ break;
+ }
+ send_status = DONE;
+ }
+ }
+ }
+ if (send_status == DECLINED)
+ {
+ send_status = OK;
+ if (out_stream)
+ {
+ body_string = axutil_stream_get_buffer(out_stream, env);
+ body_string_len = axutil_stream_get_len(out_stream, env);
+ }
+ }
+ }
+ else if (op_ctx)
+ {
+ if (do_rest)
+ {
+ axis2_msg_ctx_t *out_msg_ctx = NULL;
+ axis2_msg_ctx_t *in_msg_ctx = NULL;
+ axis2_msg_ctx_t **msg_ctx_map = NULL;
+
+ msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env);
+ out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT];
+ in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN];
+ if (in_msg_ctx)
+ {
+ /* TODO: Add necessary handling */
+ }
+ if (out_msg_ctx)
+ {
+ int size = 0;
+ axutil_array_list_t *output_header_list = NULL;
+ output_header_list = axis2_msg_ctx_get_http_output_headers(out_msg_ctx, env);
+ if (output_header_list)
+ {
+ size = axutil_array_list_size(output_header_list, env);
+ }
+ while (size)
+ {
+ axis2_http_header_t *output_header = NULL;
+ size--;
+ output_header = (axis2_http_header_t *)
+ axutil_array_list_get(output_header_list, env, size);
+ apr_table_set(request->err_headers_out,
+ axis2_http_header_get_name(output_header, env),
+ axis2_http_header_get_value(output_header, env));
+ }
+ if (axis2_msg_ctx_get_no_content(out_msg_ctx, env))
+ {
+ if (axis2_msg_ctx_get_status_code(out_msg_ctx, env))
+ {
+ int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env);
+ switch (status_code)
+ {
+ case AXIS2_HTTP_RESPONSE_RESET_CONTENT_CODE_VAL:
+ request->status = HTTP_RESET_CONTENT;
+ break;
+ case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL:
+ request->status = HTTP_NOT_MODIFIED;
+ break;
+ default:
+ request->status = HTTP_NO_CONTENT;
+ break;
+ }
+ }
+ else
+ {
+ request->status = HTTP_NO_CONTENT;
+ }
+ send_status = DONE;
+ }
+ else if (axis2_msg_ctx_get_status_code(out_msg_ctx, env))
+ {
+ int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env);
+ switch (status_code)
+ {
+ case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL:
+ request->status = HTTP_CONTINUE;
+ break;
+ case AXIS2_HTTP_RESPONSE_OK_CODE_VAL:
+ request->status = HTTP_OK;
+ break;
+ case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL:
+ request->status = HTTP_MULTIPLE_CHOICES;
+ break;
+ case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL:
+ request->status = HTTP_MOVED_PERMANENTLY;
+ break;
+ case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL:
+ request->status = HTTP_SEE_OTHER;
+ break;
+ case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL:
+ request->status = HTTP_NOT_MODIFIED;
+ break;
+ case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL:
+ request->status = HTTP_TEMPORARY_REDIRECT;
+ break;
+ case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL:
+ request->status = HTTP_BAD_REQUEST;
+ break;
+ case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL:
+ request->status = HTTP_REQUEST_TIME_OUT;
+ break;
+ case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL:
+ request->status = HTTP_CONFLICT;
+ break;
+ case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL:
+ request->status = HTTP_GONE;
+ break;
+ case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL:
+ request->status = HTTP_PRECONDITION_FAILED;
+ break;
+ case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL:
+ request->status = HTTP_REQUEST_ENTITY_TOO_LARGE;
+ break;
+ case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL:
+ request->status = HTTP_SERVICE_UNAVAILABLE;
+ break;
+ default:
+ request->status = HTTP_ACCEPTED;
+ break;
+ }
+ send_status = DONE;
+ }
+ }
+ }
+ if (send_status == DECLINED)
+ {
+ if (msg_ctx)
+ {
+ int size = 0;
+ int status_code;
+ axutil_array_list_t *output_header_list = NULL;
+ output_header_list = axis2_msg_ctx_get_http_output_headers(msg_ctx, env);
+ if (output_header_list)
+ {
+ size = axutil_array_list_size(output_header_list, env);
+ }
+ while (size)
+ {
+ axis2_http_header_t *output_header = NULL;
+ size--;
+ output_header = (axis2_http_header_t *)
+ axutil_array_list_get(output_header_list, env, size);
+ apr_table_set(request->err_headers_out,
+ axis2_http_header_get_name(output_header, env),
+ axis2_http_header_get_value(output_header, env));
+ }
+
+ status_code = axis2_msg_ctx_get_status_code(msg_ctx, env);
+ switch (status_code)
+ {
+ case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL:
+ request->status = HTTP_CONTINUE;
+ break;
+ case AXIS2_HTTP_RESPONSE_OK_CODE_VAL:
+ request->status = HTTP_OK;
+ break;
+ case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL:
+ request->status = HTTP_MULTIPLE_CHOICES;
+ break;
+ case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL:
+ request->status = HTTP_MOVED_PERMANENTLY;
+ break;
+ case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL:
+ request->status = HTTP_SEE_OTHER;
+ break;
+ case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL:
+ request->status = HTTP_NOT_MODIFIED;
+ break;
+ case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL:
+ request->status = HTTP_TEMPORARY_REDIRECT;
+ break;
+ case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL:
+ request->status = HTTP_BAD_REQUEST;
+ break;
+ case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL:
+ request->status = HTTP_REQUEST_TIME_OUT;
+ break;
+ case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL:
+ request->status = HTTP_CONFLICT;
+ break;
+ case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL:
+ request->status = HTTP_GONE;
+ break;
+ case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL:
+ request->status = HTTP_PRECONDITION_FAILED;
+ break;
+ case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL:
+ request->status = HTTP_REQUEST_ENTITY_TOO_LARGE;
+ break;
+ case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL:
+ request->status = HTTP_SERVICE_UNAVAILABLE;
+ break;
+ case AXIS2_HTTP_RESPONSE_FORBIDDEN_CODE_VAL:
+ request->status = HTTP_FORBIDDEN;
+ break;
+ case AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL:
+ request->status = HTTP_UNAUTHORIZED;
+ break;
+ default:
+ request->status = HTTP_ACCEPTED;
+ break;
+ }
+
+ out_stream = axis2_msg_ctx_get_transport_out_stream(msg_ctx, env);
+ if (out_stream)
+ {
+ body_string = axutil_stream_get_buffer(out_stream, env);
+ body_string_len = axutil_stream_get_len(out_stream, env);
+ }
+ send_status = DONE;
+ }
+ else
+ {
+ request->status = HTTP_ACCEPTED;
+ send_status = DONE;
+ }
+ }
+ }
+ else
+ {
+ send_status = DONE;
+ request->status = HTTP_ACCEPTED;
+ }
+ }
+
+ if (content_language_header_value)
+ {
+ apr_table_set(request->err_headers_out, AXIS2_HTTP_HEADER_CONTENT_LANGUAGE,
+ content_language_header_value);
+ }
+
+ if (op_ctx)
+ {
+ axis2_msg_ctx_t *out_msg_ctx = NULL,
+ *in_msg_ctx = NULL;
+ axis2_msg_ctx_t **msg_ctx_map = NULL;
+ axis2_char_t *msg_id = NULL;
+ axis2_conf_ctx_t *conf_ctx = NULL;
+ msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env);
+
+ out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT];
+ in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN];
+
+ /* In mtom case we send the attachment differently */
+
+ /* status = AXIS2_FAILURE means fault scenario. We are not
+ * doing MTOM for fault cases. */
+
+ if(status != AXIS2_FAILURE)
+ {
+ do_mtom = axis2_msg_ctx_get_doing_mtom(out_msg_ctx, env);
+ if(do_mtom)
+ {
+ mime_parts = axis2_msg_ctx_get_mime_parts(out_msg_ctx, env);
+ if(!mime_parts)
+ {
+ return AXIS2_FAILURE;
+ }
+ callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env ,
+ AXIS2_MTOM_SENDING_CALLBACK);
+ if(callback_name_param)
+ {
+ mtom_sending_callback_name =
+ (axis2_char_t *) axutil_param_get_value (callback_name_param, env);
+ }
+ }
+ }
+
+ if (out_msg_ctx)
+ {
+ axis2_msg_ctx_free(out_msg_ctx, env);
+ out_msg_ctx = NULL;
+ msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = NULL;
+ }
+
+ if (in_msg_ctx)
+ {
+ msg_id =
+ axutil_strdup(env, axis2_msg_ctx_get_msg_id(in_msg_ctx, env));
+ conf_ctx = axis2_msg_ctx_get_conf_ctx(in_msg_ctx, env);
+ axis2_msg_ctx_reset_out_transport_info(in_msg_ctx, env);
+ axis2_msg_ctx_free(in_msg_ctx, env);
+ in_msg_ctx = NULL;
+ msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = NULL;
+ }
+
+ if (!axis2_op_ctx_is_in_use(op_ctx, env))
+ {
+ axis2_op_ctx_destroy_mutex(op_ctx, env);
+ if (conf_ctx && msg_id)
+ {
+ axis2_conf_ctx_register_op_ctx(conf_ctx, env, msg_id, NULL);
+ AXIS2_FREE(env->allocator, msg_id);
+ }
+ axis2_op_ctx_free(op_ctx, env);
+ }
+
+ } /* Done freeing message contexts */
+
+ /* We send the message in parts when doing MTOM */
+
+ if(do_mtom)
+ {
+ axis2_status_t mtom_status = AXIS2_FAILURE;
+
+ if(!mtom_sending_callback_name)
+ {
+ /* If the callback name is not there, then we will check whether there
+ * is any mime_parts which has type callback. If we found then no point
+ * of continuing we should return a failure */
+
+ if(!mtom_sending_callback_name)
+ {
+ if(axis2_http_transport_utils_is_callback_required(
+ env, mime_parts))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Sender callback not specified");
+ return AXIS2_FAILURE;
+ }
+ }
+ }
+
+ mtom_status = apache2_worker_send_mtom_message(request, env, mime_parts,
+ mtom_sending_callback_name);
+ if(mtom_status == AXIS2_SUCCESS)
+ {
+ send_status = DONE;
+ }
+ else
+ {
+ send_status = DECLINED;
+ }
+
+ axis2_http_transport_utils_destroy_mime_parts(mime_parts, env);
+ mime_parts = NULL;
+ }
+
+ else if (body_string)
+ {
+ ap_rwrite(body_string, body_string_len, request);
+ body_string = NULL;
+ }
+
+ if (request_body)
+ {
+ axutil_stream_free(request_body, env);
+ request_body = NULL;
+ }
+
+ axutil_string_free(soap_action, env);
+
+ msg_ctx = NULL;
+ return send_status;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axis2_apache2_worker_get_bytes(
+ const axutil_env_t * env,
+ axutil_stream_t * stream)
+{
+
+ axutil_stream_t *tmp_stream = NULL;
+ int return_size = -1;
+ axis2_char_t *buffer = NULL;
+ axis2_bool_t loop_status = AXIS2_TRUE;
+
+ AXIS2_ENV_CHECK(env, NULL);
+ AXIS2_PARAM_CHECK(env->error, stream, NULL);
+
+ tmp_stream = axutil_stream_create_basic(env);
+ while(loop_status)
+ {
+ int read = 0;
+ int write = 0;
+
+ char buf[READ_SIZE];
+ read = axutil_stream_read(stream, env, buf, READ_SIZE);
+ if(read < 0)
+ {
+ break;
+ }
+ write = axutil_stream_write(tmp_stream, env, buf, read);
+ if(read < (READ_SIZE - 1))
+ {
+ break;
+ }
+ }
+ return_size = axutil_stream_get_len(tmp_stream, env);
+
+ if(return_size > 0)
+ {
+ buffer = (char *)AXIS2_MALLOC(env->allocator, sizeof(char) * (return_size + 2));
+ return_size = axutil_stream_read(tmp_stream, env, buffer, return_size + 1);
+ buffer[return_size + 1] = '\0';
+ }
+ axutil_stream_free(tmp_stream, env);
+ return buffer;
+}
+
+static axis2_status_t
+apache2_worker_send_mtom_message(
+ request_rec *request,
+ const axutil_env_t * env,
+ axutil_array_list_t *mime_parts,
+ axis2_char_t *mtom_sending_callback_name)
+{
+ int i = 0;
+ axiom_mime_part_t *mime_part = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+ /*int written = 0;*/
+ int len = 0;
+
+ if(mime_parts)
+ {
+ for(i = 0; i < axutil_array_list_size(mime_parts, env); i++)
+ {
+ mime_part = (axiom_mime_part_t *)axutil_array_list_get(mime_parts, env, i);
+ if((mime_part->type) == AXIOM_MIME_PART_BUFFER)
+ {
+ len = 0;
+ len = ap_rwrite(mime_part->part, (int)mime_part->part_size, request);
+ ap_rflush(request);
+ if(len == -1)
+ {
+ status = AXIS2_FAILURE;
+ break;
+ }
+ }
+ else if((mime_part->type) == AXIOM_MIME_PART_FILE)
+ {
+ FILE *f = NULL;
+ axis2_byte_t *output_buffer = NULL;
+ int output_buffer_size = 0;
+
+ f = fopen(mime_part->file_name, "rb");
+ if(!f)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for reading",
+ mime_part->file_name);
+ return AXIS2_FAILURE;
+ }
+ if(mime_part->part_size > AXIS2_MTOM_OUTPUT_BUFFER_SIZE)
+ {
+ output_buffer_size = AXIS2_MTOM_OUTPUT_BUFFER_SIZE;
+ }
+ else
+ {
+ output_buffer_size = (int)mime_part->part_size;
+ }
+
+ output_buffer = AXIS2_MALLOC(env->allocator, (output_buffer_size + 1)
+ * sizeof(axis2_char_t));
+
+ status = apache2_worker_send_attachment_using_file(env, request, f, output_buffer,
+ output_buffer_size);
+ if(status == AXIS2_FAILURE)
+ {
+ return status;
+ }
+ }
+ else if((mime_part->type) == AXIOM_MIME_PART_CALLBACK)
+ {
+ void *handler = NULL;
+ axiom_mtom_sending_callback_t *callback = NULL;
+
+ handler = axis2_http_transport_utils_initiate_callback(env,
+ mtom_sending_callback_name, mime_part->user_param, &callback);
+
+ if(handler)
+ {
+ status = apache2_worker_send_attachment_using_callback(env, request, callback,
+ handler, mime_part->user_param);
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "MTOM Sending Callback loading failed");
+ status = AXIS2_FAILURE;
+ }
+ if(callback)
+ {
+ axutil_param_t *param = NULL;
+
+ param = callback->param;
+
+ AXIOM_MTOM_SENDING_CALLBACK_FREE(callback, env);
+ callback = NULL;
+
+ if(param)
+ {
+ axutil_param_free(param, env);
+ param = NULL;
+ }
+
+ }
+
+ if(status == AXIS2_FAILURE)
+ {
+ return status;
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ if(status == AXIS2_FAILURE)
+ {
+ break;
+ }
+ }
+ return status;
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+}
+
+static axis2_status_t
+apache2_worker_send_attachment_using_file(
+ const axutil_env_t * env,
+ request_rec *request,
+ FILE *fp,
+ axis2_byte_t *buffer,
+ int buffer_size)
+{
+
+ int count = 0;
+ int len = 0;
+ /*int written = 0;*/
+ axis2_status_t status = AXIS2_SUCCESS;
+
+ do
+ {
+ count = (int)fread(buffer, 1, buffer_size + 1, fp);
+ if(ferror(fp))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in reading file containg the attachment");
+ if(buffer)
+ {
+ AXIS2_FREE(env->allocator, buffer);
+ buffer = NULL;
+ }
+ fclose(fp);
+ return AXIS2_FAILURE;
+ }
+
+ if(count > 0)
+ {
+ len = 0;
+ len = ap_rwrite(buffer, count, request);
+ ap_rflush(request);
+ if(len == -1)
+ {
+ status = AXIS2_FAILURE;
+ break;
+ }
+ }
+ else
+ {
+ if(buffer)
+ {
+ AXIS2_FREE(env->allocator, buffer);
+ buffer = NULL;
+ }
+ fclose(fp);
+ return AXIS2_FAILURE;
+ }
+ memset(buffer, 0, buffer_size);
+ if(status == AXIS2_FAILURE)
+ {
+ if(buffer)
+ {
+ AXIS2_FREE(env->allocator, buffer);
+ buffer = NULL;
+ }
+ fclose(fp);
+ return AXIS2_FAILURE;
+ }
+ }
+ while(!feof(fp));
+
+ fclose(fp);
+ AXIS2_FREE(env->allocator, buffer);
+ buffer = NULL;
+ return AXIS2_SUCCESS;
+}
+
+static axis2_status_t
+apache2_worker_send_attachment_using_callback(
+ const axutil_env_t * env,
+ request_rec *request,
+ axiom_mtom_sending_callback_t *callback,
+ void *handler,
+ void *user_param)
+{
+ int count = 0;
+ int len = 0;
+ axis2_status_t status = AXIS2_SUCCESS;
+ axis2_char_t *buffer = NULL;
+
+ /* Keep on loading the data in a loop until
+ * all the data is sent */
+
+ while((count = AXIOM_MTOM_SENDING_CALLBACK_LOAD_DATA(callback, env, handler, &buffer)) > 0)
+ {
+ len = 0;
+ len = ap_rwrite(buffer, count, request);
+ ap_rflush(request);
+ if(len == -1)
+ {
+ status = AXIS2_FAILURE;
+ break;
+ }
+ }
+
+ if(status == AXIS2_FAILURE)
+ {
+ AXIOM_MTOM_SENDING_CALLBACK_CLOSE_HANDLER(callback, env, handler);
+ return status;
+ }
+
+ status = AXIOM_MTOM_SENDING_CALLBACK_CLOSE_HANDLER(callback, env, handler);
+ return status;
+}
+
+
+static axutil_hash_t*
+axis2_apache_worker_get_headers(
+ const axutil_env_t *env,
+ request_rec *request)
+{
+ int i = 0;
+ axutil_hash_t *header_map = NULL;
+ const apr_array_header_t *tarr;
+ const apr_table_entry_t *telts;
+ axis2_http_header_t * tmp_http_header = NULL;
+
+
+ header_map = axutil_hash_make(env);
+ tarr = apr_table_elts(request->headers_in);
+ telts = (const apr_table_entry_t*)tarr->elts;
+
+ for (i = 0; i < tarr->nelts; i++)
+ {
+ axis2_char_t* tmp_key = (axis2_char_t*) telts[i].key;
+ axis2_char_t* tmp_value = (axis2_char_t*) telts[i].val;
+ tmp_http_header = axis2_http_header_create(env, tmp_key, tmp_value);
+ axutil_hash_set(header_map, tmp_key, AXIS2_HASH_KEY_STRING, tmp_http_header);
+ }
+
+ return header_map;
+
+
+}
diff --git a/src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h b/src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h new file mode 100644 index 0000000..9ab9250 --- /dev/null +++ b/src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h @@ -0,0 +1,61 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_APACHE2_OUT_TRANSPORT_INFO_H +#define AXIS2_APACHE2_OUT_TRANSPORT_INFO_H + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_apache2_out_transport_info.h + * @brief axis2 Apache2 Out Transport Info + */ + +#include <axis2_http_out_transport_info.h> +#include <httpd.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + + AXIS2_EXTERN axis2_http_out_transport_info_t *AXIS2_CALL + + axis2_apache2_out_transport_info_create( + const axutil_env_t * env, + request_rec * r); + + /** + * Free http_out_transport_info passed as void pointer. This will be + * cast into appropriate type and then pass the cast object + * into the http_out_transport_info structure's free method + */ + AXIS2_EXTERN void AXIS2_CALL + + axis2_apache2_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env); + + /** @} */ +#ifdef __cplusplus +} +#endif +#endif /* AXIS2_APACHE2_OUT_TRANSPORT_INFO_H */ diff --git a/src/core/transport/http/server/apache2/axis2_apache2_worker.h b/src/core/transport/http/server/apache2/axis2_apache2_worker.h new file mode 100644 index 0000000..eea4033 --- /dev/null +++ b/src/core/transport/http/server/apache2/axis2_apache2_worker.h @@ -0,0 +1,78 @@ + +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AXIS2_APACHE2_WORKER_H +#define AXIS2_APACHE2_WORKER_H + +/** + * @brief Apache2 Worker ops struct + * Encapsulator struct for ops of axis2_apache2_worker + */ + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_apache2_worker.h + * @brief axis2 Apache2 Worker + */ + +#include <axis2_const.h> +#include <axis2_defines.h> +#include <axutil_env.h> +#include <axis2_conf_ctx.h> +#include "apache2_stream.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct axis2_apache2_worker axis2_apache2_worker_t; + + AXIS2_EXTERN int AXIS2_CALL + axis2_apache2_worker_process_request( + axis2_apache2_worker_t * apache2_worker, + const axutil_env_t * env, + request_rec * r); + + AXIS2_EXTERN void AXIS2_CALL + axis2_apache2_worker_free( + axis2_apache2_worker_t * apache2_worker, + const axutil_env_t * env); + + AXIS2_EXTERN axis2_apache2_worker_t *AXIS2_CALL + + axis2_apache2_worker_create( + const axutil_env_t * env, + axis2_char_t * repo_path); + +#define AXIS2_APACHE2_WORKER_PROCESS_REQUEST(apache2_worker, env, request) \ + axis2_apache2_worker_process_request(\ + apache2_worker, env, request) +#define AXIS2_APACHE2_WORKER_FREE(apache2_worker, env) \ + axis2_apache2_worker_free(apache2_worker, env) + + /** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* AXIS2_APACHE2_WORKER_H */ diff --git a/src/core/transport/http/server/apache2/mod_axis2.c b/src/core/transport/http/server/apache2/mod_axis2.c new file mode 100644 index 0000000..a9431eb --- /dev/null +++ b/src/core/transport/http/server/apache2/mod_axis2.c @@ -0,0 +1,844 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <httpd.h> +#include <http_config.h> +#include <http_log.h> +#include <http_protocol.h> +#include <ap_config.h> +#include <apr_strings.h> +#include "axis2_apache2_worker.h" +#include <axutil_error_default.h> +#include <axutil_log_default.h> +#include <axutil_thread_pool.h> +#include <axiom_xml_reader.h> +#include <axutil_version.h> +#include <apr_rmm.h> +#include <apr_shm.h> +#include <apr_dbd.h> +#include <mod_dbd.h> +#include <axis2_http_transport.h> +#include <axutil_types.h> + +/* Configuration structure populated by apache2.conf */ +typedef struct axis2_config_rec +{ + char *axutil_log_file; + char *axis2_repo_path; + axutil_log_levels_t log_level; + int max_log_file_size; + int axis2_global_pool_size; +} axis2_config_rec_t; + +axis2_apache2_worker_t *axis2_worker = NULL; +axutil_env_t *axutil_env = NULL; +apr_rmm_t* rmm = NULL; +apr_global_mutex_t *global_mutex = NULL; + +/******************************Function Headers********************************/ +static void * +axis2_create_svr( + apr_pool_t * p, + server_rec * s); + +static const char * +axis2_set_repo_path( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_log_file( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_max_log_file_size( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_global_pool_size( + cmd_parms * cmd, + void * dummy, + const char *arg); + +static const char * +axis2_set_log_level( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_svc_url_prefix( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static int +axis2_handler( + request_rec * req); + +/* Shutdown Axis2 */ +apr_status_t +axis2_shutdown( + void *tmp); + +void *AXIS2_CALL axis2_module_malloc( + axutil_allocator_t * allocator, + size_t size); + +void *AXIS2_CALL axis2_module_realloc( + axutil_allocator_t * allocator, + void *ptr, + size_t size); + +void AXIS2_CALL axis2_module_free( + axutil_allocator_t * allocator, + void *ptr); + +static void +axis2_module_init( + apr_pool_t * p, + server_rec * svr_rec); + +static void +axis2_register_hooks( + apr_pool_t * p); + +char * +axis2_get_session( + void *req, + const char *id); + +axis2_status_t +axis2_set_session( + void *req, + const char *id, + const char *session); + +/***************************End of Function Headers****************************/ + +static const command_rec axis2_cmds[] = { AP_INIT_TAKE1("Axis2RepoPath", axis2_set_repo_path, NULL, + RSRC_CONF, "Axis2/C repository path"), AP_INIT_TAKE1("Axis2LogFile", axis2_set_log_file, NULL, + RSRC_CONF, "Axis2/C log file name"), AP_INIT_TAKE1("Axis2LogLevel", axis2_set_log_level, NULL, + RSRC_CONF, "Axis2/C log level"), AP_INIT_TAKE1("Axis2MaxLogFileSize", + axis2_set_max_log_file_size, NULL, RSRC_CONF, "Axis2/C maximum log file size"), + AP_INIT_TAKE1("Axis2GlobalPoolSize", axis2_set_global_pool_size, NULL, RSRC_CONF, + "Axis2/C global pool size"), AP_INIT_TAKE1("Axis2ServiceURLPrefix", + axis2_set_svc_url_prefix, NULL, RSRC_CONF, "Axis2/C service URL prifix"), + { NULL } }; + +/* Dispatch list for API hooks */ +module AP_MODULE_DECLARE_DATA axis2_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + axis2_create_svr, /* create per-server config structures */ + NULL, /* merge per-server config structures */ + axis2_cmds, /* table of config file commands */ + axis2_register_hooks /* register hooks */ + }; + +static void * +axis2_create_svr( + apr_pool_t * p, + server_rec * s) +{ + axis2_config_rec_t *conf = apr_palloc(p, sizeof(*conf)); + conf->axutil_log_file = NULL; + conf->axis2_repo_path = NULL; + conf->log_level = AXIS2_LOG_LEVEL_DEBUG; + conf->axis2_global_pool_size = 0; + conf->max_log_file_size = 1; + return conf; +} + +static const char * +axis2_set_repo_path( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->axis2_repo_path = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +static const char * +axis2_set_log_file( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->axutil_log_file = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +static const char * +axis2_set_max_log_file_size( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->max_log_file_size = 1024 * 1024 * atoi(arg); + return NULL; +} + +static const char * +axis2_set_global_pool_size( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->axis2_global_pool_size = 1024 * 1024 * atoi(arg); + return NULL; +} + +static const char * +axis2_set_log_level( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + char *str; + axutil_log_levels_t level = AXIS2_LOG_LEVEL_DEBUG; + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + + str = ap_getword_conf(cmd->pool, &arg); + if(str) + { + if(!strcasecmp(str, "crit")) + { + level = AXIS2_LOG_LEVEL_CRITICAL; + } + else if(!strcasecmp(str, "error")) + { + level = AXIS2_LOG_LEVEL_ERROR; + } + else if(!strcasecmp(str, "warn")) + { + level = AXIS2_LOG_LEVEL_WARNING; + } + else if(!strcasecmp(str, "info")) + { + level = AXIS2_LOG_LEVEL_INFO; + } + else if(!strcasecmp(str, "debug")) + { + level = AXIS2_LOG_LEVEL_DEBUG; + } + else if(!strcasecmp(str, "user")) + { + level = AXIS2_LOG_LEVEL_USER; + } + else if(!strcasecmp(str, "trace")) + { + level = AXIS2_LOG_LEVEL_TRACE; + } + } + conf->log_level = level; + return NULL; +} + +static const char * +axis2_set_svc_url_prefix( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + + axis2_request_url_prefix = AXIS2_REQUEST_URL_PREFIX; + if(!err) + { + axis2_char_t *prefix = apr_pstrdup(cmd->pool, arg); + if(prefix) + axis2_request_url_prefix = prefix; + } + + return NULL; +} + +/* The sample content handler */ +static int +axis2_handler( + request_rec * req) +{ + int rv = 0; + axutil_env_t *thread_env = NULL; + axutil_allocator_t *allocator = NULL; + axutil_error_t *error = NULL; + + apr_allocator_t *local_allocator = NULL; + apr_pool_t *local_pool = NULL; + + if(strcmp(req->handler, "axis2_module")) + { + return DECLINED; + } + + /* Set up the read policy from the client. */ + if((rv = ap_setup_client_block(req, REQUEST_CHUNKED_DECHUNK)) != OK) + { + return rv; + } + ap_should_client_block(req); + + apr_allocator_create(&local_allocator); + apr_pool_create_ex(&local_pool, NULL, NULL, local_allocator); + + /*thread_env = axutil_init_thread_env(axutil_env);*/ + + /*axutil_env->allocator->current_pool = (void *) req->pool; + rv = AXIS2_APACHE2_WORKER_PROCESS_REQUEST(axis2_worker, axutil_env, req);*/ + + /* create new allocator for this request */ + /*allocator = (axutil_allocator_t *) apr_palloc(req->pool, + sizeof(axutil_allocator_t));*/ + + allocator = (axutil_allocator_t *)apr_palloc(local_pool, sizeof(axutil_allocator_t)); + + if(!allocator) + { + return HTTP_INTERNAL_SERVER_ERROR; + } + allocator->malloc_fn = axis2_module_malloc; + allocator->realloc = axis2_module_realloc; + allocator->free_fn = axis2_module_free; + allocator->global_pool_ref = 0; + allocator->local_pool = (void *)local_pool; + allocator->current_pool = (void *)local_pool; + allocator->global_pool = axutil_env->allocator->global_pool; + + error = axutil_error_create(allocator); + thread_env = axutil_env_create_with_error_log_thread_pool(allocator, error, axutil_env->log, + axutil_env-> thread_pool); + thread_env->allocator = allocator; + thread_env->set_session_fn = axis2_set_session; + thread_env->get_session_fn = axis2_get_session; + + rv = AXIS2_APACHE2_WORKER_PROCESS_REQUEST(axis2_worker, thread_env, req); + if(AXIS2_CRITICAL_FAILURE == rv) + { + return HTTP_INTERNAL_SERVER_ERROR; + } + + apr_pool_destroy(local_pool); + apr_allocator_destroy(local_allocator); + + return rv; +} + +void *AXIS2_CALL +axis2_module_malloc( + axutil_allocator_t * allocator, + size_t size) +{ +#if APR_HAS_SHARED_MEMORY + if (rmm == allocator->current_pool) + { + + void* ptr = NULL; + apr_rmm_off_t offset; + apr_global_mutex_lock(global_mutex); + offset = apr_rmm_malloc(rmm, size); + if (offset) + ptr = apr_rmm_addr_get(rmm, offset); + apr_global_mutex_unlock(global_mutex); + return ptr; + } +#endif + return apr_palloc((apr_pool_t *)(allocator->current_pool), size); +} + +void *AXIS2_CALL +axis2_module_realloc( + axutil_allocator_t * allocator, + void *ptr, + size_t size) +{ +#if APR_HAS_SHARED_MEMORY + if (rmm == allocator->current_pool) + { + void* ptr = NULL; + apr_rmm_off_t offset; + apr_global_mutex_lock(global_mutex); + offset = apr_rmm_realloc(rmm, ptr, size); + if (offset) + ptr = apr_rmm_addr_get(rmm, offset); + apr_global_mutex_unlock(global_mutex); + return ptr; + } +#endif + /* can't be easily implemented */ + return NULL; +} + +void AXIS2_CALL +axis2_module_free( + axutil_allocator_t * allocator, + void *ptr) +{ +#if APR_HAS_SHARED_MEMORY + if (rmm == allocator->current_pool) + { + apr_rmm_off_t offset; + apr_global_mutex_lock(global_mutex); + offset = apr_rmm_offset_get(rmm, ptr); + apr_rmm_free(rmm, offset); + apr_global_mutex_unlock(global_mutex); + } +#endif +} + +static int +axis2_post_config( + apr_pool_t *pconf, + apr_pool_t *plog, + apr_pool_t *ptemp, + server_rec *svr_rec) +{ + apr_status_t status = APR_SUCCESS; + axutil_allocator_t *allocator = NULL; + axutil_error_t *error = NULL; + axutil_log_t *axutil_logger = NULL; + axutil_thread_pool_t *thread_pool = NULL; + void *data = NULL; + const char *userdata_key = "axis2_init"; + axis2_config_rec_t *conf = (axis2_config_rec_t *)ap_get_module_config(svr_rec->module_config, + &axis2_module); + + /* axis2_post_config() will be called twice. Don't bother + * going through all of the initialization on the first call + * because it will just be thrown away.*/ + + ap_add_version_component(pconf, AXIS2_HTTP_HEADER_SERVER_AXIS2C); + + apr_pool_userdata_get(&data, userdata_key, svr_rec->process->pool); + if(!data) + { + apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, + svr_rec->process->pool); + return OK; + } + +#if APR_HAS_SHARED_MEMORY + if (conf->axis2_global_pool_size > 0) + { + apr_shm_t *shm; + apr_rmm_off_t offset; + + status = apr_shm_create(&shm, conf->axis2_global_pool_size, NULL, pconf); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error creating shared memory pool"); + exit(APEXIT_INIT); + } + + status = apr_rmm_init(&rmm, NULL, apr_shm_baseaddr_get(shm), conf->axis2_global_pool_size, + pconf); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error creating relocatable memory pool"); + exit(APEXIT_INIT); + } + + status = apr_global_mutex_create(&global_mutex, NULL, + APR_LOCK_DEFAULT, pconf); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error creating global mutex"); + exit(APEXIT_INIT); + } + + /*status = unixd_set_global_mutex_perms(global_mutex); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Permision cannot be set to global mutex"); + exit(APEXIT_INIT); + } + */ + + offset = apr_rmm_malloc(rmm, sizeof(axutil_allocator_t)); + if (!offset) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error in creating allocator in global pool"); + exit(APEXIT_INIT); + } + allocator = apr_rmm_addr_get(rmm, offset); + allocator->malloc_fn = axis2_module_malloc; + allocator->realloc = axis2_module_realloc; + allocator->free_fn = axis2_module_free; + allocator->global_pool_ref = 0; + allocator->local_pool = (void *) rmm; + allocator->current_pool = (void *) rmm; + allocator->global_pool = (void *) rmm; + + /* We need to init xml readers before we go into threaded env + */ + axiom_xml_reader_init(); + axutil_error_init(); + + error = axutil_error_create(allocator); + if (!error) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 error structure"); + exit(APEXIT_CHILDFATAL); + } + + axutil_logger = axutil_log_create(allocator, NULL, conf->axutil_log_file); + if (!axutil_logger) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 log structure"); + exit(APEXIT_CHILDFATAL); + } + thread_pool = axutil_thread_pool_init(allocator); + if (!thread_pool) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error initializing mod_axis2 thread pool"); + exit(APEXIT_CHILDFATAL); + } + axutil_env = axutil_env_create_with_error_log_thread_pool(allocator, error, + axutil_logger, + thread_pool); + if (!axutil_env) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 environment"); + exit(APEXIT_CHILDFATAL); + } + if (axutil_logger) + { + axutil_logger->level = conf->log_level; + axutil_logger->size = conf->max_log_file_size; + AXIS2_LOG_INFO(axutil_env->log, "Apache Axis2/C version in use : %s", + axis2_version_string()); + AXIS2_LOG_INFO(axutil_env->log, + "Starting log with log level %d and max log file size %d", + conf->log_level, conf->max_log_file_size); + } + axutil_env->set_session_fn = axis2_set_session; + axutil_env->get_session_fn = axis2_get_session; + + axis2_worker = axis2_apache2_worker_create(axutil_env, + conf->axis2_repo_path); + if (!axis2_worker) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 apache2 worker"); + exit(APEXIT_CHILDFATAL); + } + } + +#endif + + return OK; +} + +static void +axis2_module_init( + apr_pool_t * p, + server_rec * svr_rec) +{ + apr_pool_t *pool; + apr_status_t status; + axutil_allocator_t *allocator = NULL; + axutil_error_t *error = NULL; + axutil_log_t *axutil_logger = NULL; + axutil_thread_pool_t *thread_pool = NULL; + axis2_config_rec_t *conf = (axis2_config_rec_t*)ap_get_module_config(svr_rec->module_config, + &axis2_module); + + if(conf->axis2_global_pool_size > 0) + { + /* + If we are using shared memory, no need to init the child, as the + worker has been created in post config. + */ + return; + } + + /* We need to init xml readers before we go into threaded env + */ + axiom_xml_reader_init(); + + /* create an allocator that uses APR memory pools and lasts the + * lifetime of the httpd server child process + */ + status = apr_pool_create(&pool, p); + if(status) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error allocating mod_axis2 memory pool"); + exit(APEXIT_CHILDFATAL); + } + allocator = (axutil_allocator_t*)apr_palloc(pool, sizeof(axutil_allocator_t)); + if(!allocator) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_ENOMEM, svr_rec, + "[Axis2] Error allocating mod_axis2 allocator"); + exit(APEXIT_CHILDFATAL); + } + allocator->malloc_fn = axis2_module_malloc; + allocator->realloc = axis2_module_realloc; + allocator->free_fn = axis2_module_free; + allocator->global_pool_ref = 0; + allocator->local_pool = (void*)pool; + allocator->current_pool = (void*)pool; + allocator->global_pool = (void*)pool; + + if(!allocator) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error initializing mod_axis2 allocator"); + exit(APEXIT_CHILDFATAL); + } + + axutil_error_init(); + + error = axutil_error_create(allocator); + if(!error) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 error structure"); + exit(APEXIT_CHILDFATAL); + } + axutil_logger = axutil_log_create(allocator, NULL, conf->axutil_log_file); + if(!axutil_logger) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 log structure"); + exit(APEXIT_CHILDFATAL); + } + thread_pool = axutil_thread_pool_init(allocator); + if(!thread_pool) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error initializing mod_axis2 thread pool"); + exit(APEXIT_CHILDFATAL); + } + axutil_env = axutil_env_create_with_error_log_thread_pool(allocator, error, axutil_logger, + thread_pool); + if(!axutil_env) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 environment"); + exit(APEXIT_CHILDFATAL); + } + if(axutil_logger) + { + + axutil_logger->level = conf->log_level; + AXIS2_LOG_INFO(axutil_env->log, "Apache Axis2/C version in use : %s", + axis2_version_string()); + AXIS2_LOG_INFO(axutil_env->log, "Starting log with log level %d", conf->log_level); + } + axutil_env->set_session_fn = axis2_set_session; + axutil_env->get_session_fn = axis2_get_session; + axis2_worker = axis2_apache2_worker_create(axutil_env, conf->axis2_repo_path); + if(!axis2_worker) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 apache2 worker"); + exit(APEXIT_CHILDFATAL); + } + + /*ap_dbd_prepare(svr_rec, "SELECT value FROM session WHERE id = %s", "retrieve_session"); + ap_dbd_prepare(svr_rec, "INSERT INTO session VALUES(?,?)", "insert_session");*/ + + + /* If we are initialized we register a clean up as well */ + /* apr_pool_cleanup_register(p, NULL, axis2_shutdown, apr_pool_cleanup_null);*/ +} + +static void +axis2_register_hooks( + apr_pool_t * p) +{ + ap_hook_post_config(axis2_post_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(axis2_handler, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_child_init(axis2_module_init, NULL, NULL, APR_HOOK_MIDDLE); +} + +apr_status_t +axis2_shutdown( + void *tmp) +{ + if(axis2_worker) + { + axis2_apache2_worker_free(axis2_worker, axutil_env); + } + return APR_SUCCESS; +} + +char * +axis2_get_session( + void *req, + const char *id) +{ + request_rec *request = NULL; + apr_status_t rv; + const char *dbd_session = NULL; + apr_dbd_prepared_t *statement; + apr_dbd_results_t *res = NULL; + apr_dbd_row_t *row = NULL; + ap_dbd_t *dbd = NULL; + ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL; + request = (request_rec *) req; + + authn_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); + dbd = authn_dbd_acquire_fn(request); + if (!dbd) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Failed to acquire database connection to look up " + "id '%s'", id); + return NULL; + } + + statement = apr_hash_get(dbd->prepared, "retrieve_session", APR_HASH_KEY_STRING); + if (!statement) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "A prepared statement could not be found for " + "the key '%s'", "retrieve_session"); + return NULL; + } + if (apr_dbd_pvselect(dbd->driver, request->pool, dbd->handle, &res, statement, + 0, id, NULL) != 0) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Query execution error looking up '%s' " + "in database", id); + return NULL; + } + for (rv = apr_dbd_get_row(dbd->driver, request->pool, res, &row, -1); rv != -1; + rv = apr_dbd_get_row(dbd->driver, request->pool, res, &row, -1)) + { + if (rv != 0) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, request, + "Error retrieving results while looking up '%s' " + "in database", id); + return NULL; + } + if (!dbd_session) + { + dbd_session = apr_dbd_get_entry(dbd->driver, row, 0); + } + /* we can't break out here or row won't get cleaned up */ + } + + if (!dbd_session) + { + return NULL; + } + + return (char *) dbd_session; +} + +axis2_status_t +axis2_set_session( + void *req, + const char *id, + const char *session) +{ + request_rec *request = NULL; + apr_dbd_prepared_t *statement; + int affected_rows = -1; + ap_dbd_t *dbd = NULL; + ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL; + request = (request_rec *) req; + + authn_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); + dbd = authn_dbd_acquire_fn(request); + if (!dbd) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Failed to acquire database connection to insert session for " + "id '%s'", id); + return AXIS2_FAILURE; + } + + statement = apr_hash_get(dbd->prepared, "insert_session", APR_HASH_KEY_STRING); + if (!statement) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "A prepared statement could not be found for " + "the key '%s'", "insert_session"); + return AXIS2_FAILURE; + } + if (apr_dbd_pvquery(dbd->driver, request->pool, dbd->handle, &affected_rows, statement, id, + session, NULL) != 0) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Query execution error inserting session for '%s' " + "in database", id); + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + + diff --git a/src/core/transport/http/server/simple_axis2_server/Makefile.am b/src/core/transport/http/server/simple_axis2_server/Makefile.am new file mode 100644 index 0000000..604851d --- /dev/null +++ b/src/core/transport/http/server/simple_axis2_server/Makefile.am @@ -0,0 +1,30 @@ +prgbindir=$(bindir) +prgbin_PROGRAMS = axis2_http_server +SUBDIRS = +AM_CFLAGS = -g -pthread +axis2_http_server_SOURCES = http_server_main.c + +axis2_http_server_LDADD = $(LDFLAGS) \ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la \ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la \ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la \ + $(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/axiom/src/parser/$(WRAPPER_DIR)/libaxis2_parser.la \ + $(top_builddir)/src/core/description/libaxis2_description.la \ + $(top_builddir)/src/core/deployment/libaxis2_deployment.la \ + $(top_builddir)/src/core/context/libaxis2_context.la \ + $(top_builddir)/src/core/clientapi/libaxis2_clientapi.la \ + $(top_builddir)/src/core/engine/libaxis2_engine.la \ + $(top_builddir)/src/core/transport/http/sender/libaxis2_http_sender.la \ + $(top_builddir)/src/core/transport/http/receiver/libaxis2_http_receiver.la \ + $(top_builddir)/neethi/src/libneethi.la \ + -lpthread + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/description\ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/deployment\ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/server/simple_axis2_server/http_server_main.c b/src/core/transport/http/server/simple_axis2_server/http_server_main.c new file mode 100644 index 0000000..cfbcda4 --- /dev/null +++ b/src/core/transport/http/server/simple_axis2_server/http_server_main.c @@ -0,0 +1,310 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <axis2_http_server.h> +#include <axis2_http_transport.h> +#include <platforms/axutil_platform_auto_sense.h> +#include <stdio.h> +#include <stdlib.h> +#include <axutil_error_default.h> +#include <axutil_log_default.h> +#include <axutil_thread_pool.h> +#include <signal.h> +#include <axutil_types.h> +#include <ctype.h> +#include <axiom_xml_reader.h> +#include <axutil_version.h> +#include <axutil_file_handler.h> + +axutil_env_t *system_env = NULL; +axis2_transport_receiver_t *server = NULL; +AXIS2_IMPORT extern int axis2_http_socket_read_timeout; +AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + +#define DEFAULT_REPO_PATH "../" + +/***************************** Function headers *******************************/ +axutil_env_t * +init_syetem_env( + axutil_allocator_t * allocator, + const axis2_char_t * log_file); + +void +system_exit( + axutil_env_t * env, + int status); + +void +usage( + axis2_char_t * prog_name); + +void +sig_handler( + int signal); + +/***************************** End of function headers ************************/ +axutil_env_t * +init_syetem_env( + axutil_allocator_t * allocator, + const axis2_char_t * log_file) +{ + axutil_error_t *error = axutil_error_create(allocator); + axutil_log_t *log = axutil_log_create(allocator, NULL, log_file); + /* if (!log) */ + + /* log = axutil_log_create_default (allocator); */ + axutil_thread_pool_t *thread_pool = axutil_thread_pool_init(allocator); + /* We need to init the parser in main thread before spawning child + * threads + */ + axiom_xml_reader_init(); + return axutil_env_create_with_error_log_thread_pool(allocator, error, log, thread_pool); +} + +void +system_exit( + axutil_env_t * env, + int status) +{ + axutil_allocator_t *allocator = NULL; + if(server) + { + axis2_transport_receiver_free(server, system_env); + } + if(env) + { + allocator = env->allocator; + axutil_env_free(env); + } + /*axutil_allocator_free(allocator); */ + axiom_xml_reader_cleanup(); + exit(status); +} + +int +main( + int argc, + char *argv[]) +{ + axutil_allocator_t *allocator = NULL; + axutil_env_t *env = NULL; + extern char *optarg; + extern int optopt; + int c; + unsigned int len; + int log_file_size = AXUTIL_LOG_FILE_SIZE; + unsigned int file_flag = 0; + axutil_log_levels_t log_level = AXIS2_LOG_LEVEL_DEBUG; + const axis2_char_t *log_file = "axis2.log"; + const axis2_char_t *repo_path = DEFAULT_REPO_PATH; + int port = 9090; + axis2_status_t status; + + /* Set the service URL prefix to be used. This could default to services if not + set with AXIS2_REQUEST_URL_PREFIX macro at compile time */ + axis2_request_url_prefix = AXIS2_REQUEST_URL_PREFIX; + + while((c = AXIS2_GETOPT(argc, argv, ":p:r:ht:l:s:f:")) != -1) + { + + switch(c) + { + case 'p': + port = AXIS2_ATOI(optarg); + break; + case 'r': + repo_path = optarg; + break; + case 't': + axis2_http_socket_read_timeout = AXIS2_ATOI(optarg) * 1000; + break; + case 'l': + log_level = AXIS2_ATOI(optarg); + if(log_level < AXIS2_LOG_LEVEL_CRITICAL) + log_level = AXIS2_LOG_LEVEL_CRITICAL; + if(log_level > AXIS2_LOG_LEVEL_TRACE) + log_level = AXIS2_LOG_LEVEL_TRACE; + break; + case 's': + log_file_size = 1024 * 1024 * AXIS2_ATOI(optarg); + break; + case 'f': + log_file = optarg; + break; + case 'h': + usage(argv[0]); + return 0; + case ':': + fprintf(stderr, "\nOption -%c requires an operand\n", optopt); + usage(argv[0]); + return -1; + case '?': + if(isprint(optopt)) + fprintf(stderr, "\nUnknown option `-%c'.\n", optopt); + usage(argv[0]); + return -1; + } + } + + allocator = axutil_allocator_init(NULL); + + if(!allocator) + { + system_exit(NULL, -1); + } + + env = init_syetem_env(allocator, log_file); + env->log->level = log_level; + env->log->size = log_file_size; + + axutil_error_init(); + system_env = env; + + signal(SIGINT, sig_handler); +#ifndef WIN32 + signal(SIGPIPE, sig_handler); +#endif + + AXIS2_LOG_INFO(env->log, "Starting Axis2 HTTP server...."); + AXIS2_LOG_INFO(env->log, "Apache Axis2/C version in use : %s", axis2_version_string()); + AXIS2_LOG_INFO(env->log, "Server port : %d", port); + AXIS2_LOG_INFO(env->log, "Repo location : %s", repo_path); + AXIS2_LOG_INFO(env->log, "Read Timeout : %d ms", axis2_http_socket_read_timeout); + + status = axutil_file_handler_access(repo_path, AXIS2_R_OK); + if(status == AXIS2_SUCCESS) + { + len = (unsigned int)strlen(repo_path); + /* We are sure that the difference lies within the unsigned int range */ + if((len >= 9) && !strcmp((repo_path + (len - 9)), "axis2.xml")) + { + file_flag = 1; + } + } + else + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "provided repo path %s does " + "not exist or no permissions to read, set " + "repo_path to DEFAULT_REPO_PATH", repo_path); + repo_path = DEFAULT_REPO_PATH; + } + + if(!file_flag) + server = axis2_http_server_create(env, repo_path, port); + else + server = axis2_http_server_create_with_file(env, repo_path, port); + + if(!server) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Server creation failed: Error code:" " %d :: %s", + env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); + system_exit(env, -1); + + } + printf("Started Simple Axis2 HTTP Server ...\n"); + if(axis2_transport_receiver_start(server, env) == AXIS2_FAILURE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Server start failed: Error code:" " %d :: %s", + env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); + system_exit(env, -1); + } + return 0; +} + +void +usage( + axis2_char_t * prog_name) +{ + fprintf(stdout, "\n Usage : %s", prog_name); + fprintf(stdout, " [-p PORT]"); + fprintf(stdout, " [-t TIMEOUT]"); + fprintf(stdout, " [-r REPO_PATH]"); + fprintf(stdout, " [-l LOG_LEVEL]"); + fprintf(stdout, " [-f LOG_FILE]\n"); + fprintf(stdout, " [-s LOG_FILE_SIZE]\n"); + fprintf(stdout, " Options :\n"); + fprintf(stdout, "\t-p PORT \t port number to use, default port is 9090\n"); + fprintf(stdout, "\t-r REPO_PATH \t repository path, default is ../\n"); + fprintf(stdout, "\t-t TIMEOUT\t socket read timeout, default is 30 seconds\n"); + fprintf(stdout, "\t-l LOG_LEVEL\t log level, available log levels:" + "\n\t\t\t 0 - critical 1 - errors 2 - warnings" + "\n\t\t\t 3 - information 4 - debug 5- user 6- trace" + "\n\t\t\t Default log level is 4(debug).\n"); +#ifndef WIN32 + fprintf(stdout, "\t-f LOG_FILE\t log file, default is $AXIS2C_HOME/logs/axis2.log" + "\n\t\t\t or axis2.log in current folder if AXIS2C_HOME not set\n"); +#else + fprintf(stdout, + "\t-f LOG_FILE\t log file, default is %%AXIS2C_HOME%%\\logs\\axis2.log" + "\n\t\t\t or axis2.log in current folder if AXIS2C_HOME not set\n"); +#endif + fprintf(stdout, + "\t-s LOG_FILE_SIZE\t Maximum log file size in mega bytes, default maximum size is 1MB.\n"); + fprintf(stdout, " Help :\n\t-h \t display this help screen.\n\n"); +} + +/** + * Signal handler + */ +void +sig_handler( + int signal) +{ + + if(!system_env) + { + AXIS2_LOG_ERROR( + system_env->log, + AXIS2_LOG_SI, + "Received signal %d, unable to proceed system_env is NULL ,\ + system exit with -1", + signal); + _exit(-1); + } + + switch(signal) + { + case SIGINT: + { + /* Use of SIGINT in Windows is valid, since we have a console application + * Thus, eventhough this may a single threaded application, it does work. + */ + AXIS2_LOG_INFO(system_env->log, "Received signal SIGINT. Server " + "shutting down"); + if(server) + { + axis2_http_server_stop(server, system_env); + } + + AXIS2_LOG_INFO(system_env->log, "Shutdown complete ..."); + system_exit(system_env, 0); + } +#ifndef WIN32 + case SIGPIPE: + { + AXIS2_LOG_INFO(system_env->log, "Received signal SIGPIPE. Client " + "request serve aborted"); + return; + } +#endif + case SIGSEGV: + { + fprintf(stderr, "Received deadly signal SIGSEGV. Terminating\n"); + _exit(-1); + } + } +} |