summaryrefslogtreecommitdiffstats
path: root/src/core/transport/http/server/IIS/axis2_iis_worker.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/transport/http/server/IIS/axis2_iis_worker.c')
-rw-r--r--src/core/transport/http/server/IIS/axis2_iis_worker.c607
1 files changed, 607 insertions, 0 deletions
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;
+}
+