/* * 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 #include #include "axis2_iis_stream.h" #include /** * @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; }