#include "rcsversion.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef __cplusplus
}
#endif
#include "cms.hh"
#include "cms_up.hh"
#include "cms_xup.hh"
#include "cms_aup.hh"
#include "cms_dup.hh"
#include "rcs_print.hh"
#include "cmsdiag.hh"
#include "linklist.hh"
#include "physmem.hh"
LinkedList *cmsHostAliases = NULL;
CMS_CONNECTION_MODE cms_connection_mode = CMS_NORMAL_CONNECTION_MODE;
int CMS::number_of_cms_objects = 0;
int cms_encoded_data_explosion_factor = 4;
#if 0#endif
static int convert2upper(char *dest, const char *src, int len)
{
int i;
for (i = 0; i < len; i++) {
if (src[i] == 0) {
dest[i] = 0;
return i;
}
dest[i] = toupper(src[i]);
}
return i;
}
void *CMS::operator new(size_t size)
{
if (size < sizeof(CMS)) {
rcs_print_error
("CMS::operator new -- The size requested %zu is less than the mininimum size of CMS %zu.\n",
size, sizeof(CMS));
rcs_print_error("This could indicate a version mismatch problem.\n");
size = sizeof(CMS);
}
void *space = (void *) malloc(size);
if (NULL != space) {
memset(space, 0, size);
}
rcs_print_debug(PRINT_CMS_CONSTRUCTORS, "%p = CMS::new(%zu)\n", space,
size);
return space;
}
void CMS::operator delete(void *space)
{
rcs_print_debug(PRINT_CMS_DESTRUCTORS, " CMS::delete(%p)\n", space);
free(space);
rcs_print_debug(PRINT_CMS_DESTRUCTORS, " CMS::delete successful.\n");
}
CMS::CMS(long s)
{
rcs_print_debug(PRINT_CMS_CONSTRUCTORS, "new CMS (%lu)", s);
memset(BufferName, 0, CMS_CONFIG_LINELEN);
memset(BufferHost, 0, CMS_CONFIG_LINELEN);
memset(ProcessName, 0, CMS_CONFIG_LINELEN);
memset(BufferLine, 0, CMS_CONFIG_LINELEN);
memset(ProcessLine, 0, CMS_CONFIG_LINELEN);
memset(ProcessHost, 0, CMS_CONFIG_LINELEN);
memset(buflineupper, 0, CMS_CONFIG_LINELEN);
memset(proclineupper, 0, CMS_CONFIG_LINELEN);
memset(PermissionString, 0, CMS_CONFIG_LINELEN);
free_space = size = s;
force_raw = 0;
neutral = 0;
isserver = 0;
last_im = CMS_NOT_A_MODE;
min_compatible_version = 0;
confirm_write = 0;
disable_final_write_raw_for_dma = 0;
subdiv_data = 0;
enable_diagnostics = 0;
dpi = NULL;
di = NULL;
skip_area = 0;
half_offset = s / 2;
free_space = half_size = s / 2;
fast_mode = 0;
disable_diag_store = 0;
diag_offset = 0;
read_permission_flag = 0;
write_permission_flag = 0;
queuing_enabled = 0;
fatal_error_occurred = 0;
write_just_completed = 0;
neutral_encoding_method = CMS_XDR_ENCODING;
blocking_timeout = 0;
total_subdivisions = 1;
subdiv_size = size;
current_subdivision = 0;
enc_max_size = s;
max_encoded_message_size = s;
last_id_side0 = 0;
last_id_side1 = 0;
handle_to_global_data = NULL;
dummy_handle = (PHYSMEM_HANDLE *) NULL;
delete_totally = 0;
mode = CMS_NOT_A_MODE;
open();
}
CMS::CMS(const char *bufline_in, const char *procline_in, int set_to_server)
{
char *word[32]={0,};
char *buffer_type_name;
char *proc_type_name;
int i;
min_compatible_version = 0;
force_raw = 0;
serial = 0;
confirm_write = 0;
disable_final_write_raw_for_dma = 0;
memset(BufferName, 0, CMS_CONFIG_LINELEN);
memset(BufferHost, 0, CMS_CONFIG_LINELEN);
memset(ProcessName, 0, CMS_CONFIG_LINELEN);
memset(BufferLine, 0, CMS_CONFIG_LINELEN);
memset(ProcessLine, 0, CMS_CONFIG_LINELEN);
memset(ProcessHost, 0, CMS_CONFIG_LINELEN);
memset(buflineupper, 0, CMS_CONFIG_LINELEN);
memset(proclineupper, 0, CMS_CONFIG_LINELEN);
memset(PermissionString, 0, CMS_CONFIG_LINELEN);
read_permission_flag = 0;
write_permission_flag = 0;
queuing_enabled = 0;
fatal_error_occurred = 0;
write_just_completed = 0;
neutral_encoding_method = CMS_XDR_ENCODING;
blocking_timeout = 0;
min_compatible_version = 0;
enc_max_size = -1;
max_encoded_message_size = 0;
enable_diagnostics = 0;
dpi = NULL;
di = NULL;
disable_diag_store = 0;
diag_offset = 0;
use_autokey_for_connection_number = 0;
if ((NULL == bufline_in) || (NULL == procline_in)) {
rcs_print_error("CMS: Pointer to bufline or procline is NULL.\n");
return;
}
char *bufline = strdup(bufline_in);
char *procline = strdup(procline_in);
convert2upper(buflineupper, bufline, CMS_CONFIG_LINELEN);
convert2upper(proclineupper, procline, CMS_CONFIG_LINELEN);
is_phantom = 0;
max_message_size = 0;
using_external_encoded_data = 0;
in_buffer_id = 0;
last_id_side0 = 0;
last_id_side1 = 0;
delete_totally = 0;
queuing_enabled = 0;
split_buffer = 0;
fatal_error_occurred = 0;
consecutive_timeouts = 0;
write_just_completed = 0;
pointer_check_disabled = 0;
blocking_timeout = 0;
last_im = CMS_NOT_A_MODE;
total_subdivisions = 1;
size = 0;
subdiv_size = 0;
current_subdivision = 0;
max_encoded_message_size = 0;
skip_area = 0;
half_offset = 0;
half_size = 0;
fast_mode = 0;
last_id_side0 = 0;
last_id_side1 = 0;
free_space = 0;
handle_to_global_data = NULL;
dummy_handle = (PHYSMEM_HANDLE *) NULL;
remote_port_type = CMS_NO_REMOTE_PORT_TYPE;
strcpy(BufferLine, bufline);
strcpy(ProcessLine, procline);
if (separate_words(word, 9, bufline) != 9) {
rcs_print_error("CMS: Error in buffer line from config file.\n");
rcs_print_error("%s\n", bufline);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
strcpy(BufferName, word[1]);
rcs_print_debug(PRINT_CMS_CONSTRUCTORS, "new CMS (%s)\n", BufferName);
if (errno == ERANGE) {
errno = 0;
}
char *realname = cms_check_for_host_alias(word[3]);
if (realname == NULL) {
strcpy(BufferHost, word[3]);
} else {
strcpy(BufferHost, realname);
}
buffer_type_name = word[2];
size = (long) strtol(word[4], (char **) NULL, 0);
neutral = (int) strtol(word[5], (char **) NULL, 0);
rpc_program_number = strtol(word[6], (char **) NULL, 0);
buffer_number = strtol(word[7], (char **) NULL, 0);
total_connections = strtol(word[8], (char **) NULL, 0);
free_space = size;
if (ERANGE == errno) {
rcs_print_error("CMS: Error in buffer line from config file.\n");
rcs_print_error("%s\n", bufline);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
if (!strcmp(buffer_type_name, "SHMEM")) {
BufferType = CMS_SHMEM_TYPE;
} else if (!strcmp(buffer_type_name, "PHANTOM")) {
BufferType = CMS_PHANTOM_BUFFER;
is_phantom = 1;
} else if (!strcmp(buffer_type_name, "LOCMEM")) {
BufferType = CMS_LOCMEM_TYPE;
} else if (!strcmp(buffer_type_name, "FILEMEM")) {
BufferType = CMS_FILEMEM_TYPE;
} else {
rcs_print_error("CMS: invalid buffer type (%s)\n", buffer_type_name);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
int num_words = separate_words(word, 32, buflineupper);
if (num_words < 8) {
rcs_print_error("CMS: Error in buffer line from config file.\n");
rcs_print_error("%s\n", bufline);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
for (i = 8; i < num_words && i < 32; i++) {
if (word[i] == NULL) {
break;
}
if (!strcmp(word[i], "QUEUE")) {
queuing_enabled = 1;
continue;
}
if (!strcmp(word[i], "DIAG")) {
enable_diagnostics = 1;
continue;
}
if (!strcmp(word[i], "SPLIT")) {
split_buffer = 1;
continue;
}
if (!strcmp(word[i], "DISP")) {
neutral_encoding_method = CMS_DISPLAY_ASCII_ENCODING;
continue;
}
if (!strcmp(buflineupper, "ASCII")) {
neutral_encoding_method = CMS_ASCII_ENCODING;
continue;
}
if (!strcmp(buflineupper, "XDR")) {
neutral_encoding_method = CMS_XDR_ENCODING;
continue;
}
char *port_string;
if (NULL != (port_string = strstr(word[i], "STCP="))) {
remote_port_type = CMS_STCP_REMOTE_PORT_TYPE;
stcp_port_number =
(int) strtol(port_string + 5, (char **) NULL, 0);
continue;
} else if (NULL != (port_string = strstr(word[i], "TCP="))) {
remote_port_type = CMS_TCP_REMOTE_PORT_TYPE;
tcp_port_number =
(int) strtol(port_string + 4, (char **) NULL, 0);
continue;
} else if (NULL != (port_string = strstr(word[i], "UDP="))) {
remote_port_type = CMS_UDP_REMOTE_PORT_TYPE;
udp_port_number =
(int) strtol(port_string + 4, (char **) NULL, 0);
continue;
}
char *version_string;
if (NULL != (version_string = strstr(word[i], "VERSION="))) {
min_compatible_version =
strtod(version_string + 8, (char **) NULL);
continue;
}
char *subdiv_string;
if (NULL != (subdiv_string = strstr(word[i], "SUBDIV="))) {
total_subdivisions = strtol(subdiv_string + 7, (char **) NULL, 0);
subdiv_size = size / total_subdivisions;
subdiv_size -= subdiv_size % 4;
continue;
}
char *enc_max_string;
if (NULL != (enc_max_string = strstr(word[i], "ENC_MAX_SIZE="))) {
enc_max_size = strtoul(enc_max_string + 13, (char **) NULL, 0);
continue;
}
if (!strcmp(word[i], "SERIAL")) {
serial = 1;
continue;
}
if (!strcmp(word[i], "CONFIRM_WRITE")) {
confirm_write = 1;
continue;
}
if (!strcmp(word[i], "FORCE_RAW")) {
force_raw = 1;
continue;
}
if (!strcmp(word[i], "AUTOCNUM")) {
use_autokey_for_connection_number = 1;
continue;
}
}
if (use_autokey_for_connection_number) {
if (separate_words(word, 9, procline) != 9) {
rcs_print_error
("CMS: Error parsing process line from config file.\n");
rcs_print_error("%s\n", procline);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
} else {
if (separate_words(word, 10, procline) != 10) {
rcs_print_error
("CMS: Error parsing process line from config file.\n");
rcs_print_error("%s\n", procline);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
}
if (errno == ERANGE) {
errno = 0;
}
strcpy(ProcessName, word[1]);
strcpy(ProcessHost, word[4]);
if (errno == ERANGE) {
errno = 0;
}
proc_type_name = word[3];
strcpy(PermissionString, word[5]);
spawn_server = atoi(word[6]);
if (!strcmp(word[7], "INF")) {
timeout = -1;
} else {
timeout = strtod(word[7], (char **) NULL);
}
is_local_master = (int) atol(word[8]);
if (!use_autokey_for_connection_number) {
connection_number = atol(word[9]);
if (total_connections <= connection_number) {
rcs_print_error
("CMS: connection number(%lu) must be less than total connections (%lu).\n",
connection_number, total_connections);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
}
if (ERANGE == errno) {
rcs_print_error("CMS: Error in proc line from config file.\n");
rcs_print_error("%s\n", procline);
status = CMS_CONFIG_ERROR;
free(bufline);
free(procline);
return;
}
if (set_to_server < 0) {
isserver = 0;
} else if (set_to_server > 0) {
isserver = 1;
} else {
isserver = (spawn_server == 1);
}
switch (cms_connection_mode) {
case CMS_NORMAL_CONNECTION_MODE:
if (!strcmp(proc_type_name, "REMOTE")) {
ProcessType = CMS_REMOTE_TYPE;
spawn_server = 0;
} else if (!strcmp(proc_type_name, "LOCAL")) {
ProcessType = CMS_LOCAL_TYPE;
} else if (!strcmp(proc_type_name, "AUTO")) {
if (hostname_matches_bufferline(BufferLine)) {
ProcessType = CMS_LOCAL_TYPE;
} else {
ProcessType = CMS_REMOTE_TYPE;
spawn_server = 0;
}
} else if (!strcmp(proc_type_name, "PHANTOM")) {
ProcessType = CMS_PHANTOM_USER;
spawn_server = 0;
is_phantom = 1;
} else {
rcs_print_error("CMS: invalid process type (%s)/n",
proc_type_name);
status = CMS_CONFIG_ERROR;
return;
}
break;
case CMS_FORCE_LOCAL_CONNECTION_MODE:
ProcessType = CMS_LOCAL_TYPE;
break;
case CMS_FORCE_REMOTE_CONNECTION_MODE:
ProcessType = CMS_REMOTE_TYPE;
break;
}
if (NULL != strchr(PermissionString, 'R')) {
read_permission_flag = 1;
} else {
read_permission_flag = 0;
}
if (NULL != strchr(PermissionString, 'W')) {
write_permission_flag = 1;
} else {
write_permission_flag = 0;
}
if (isserver) {
read_permission_flag = 1;
write_permission_flag = 1;
}
mode = CMS_NOT_A_MODE;
if (NULL != strstr(ProcessLine, "serialPortDevName=")) {
remote_port_type = CMS_TTY_REMOTE_PORT_TYPE;
}
if (min_compatible_version < 3.44 && min_compatible_version > 0) {
total_subdivisions = 1;
}
if (queuing_enabled && split_buffer) {
rcs_print_error("CMS: Can not split buffer with queuing enabled.\n");
status = CMS_CONFIG_ERROR;
return;
}
if (min_compatible_version > 3.39 || min_compatible_version <= 0.0) {
if (neutral_encoding_method == CMS_ASCII_ENCODING) {
neutral_encoding_method = CMS_DISPLAY_ASCII_ENCODING;
}
}
if (min_compatible_version <= 3.71 && min_compatible_version >= 1e-6) {
rcs_print("NO DIAGNOSTICS\n");
enable_diagnostics = 0;
}
open();
if (enable_diagnostics) {
setup_diag_proc_info();
}
free(bufline);
free(procline);
}
void CMS::open(void)
{
int encode_header_ret;
int encode_queuing_header_ret;
status = CMS_STATUS_NOT_SET;
data = NULL;
subdiv_data = NULL;
encoded_data = NULL;
encoded_header = NULL;
encoded_queuing_header = NULL;
encoded_header_size = 0;
updater = (CMS_UPDATER *) NULL;
normal_updater = (CMS_UPDATER *) NULL;
temp_updater = (CMS_UPDATER *) NULL;
last_im = CMS_NOT_A_MODE;
pointer_check_disabled = 0;
dummy_handle = (PHYSMEM_HANDLE *) NULL;
first_read_done = 0;
first_write_done = 0;
total_messages_missed = 0;
messages_missed_on_last_read = 0;
format_low_ptr = (char *) NULL;
format_high_ptr = (char *) NULL;
header.was_read = 0;
header.write_id = 0;
header.in_buffer_size = 0;
number_of_cms_objects++;
if (!is_phantom) {
data = malloc(size);
memset(data, 0, size);
subdiv_data = data;
if (force_raw) {
encoded_data = data;
}
rcs_print_debug(PRINT_CMS_CONSTRUCTORS, "%p = data = calloc(%lu,1);\n",
data, size);
if (data == NULL) {
rcs_print_error("CMS: Can't allocate memory for local buffer.\n");
status = CMS_CREATE_ERROR;
return;
}
}
if (isserver || neutral || ((ProcessType == CMS_REMOTE_TYPE) && !force_raw)) {
switch (neutral_encoding_method) {
case CMS_XDR_ENCODING:
updater = new CMS_XDR_UPDATER(this);
break;
case CMS_ASCII_ENCODING:
updater = new CMS_ASCII_UPDATER(this);
break;
case CMS_DISPLAY_ASCII_ENCODING:
updater = new CMS_DISPLAY_ASCII_UPDATER(this);
break;
default:
updater = (CMS_UPDATER *) NULL;
status = CMS_UPDATE_ERROR;
rcs_print_error("CMS: Invalid encoding method(%d)\n",
neutral_encoding_method);
break;
}
normal_updater = updater;
if (((int) status) < 0) {
return;
}
if ((encode_header_ret = encode_header()) == -1) {
rcs_print_error("CMS:Error encoding CMS header.\n");
status = CMS_MISC_ERROR;
return;
}
encoded_header_size = (long) encode_header_ret;
if (min_compatible_version <= 0.0 || min_compatible_version > 3.29) {
if (neutral_encoding_method == CMS_DISPLAY_ASCII_ENCODING) {
encoded_header_size = 16;
}
}
if (queuing_enabled) {
memset(&queuing_header, 0, sizeof(queuing_header));
if ((encode_queuing_header_ret = encode_queuing_header()) == -1) {
rcs_print_error("CMS:Error encoding CMS queuing_header.\n");
status = CMS_MISC_ERROR;
return;
}
encoded_queuing_header_size = (long) encode_queuing_header_ret;
}
}
if (split_buffer && total_subdivisions > 1) {
rcs_print_error
("Can't split buffer and use subdivisions. (total_subsivisions=%d)",
total_subdivisions);
status = CMS_MISC_ERROR;
return;
}
int nfactor = 4;
if (NULL != updater) {
nfactor = updater->neutral_size_factor;
}
size_without_diagnostics = size;
diag_offset = 0;
if (enable_diagnostics) {
diag_offset = (sizeof(CMS_DIAG_HEADER) +
(total_connections * sizeof(CMS_DIAG_PROC_INFO)));
size_without_diagnostics -= diag_offset;
}
skip_area = 0;
half_offset = (size_without_diagnostics / 2);
half_size = (size_without_diagnostics / 2);
fast_mode = 0;
if (split_buffer) {
if (neutral) {
subdiv_size = (size_without_diagnostics / 2) - total_connections;
subdiv_size -= (subdiv_size % 4);
max_message_size =
(size_without_diagnostics / 2) - total_connections -
encoded_header_size - 2;
max_encoded_message_size =
size_without_diagnostics - total_connections -
encoded_header_size;
guaranteed_message_space =
max_message_size / cms_encoded_data_explosion_factor;
} else {
if (ProcessType == CMS_REMOTE_TYPE) {
subdiv_size =
(size_without_diagnostics / 2) - total_connections;
subdiv_size -= (subdiv_size % 4);
max_message_size =
(size_without_diagnostics / 2) - total_connections -
sizeof(CMS_HEADER) - 2;
max_encoded_message_size = nfactor * max_message_size;
guaranteed_message_space = max_message_size / nfactor;
} else {
subdiv_size =
(size_without_diagnostics / 2) - total_connections;
subdiv_size -= (subdiv_size % 4);
max_message_size =
(size_without_diagnostics / 2) - total_connections -
sizeof(CMS_HEADER) - 2;
max_encoded_message_size = nfactor * max_message_size;
guaranteed_message_space = max_message_size;
}
}
} else {
if (neutral) {
subdiv_size =
(size_without_diagnostics -
total_connections) / total_subdivisions;
subdiv_size -= (subdiv_size % 4);
max_message_size = subdiv_size - encoded_header_size;
max_encoded_message_size = subdiv_size - encoded_header_size;
guaranteed_message_space = max_message_size / nfactor;
} else {
if (ProcessType == CMS_REMOTE_TYPE) {
subdiv_size =
(size_without_diagnostics -
total_connections) / total_subdivisions;
subdiv_size -= (subdiv_size % 4);
max_message_size = subdiv_size - sizeof(CMS_HEADER);
max_encoded_message_size = nfactor * max_message_size;
guaranteed_message_space = max_message_size / nfactor;
} else {
subdiv_size =
(size_without_diagnostics -
total_connections) / total_subdivisions;
subdiv_size -= (subdiv_size % 4);
max_message_size = subdiv_size - sizeof(CMS_HEADER);
max_encoded_message_size = nfactor * max_message_size;
guaranteed_message_space = max_message_size;
}
}
}
if (enc_max_size > 0 && enc_max_size < max_encoded_message_size) {
max_encoded_message_size = enc_max_size;
}
if ((neutral || ProcessType == CMS_REMOTE_TYPE) && !isserver) {
read_mode = CMS_DECODE;
read_updater_mode = CMS_DECODE_DATA;
write_mode = CMS_ENCODE;
write_updater_mode = CMS_ENCODE_DATA;
} else if (!neutral && isserver && !force_raw) {
read_mode = CMS_ENCODE;
read_updater_mode = CMS_ENCODE_DATA;
write_mode = CMS_DECODE;
write_updater_mode = CMS_DECODE_DATA;
} else {
read_mode = CMS_RAW_OUT;
read_updater_mode = CMS_NO_UPDATE;
write_mode = CMS_RAW_IN;
write_updater_mode = CMS_NO_UPDATE;
}
}
void CMS::set_encoded_data(void *_encoded_data, long _encoded_data_size)
{
if (force_raw) {
if (NULL != data && data != _encoded_data) {
free(data);
}
data = encoded_data = _encoded_data;
encoded_data_size = size;
subdiv_data = data;
using_external_encoded_data = 1;
} else {
if (max_encoded_message_size > _encoded_data_size) {
max_encoded_message_size = _encoded_data_size;
}
if (NULL != updater) {
updater->set_encoded_data(_encoded_data, _encoded_data_size);
}
if (NULL != _encoded_data) {
memset(_encoded_data, 0, max_encoded_message_size);
}
using_external_encoded_data = 1;
}
}
CMS::~CMS()
{
rcs_print_debug(PRINT_CMS_DESTRUCTORS, "deleting CMS (%s)\n", BufferName);
if (NULL != updater) {
delete updater;
updater = (CMS_UPDATER *) NULL;
}
if (NULL != data && (!force_raw || !using_external_encoded_data)) {
rcs_print_debug(PRINT_CMS_DESTRUCTORS, "free( data = %p);\n", data);
free(data);
data = NULL;
if (force_raw) {
encoded_data = NULL;
}
}
number_of_cms_objects--;
if (NULL != dummy_handle) {
delete dummy_handle;
dummy_handle = (PHYSMEM_HANDLE *) NULL;
}
rcs_print_debug(PRINT_CMS_DESTRUCTORS, "Leaving ~CMS()\n");
}
CMS_STATUS CMS::main_access(void *_local, int *serial_number)
{
rcs_print_error("CMS::main_access called by %s for %s.\n",
ProcessName, BufferName);
rcs_print_error("This should never happen.\n");
rcs_print_error
("Derived classes should either override main_access() or\n");
rcs_print_error("the functions that call it.(read(), write(), etc.)\n");
rcs_print_error("_local = %p\n", _local);
return (CMS_MISC_ERROR);
}
CMS_STATUS CMS::check_id(CMSID id)
{
if (status < 0) {
return (status);
}
if (0 == id) {
messages_missed_on_last_read = 0;
in_buffer_id = 0;
return (status = CMS_READ_OLD);
}
if (id == in_buffer_id) {
status = CMS_READ_OLD;
messages_missed_on_last_read = 0;
} else {
if (split_buffer) {
if (id == last_id_side0 || id == last_id_side1) {
status = CMS_READ_OLD;
messages_missed_on_last_read = 0;
return (status);
}
if (toggle_bit) {
last_id_side0 = id;
} else {
last_id_side1 = id;
}
}
status = CMS_READ_OK;
messages_missed_on_last_read = id - in_buffer_id - 1;
if (messages_missed_on_last_read < 0) {
messages_missed_on_last_read = 0;
}
total_messages_missed += messages_missed_on_last_read;
in_buffer_id = id;
}
return (status);
}
void CMS::clean_buffers()
{
in_buffer_id = 0;
last_id_side0 = 0;
last_id_side1 = 0;
if (NULL != data) {
memset(data, 0, size);
}
if (NULL != encoded_data) {
memset(encoded_data, 0, max_encoded_message_size);
}
}
CMS_STATUS CMS::clear()
{
in_buffer_id = 0;
last_id_side0 = 0;
last_id_side1 = 0;
status = CMS_STATUS_NOT_SET;
internal_access_type = CMS_CLEAR_ACCESS;
main_access(data);
return (status);
}
int CMS::check_if_read()
{
internal_access_type = CMS_CHECK_IF_READ_ACCESS;
status = CMS_STATUS_NOT_SET;
main_access(data);
return ((int) header.was_read);
}
int CMS::get_queue_length()
{
internal_access_type = CMS_GET_QUEUE_LENGTH_ACCESS;
status = CMS_STATUS_NOT_SET;
if (!queuing_enabled) {
return 0;
}
main_access(data);
return ((int) queuing_header.queue_length);
}
int CMS::get_space_available()
{
internal_access_type = CMS_GET_SPACE_AVAILABLE_ACCESS;
status = CMS_STATUS_NOT_SET;
if (!queuing_enabled) {
return size;
}
main_access(data);
return ((int) free_space);
}
CMS_STATUS CMS::read()
{
internal_access_type = CMS_READ_ACCESS;
status = CMS_STATUS_NOT_SET;
blocking_timeout = 0;
main_access(data);
return (status);
}
CMS_STATUS CMS::blocking_read(double _blocking_timeout)
{
status = CMS_STATUS_NOT_SET;
internal_access_type = CMS_READ_ACCESS;
blocking_timeout = _blocking_timeout;
main_access(data);
return (status);
}
void CMS::disconnect()
{
}
void CMS::reconnect()
{
}
CMS_STATUS CMS::peek()
{
internal_access_type = CMS_PEEK_ACCESS;
status = CMS_STATUS_NOT_SET;
blocking_timeout = 0;
main_access(data);
return (status);
}
CMS_STATUS CMS::write(void *user_data, int *serial_number)
{
internal_access_type = CMS_WRITE_ACCESS;
status = CMS_STATUS_NOT_SET;
main_access(user_data, serial_number);
return (status);
}
CMS_STATUS CMS::write_if_read(void *user_data, int *serial_number)
{
internal_access_type = CMS_WRITE_IF_READ_ACCESS;
status = CMS_STATUS_NOT_SET;
main_access(user_data, serial_number);
return (status);
}
int CMS::login(const char *name, const char *passwd)
{
return 1;
}
void CMS::set_mode(CMSMODE im)
{
status = CMS_STATUS_NOT_SET;
if (last_im == im) {
return;
}
if (!force_raw) {
if (CMS_WRITE == im) {
mode = write_mode;
if (NULL != updater) {
updater->set_mode((CMS_UPDATER_MODE) write_updater_mode);
}
last_im = im;
return;
}
if (CMS_READ == im) {
mode = read_mode;
if (NULL != updater) {
updater->set_mode((CMS_UPDATER_MODE) read_updater_mode);
}
last_im = im;
return;
}
if (CMS_DECODE == im) {
mode = CMS_DECODE;
if (NULL != updater) {
updater->set_mode(CMS_DECODE_DATA);
}
}
if (CMS_ENCODE == im) {
mode = CMS_ENCODE;
if (NULL != updater) {
updater->set_mode(CMS_ENCODE_DATA);
}
}
}
last_im = im;
mode = im;
}
void CMS::set_temp_updater(CMS_NEUTRAL_ENCODING_METHOD temp_encoding_method)
{
if (force_raw) {
return;
}
if (temp_updater_encoding_method != temp_encoding_method &&
NULL != temp_updater) {
delete temp_updater;
temp_updater = (CMS_UPDATER *) NULL;
}
if (NULL == temp_updater) {
switch (temp_encoding_method) {
case CMS_XDR_ENCODING:
temp_updater = new CMS_XDR_UPDATER(this);
break;
case CMS_ASCII_ENCODING:
temp_updater = new CMS_ASCII_UPDATER(this);
break;
case CMS_DISPLAY_ASCII_ENCODING:
temp_updater = new CMS_DISPLAY_ASCII_UPDATER(this);
break;
default:
temp_updater = (CMS_UPDATER *) NULL;
status = CMS_UPDATE_ERROR;
rcs_print_error("CMS: Invalid encoding method(%d)\n",
neutral_encoding_method);
break;
}
}
if (NULL != temp_updater) {
updater = temp_updater;
temp_updater_encoding_method = temp_encoding_method;
}
}
void CMS::restore_normal_updater()
{
updater = normal_updater;
}
void CMS::rewind()
{
if (force_raw) {
return;
}
if (NULL != updater) {
updater->rewind();
}
}
int CMS::encode_header()
{
if (force_raw) {
return 0;
}
if (NULL == updater) {
return -1;
}
CMS_UPDATER_MODE original_mode;
original_mode = updater->get_mode();
format_low_ptr = (char *) &header;
format_high_ptr = ((char *) &header) + sizeof(CMS_HEADER);
updater->set_mode(CMS_ENCODE_HEADER);
updater->rewind();
updater->update(header.was_read);
updater->update(header.write_id);
updater->update(header.in_buffer_size);
if (status == CMS_UPDATE_ERROR || status == CMS_MISC_ERROR) {
return (-1);
}
encoded_header_size = updater->get_encoded_msg_size();
if (min_compatible_version <= 0.0 || min_compatible_version > 3.29) {
if (neutral_encoding_method == CMS_DISPLAY_ASCII_ENCODING) {
encoded_header_size = 16;
}
}
updater->set_mode(original_mode);
return (encoded_header_size);
}
int CMS::decode_header()
{
if (force_raw) {
return 0;
}
if (NULL == updater) {
return -1;
}
CMS_UPDATER_MODE original_mode = updater->get_mode();
format_low_ptr = (char *) &header;
format_high_ptr = ((char *) &header) + sizeof(CMS_HEADER);
updater->set_mode(CMS_DECODE_HEADER);
updater->rewind();
updater->update(header.was_read);
updater->update(header.write_id);
updater->update(header.in_buffer_size);
updater->set_mode(original_mode);
return ((int) (status != CMS_UPDATE_ERROR
&& status != CMS_MISC_ERROR) ? 0 : -1);
}
int CMS::encode_queuing_header()
{
if (force_raw) {
return 0;
}
if (NULL == updater) {
return -1;
}
CMS_UPDATER_MODE original_mode = updater->get_mode();
format_low_ptr = (char *) &queuing_header;
format_high_ptr = ((char *) &queuing_header) + sizeof(CMS_QUEUING_HEADER);
updater->set_mode(CMS_ENCODE_QUEUING_HEADER);
updater->rewind();
updater->update(queuing_header.head);
updater->update(queuing_header.tail);
updater->update(queuing_header.queue_length);
updater->update(queuing_header.end_queue_space);
updater->update(queuing_header.write_id);
if (status == CMS_UPDATE_ERROR || status == CMS_MISC_ERROR) {
return (-1);
}
encoded_queuing_header_size = updater->get_encoded_msg_size();
if (min_compatible_version <= 0.0 || min_compatible_version > 3.29) {
if (neutral_encoding_method == CMS_DISPLAY_ASCII_ENCODING) {
encoded_queuing_header_size = 24;
}
}
updater->set_mode(original_mode);
return (encoded_queuing_header_size);
}
int CMS::decode_queuing_header()
{
if (force_raw) {
return 0;
}
if (NULL == updater) {
return -1;
}
CMS_UPDATER_MODE original_mode = updater->get_mode();
format_low_ptr = (char *) &queuing_header;
format_high_ptr = ((char *) &queuing_header) + sizeof(CMS_QUEUING_HEADER);
updater->set_mode(CMS_DECODE_QUEUING_HEADER);
updater->rewind();
updater->update(queuing_header.head);
updater->update(queuing_header.tail);
updater->update(queuing_header.queue_length);
updater->update(queuing_header.end_queue_space);
updater->update(queuing_header.write_id);
updater->set_mode(original_mode);
return ((int) (status != CMS_UPDATE_ERROR
&& status != CMS_MISC_ERROR) ? 0 : -1);
}
int CMS::get_encoded_msg_size()
{
if (force_raw) {
return 0;
}
if (NULL == updater) {
return (-1);
}
return (header.in_buffer_size = updater->get_encoded_msg_size());
}
int CMS::check_pointer(char *ptr, long bytes)
{
if (force_raw) {
return 0;
}
if (NULL == format_low_ptr || NULL == format_high_ptr
|| pointer_check_disabled) {
return 0;
}
if (ptr < format_low_ptr || ptr > (format_high_ptr - bytes)) {
rcs_print_error("CMS: pointer %p to %ld bytes out of range %p to %p\n",
ptr, bytes, format_low_ptr, format_high_ptr);
rcs_print_error("CMS: Check buffer and message sizes.\n");
status = CMS_UPDATE_ERROR;
return -1;
}
format_size = (long) (ptr - format_low_ptr) + bytes;
return 0;
}
void CMS::set_cms_status(CMS_STATUS new_status)
{
status = new_status;
}
CMS_STATUS CMS::update(bool &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(char &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned char &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(short int &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned short int &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(int &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned int &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(long int &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned long int &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(float &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(double &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(long double &x)
{
if (NULL != updater) {
return (updater->update(x));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(char *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned char *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(short *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned short *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(int *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned int *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(long *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(unsigned long *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(float *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(double *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
CMS_STATUS CMS::update(long double *x, unsigned int len)
{
if (NULL != updater) {
return (updater->update(x, len));
} else {
return (status = CMS_UPDATE_ERROR);
}
}
const char *CMS::status_string(int status_type)
{
switch (status_type) {
case CMS_MISC_ERROR:
return ("CMS_MISC_ERROR: A miscellaneous error occurred.");
case CMS_UPDATE_ERROR:
return ("CMS_UPDATE_ERROR: An error occurred during an update. ");
case CMS_INTERNAL_ACCESS_ERROR:
return
("CMS_INTERNAL_ACCESS_ERROR: An error occurred during an internal access function. ");
case CMS_NO_MASTER_ERROR:
return
("CMS_NO_MASTER_ERROR: An error occurred becouse the master was not started.");
case CMS_CONFIG_ERROR:
return ("CMS_CONFIG_ERROR: There was an error in the configuration.");
case CMS_TIMED_OUT:
return ("CMS_TIMED_OUT: operation timed out.");
case CMS_QUEUE_FULL:
return
("CMS_QUEUE_FULL:= A write failed because queuing was enabled but there was no room to add to the queue. ");
case CMS_CREATE_ERROR:
return
("CMS_CREATE_ERROR: Something could not be created because we were out of memory or another system resource.");
case CMS_PERMISSIONS_ERROR:
return ("CMS_PERMISSIONS_ERROR: Problem with permissions.");
case CMS_STATUS_NOT_SET:
return
("CMS_STATUS_NOT_SET: The status variable has not been set yet.");
case CMS_READ_OLD:
return ("CMS_READ_OLD: Read successful, but data is old. \n");
case CMS_READ_OK:
return ("CMS_READ_OK: Read successful so far.");
case CMS_WRITE_OK:
return ("CMS_WRITE_OK: Write successful so far. ");
case CMS_WRITE_WAS_BLOCKED:
return
("CMS_WRITE_WAS_BLOCKED: Write if read did not succeed, because the buffer had not been read yet.");
case CMS_CLEAR_OK:
return ("CMS_CLEAR_OK: A clear operation was successful.");
case CMS_CLOSED:
return ("CMS_CLOSED: The channel has been closed.");
case CMS_NO_SERVER_ERROR:
return
(" CMS_NO_SERVER_ERROR: The server has not been started or could not be contacted.");
case CMS_RESOURCE_CONFLICT_ERROR:
return
("CMS_RESOURCE_CONFLICT_ERROR: Two or more CMS buffers are trying to use the same resource.");
case CMS_NO_IMPLEMENTATION_ERROR:
return
("CMS_NO_IMPLEMENTATION_ERROR: An operation was attempted which has not yet been implemented for the current platform or protocol.");
case CMS_INSUFFICIENT_SPACE_ERROR:
return
("CMS_INSUFFICIENT_SPACE_ERROR: The size of the buffer was insufficient for the requested operation.");
case CMS_LIBRARY_UNAVAILABLE_ERROR:
return
("CMS_LIBRARY_UNAVAILABLE_ERROR: A DLL or Shared Object library needed for the current protocol could not be found or initialized.");
case CMS_SERVER_SIDE_ERROR:
return ("CMS_SERVER_SIDE_ERROR: The server reported an error.");
case CMS_NO_BLOCKING_SEM_ERROR:
return
("CMS_NO_BLOCKING_SEM_ERROR: A blocking_read operartion was tried but no semaphore for the blocking was configured or available.");
default:
return ("UNKNOWN");
}
}
int CMS::set_subdivision(int _subdiv)
{
if (_subdiv < 0 || _subdiv > total_subdivisions) {
return -1;
}
current_subdivision = _subdiv;
subdiv_data = ((char *) data) + _subdiv * (subdiv_size);
return (0);
}
CMS::CMS(CMS & cms)
{
}
int
CMS::get_msg_count()
{
internal_access_type = CMS_GET_MSG_COUNT_ACCESS;
status = CMS_STATUS_NOT_SET;
blocking_timeout = 0;
main_access(data);
return (header.write_id);
}
char *cms_check_for_host_alias(char *in)
{
if (NULL == in) {
return NULL;
}
if (NULL == cmsHostAliases) {
return NULL;
}
CMS_HOST_ALIAS_ENTRY *entry =
(CMS_HOST_ALIAS_ENTRY *) cmsHostAliases->get_head();
while (NULL != entry) {
if (!strncmp(entry->alias, in, 64)) {
return entry->host;
}
entry = (CMS_HOST_ALIAS_ENTRY *) cmsHostAliases->get_next();
}
return NULL;
}