blob: bdc4e03132820b92782e70dc2e4dad4cf9153cae [file] [log] [blame]
/*
* 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 <axutil_stream.h>
#include <platforms/axutil_platform_auto_sense.h>
/** basic stream operatons **/
int AXIS2_CALL axutil_stream_write_basic(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count);
int AXIS2_CALL axutil_stream_read_basic(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count);
int AXIS2_CALL axutil_stream_skip_basic(
axutil_stream_t *stream,
const axutil_env_t *env,
int count);
/** file stream operations **/
int AXIS2_CALL axutil_stream_write_file(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count);
int AXIS2_CALL axutil_stream_read_file(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count);
int AXIS2_CALL axutil_stream_skip_file(
axutil_stream_t *stream,
const axutil_env_t *env,
int count);
/** socket stream operations **/
int AXIS2_CALL axutil_stream_write_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count);
int AXIS2_CALL axutil_stream_read_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count);
int AXIS2_CALL axutil_stream_skip_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
int count);
AXIS2_EXTERN axutil_stream_t *AXIS2_CALL
axutil_stream_create_internal(
const axutil_env_t *env)
{
axutil_stream_t *stream = NULL;
stream = (axutil_stream_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_stream_t));
if(!stream)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory. Cannot create axutil stream");
return NULL;
}
stream->buffer = NULL;
stream->buffer_head = NULL;
stream->fp = NULL;
stream->socket = -1;
stream->len = -1;
stream->max_len = -1;
stream->axis2_eof = EOF;
return stream;
}
void AXIS2_CALL
axutil_stream_free(
axutil_stream_t *stream,
const axutil_env_t *env)
{
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
/* avoid access violation / segment fault */
if (stream == NULL)
{
return;
}
switch(stream->stream_type)
{
case AXIS2_STREAM_BASIC:
{
if(stream->buffer_head)
{
AXIS2_FREE(env->allocator, stream->buffer_head);
}
stream->buffer = NULL;
stream->len = -1;
break;
}
case AXIS2_STREAM_FILE:
{
stream->fp = NULL;
stream->len = -1;
break;
}
case AXIS2_STREAM_SOCKET:
{
if(stream->fp)
{
fclose(stream->fp);
}
stream->socket = -1;
stream->len = -1;
break;
}
default:
break;
}
AXIS2_FREE(env->allocator, stream);
}
void AXIS2_CALL
axutil_stream_free_void_arg(
void *stream,
const axutil_env_t *env)
{
axutil_stream_t *stream_l = NULL;
stream_l = (axutil_stream_t *)stream;
axutil_stream_free(stream_l, env);
return;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_flush(
axutil_stream_t *stream,
const axutil_env_t *env)
{
if(stream->fp)
{
if(fflush(stream->fp))
{
return AXIS2_FAILURE;
}
}
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_close(
axutil_stream_t *stream,
const axutil_env_t *env)
{
switch(stream->stream_type)
{
case AXIS2_STREAM_BASIC:
{
if(stream->buffer_head)
{
AXIS2_FREE(env->allocator, stream->buffer_head);
}
stream->buffer = NULL;
stream->len = -1;
break;
}
case AXIS2_STREAM_FILE:
{
if(stream->fp)
{
if(fclose(stream->fp))
{
return AXIS2_FAILURE;
}
}
stream->fp = NULL;
stream->len = -1;
break;
}
case AXIS2_STREAM_SOCKET:
{
if(stream->fp)
{
if(fclose(stream->fp))
{
return AXIS2_FAILURE;
}
}
stream->socket = -1;
stream->len = -1;
break;
}
default:
break;
}
return AXIS2_SUCCESS;
}
/************************ Basic Stream Operations *****************************/
AXIS2_EXTERN axutil_stream_t *AXIS2_CALL
axutil_stream_create_basic(
const axutil_env_t *env)
{
axutil_stream_t *stream = NULL;
AXIS2_ENV_CHECK(env, NULL);
stream = axutil_stream_create_internal(env);
if(!stream)
{
/*
* We leave the error returned by the
* axutil_stream_create_internal intact
*/
return NULL;
}
stream->stream_type = AXIS2_STREAM_BASIC;
stream->read = axutil_stream_read_basic;
stream->write = axutil_stream_write_basic;
stream->skip = axutil_stream_skip_basic;
stream->buffer = (axis2_char_t *)AXIS2_MALLOC(env->allocator, AXIS2_STREAM_DEFAULT_BUF_SIZE
* sizeof(axis2_char_t));
stream->buffer_head = stream->buffer;
stream->len = 0;
stream->max_len = AXIS2_STREAM_DEFAULT_BUF_SIZE;
if(!stream->buffer)
{
axutil_stream_free(stream, env);
return NULL;
}
return stream;
}
int AXIS2_CALL
axutil_stream_read_basic(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count)
{
int len = 0;
char *buf = NULL;
buf = stream->buffer;
if(!buf)
{
return -1;
}
if(!buffer)
{
return -1;
}
if((int)(count - 1) > stream->len)
/* We are sure that the difference lies within the int range */
{
len = stream->len;
}
else
{
len = (int)(count - 1);
/* We are sure that the difference lies within the int range */
}
memcpy(buffer, buf, len);
/*
* Finally we need to remove the read bytes from the stream
* adjust the length of the stream.
*/
stream->len -= len;
stream->buffer = buf + len;
((axis2_char_t *)buffer)[len] = '\0';
return len;
}
int AXIS2_CALL
axutil_stream_write_basic(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count)
{
int new_len = 0;
if(!buffer)
return -1;
new_len = (int)(stream->len + count);
/* We are sure that the difference lies within the int range */
if(new_len > stream->max_len)
{
axis2_char_t *tmp = (axis2_char_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t)
* (new_len + AXIS2_STREAM_DEFAULT_BUF_SIZE));
if(!tmp)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
return -1;
}
/*
* pre allocation: extra AXIS2_STREAM_DEFAULT_BUF_SIZE more bytes
* allocated
*/
stream->max_len = new_len + AXIS2_STREAM_DEFAULT_BUF_SIZE;
memcpy(tmp, stream->buffer, sizeof(axis2_char_t) * stream->len);
AXIS2_FREE(env->allocator, stream->buffer_head);
stream->buffer = tmp;
stream->buffer_head = tmp;
}
memcpy(stream->buffer + (stream->len * sizeof(axis2_char_t)), buffer, count);
stream->len += (int)count;
/* We are sure that the difference lies within the int range */
return (int)count;
}
int AXIS2_CALL
axutil_stream_get_len(
axutil_stream_t *stream,
const axutil_env_t *env)
{
return stream->len;
}
int AXIS2_CALL
axutil_stream_skip_basic(
axutil_stream_t *stream,
const axutil_env_t *env,
int count)
{
int del_len = 0;
if(count > 0)
{
if(count <= stream->len)
{
del_len = count;
}
else
{
del_len = stream->len;
}
stream->len -= del_len;
stream->buffer += del_len;
return del_len;
}
return -1;
}
AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_stream_get_buffer(
const axutil_stream_t *stream,
const axutil_env_t *env)
{
return stream->buffer;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_flush_buffer(
axutil_stream_t *stream,
const axutil_env_t *env)
{
stream->len = 0;
return AXIS2_SUCCESS;
}
/********************* End of Basic Stream Operations *************************/
/************************** File Stream Operations ****************************/
AXIS2_EXTERN axutil_stream_t *AXIS2_CALL
axutil_stream_create_file(
const axutil_env_t *env,
FILE * fp)
{
axutil_stream_t *stream = NULL;
AXIS2_ENV_CHECK(env, NULL);
stream = axutil_stream_create_internal(env);
if(!stream)
{
/*
* We leave the error returned by the
* axutil_stream_create_internal intact
*/
return NULL;
}
stream->stream_type = AXIS2_STREAM_FILE;
stream->fp = fp;
stream->read = axutil_stream_read_file;
stream->write = axutil_stream_write_file;
stream->skip = axutil_stream_skip_file;
return stream;
}
int AXIS2_CALL
axutil_stream_read_file(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count)
{
FILE *fp = NULL;
if(!stream->fp)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_FD, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Trying to do operation on invalid file descriptor");
return -1;
}
fp = stream->fp;
if(!buffer)
{
return -1;
}
return (int)fread(buffer, sizeof(axis2_char_t), count, fp);
/* We are sure that the difference lies within the int range */
}
int AXIS2_CALL
axutil_stream_write_file(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count)
{
int len = 0;
FILE *fp = NULL;
if(!(stream->fp))
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_FD, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Trying to do operation on invalid file descriptor");
return -1;
}
fp = stream->fp;
if(!buffer)
return -1;
len = (int)fwrite(buffer, sizeof(axis2_char_t), count, fp);
/* We are sure that the difference lies within the int range */
return len;
}
int AXIS2_CALL
axutil_stream_skip_file(
axutil_stream_t *stream,
const axutil_env_t *env,
int count)
{
int c = -1;
int i = count;
if(!(stream->fp))
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_FD, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Trying to do operation on invalid file descriptor");
return -1;
}
while(EOF != (c = fgetc(stream->fp)) && i > 0)
{
i--;
}
return count - i;
}
/********************** End of File Stream Operations *************************/
/************************** Socket Stream Operations **************************/
AXIS2_EXTERN axutil_stream_t *AXIS2_CALL
axutil_stream_create_socket(
const axutil_env_t *env,
int socket)
{
axutil_stream_t *stream = NULL;
stream = axutil_stream_create_internal(env);
if(!stream)
{
/*
* We leave the error returned by the
* axutil_stream_create_internal intact
*/
return NULL;
}
stream->read = axutil_stream_read_socket;
stream->write = axutil_stream_write_socket;
stream->skip = axutil_stream_skip_socket;
stream->peek = axutil_stream_peek_socket;
stream->stream_type = AXIS2_STREAM_SOCKET;
stream->socket = socket;
stream->fp = NULL;
return stream;
}
int AXIS2_CALL
axutil_stream_read_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count)
{
int len = 0;
if(-1 == stream->socket)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_SOCKET, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"Trying to do operation on closed/not-opened socket");
return -1;
}
if(!buffer)
{
return -1;
}
len = (int)recv(stream->socket, buffer, (int)count, 0);
/* We are sure that the difference lies within the int range */
#ifdef AXIS2_TCPMON
if (len > 1)
{
axis2_char_t *temp = NULL;
temp = (axis2_char_t *) AXIS2_MALLOC(env->allocator, (len + 1) * sizeof(axis2_char_t));
if (temp)
{
memcpy(temp, buffer, len * sizeof(axis2_char_t));
temp[len] = '\0';
fprintf(stderr, "%s", temp);
AXIS2_FREE(env->allocator, temp);
}
}
#endif
return len;
}
int AXIS2_CALL
axutil_stream_write_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count)
{
int len = 0;
#ifdef AXIS2_TCPMON
axis2_char_t *temp = NULL;
#endif
if(-1 == stream->socket)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_SOCKET, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"Trying to do operation on closed/not-opened socket");
return -1;
}
if(!buffer)
return -1;
len = (int)send(stream->socket, buffer, (int)count, 0);
/* We are sure that the difference lies within the int range */
#ifdef AXIS2_TCPMON
if (len > 0)
{
temp =
(axis2_char_t *) AXIS2_MALLOC(env->allocator,
(len + 1) * sizeof(axis2_char_t));
if (temp)
{
memcpy(temp, buffer, len * sizeof(axis2_char_t));
temp[len] = '\0';
fprintf(stderr, "%s", temp);
AXIS2_FREE(env->allocator, temp);
}
}
#endif
return len;
}
int AXIS2_CALL
axutil_stream_skip_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
int count)
{
int len = 0;
int received = 0;
char buffer[2];
if(-1 == stream->socket)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_SOCKET, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"Trying to do operation on closed/not-opened socket");
return -1;
}
while(len < count)
{
received = recv(stream->socket, buffer, 1, 0);
if(received == 0)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Socket has being shutdown");
return -1;
}
if(received < 0)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error while trying to read the socke");
return -1;
}
len += received;
}
return len;
}
AXIS2_EXTERN int AXIS2_CALL
axutil_stream_peek_socket(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count)
{
int len = 0;
/* Added to prevent a segfault */
AXIS2_PARAM_CHECK(env->error, stream, -1);
if(-1 == stream->socket)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_SOCKET, AXIS2_FAILURE);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"Trying to do operation on closed/not-opened socket");
return -1;
}
if(!buffer)
{
return -1;
}
len = (int)recv(stream->socket, buffer, (int)count, MSG_PEEK);
/* We are sure that the difference lies within the int range */
return len;
}
/********************** End of Socket Stream Operations ***********************/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_set_read(
axutil_stream_t *stream,
const axutil_env_t *env,
AXUTIL_STREAM_READ func)
{
stream->read = func;
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_set_write(
axutil_stream_t *stream,
const axutil_env_t *env,
AXUTIL_STREAM_WRITE func)
{
stream->write = func;
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_set_skip(
axutil_stream_t *stream,
const axutil_env_t *env,
AXUTIL_STREAM_SKIP func)
{
stream->skip = func;
return AXIS2_SUCCESS;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_stream_set_peek(
axutil_stream_t *stream,
const axutil_env_t *env,
AXUTIL_STREAM_PEEK func)
{
stream->peek = func;
return AXIS2_SUCCESS;
}
AXIS2_EXTERN int AXIS2_CALL
axutil_stream_read(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
size_t count)
{
return stream->read(stream, env, buffer, count);
}
AXIS2_EXTERN int AXIS2_CALL
axutil_stream_write(
axutil_stream_t *stream,
const axutil_env_t *env,
const void *buffer,
size_t count)
{
return stream->write(stream, env, buffer, count);
}
AXIS2_EXTERN int AXIS2_CALL
axutil_stream_skip(
axutil_stream_t *stream,
const axutil_env_t *env,
int count)
{
return stream->skip(stream, env, count);
}
AXIS2_EXTERN int AXIS2_CALL
axutil_stream_peek(
axutil_stream_t *stream,
const axutil_env_t *env,
void *buffer,
int count)
{
return stream->peek(stream, env, buffer, count);
}