trick/trick_source/sim_services/VariableServer/VariableServerThread_write_data.cpp
2017-06-26 17:50:54 -05:00

281 lines
10 KiB
C++

/*
PURPOSE: (Allows clients to get and set Trick parameters)
PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--)))
*/
#include <iostream>
#include <pthread.h>
#include "trick/VariableServer.hh"
#include "trick/variable_server_message_types.h"
#include "trick/parameter_types.h"
#include "trick/bitfield_proto.h"
#include "trick/trick_byteswap.h"
#include "trick/tc_proto.h"
#include "trick/message_proto.h"
#include "trick/message_type.h"
extern "C" {
void *trick_bswap_buffer(void *out, void *in, ATTRIBUTES * attr, int tofrom) ;
}
#define MAX_MSG_LEN 8192
int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int PacketNum ) {
int i;
int ret ;
int HeaderSize, MessageSize;
int NumVariablesProcessed;
unsigned int msg_type , offset, len ;
unsigned int size ;
unsigned int swap_int ;
char * address = 0 ;
char* param_name;
//remove warning for unused PacketNum... to be deleted.
(void)PacketNum ;
/* start the offset 4 bytes into the message, we'll subtract the sizeof offset at the end */
offset = sizeof(msg_type) + sizeof(offset) ;
/* if we are here the msg_type is good, so send a 0, swapped or not 0 is still 0 */
msg_type = VS_VAR_LIST ;
memcpy(buf1, &msg_type , sizeof(msg_type)) ;
HeaderSize = sizeof(msg_type);
offset += sizeof(unsigned int) ;
HeaderSize += sizeof(unsigned int);
for (i = Start; i < (int)vars.size() ; i++) {
// data to send was copied to buffer in copy_sim_data
address = (char *)vars[i]->buffer_out;
size = vars[i]->size ;
param_name = vars[i]->ref->reference;
len = strlen(param_name) ;
// when var_binary_nonames, do not put the variable names into the message to be sent
if (binary_data_nonames) {
MessageSize = sizeof(int) + sizeof(size) + size ;
} else {
MessageSize = sizeof(len) + len + sizeof(int) + sizeof(size) + size ;
}
/* make sure this message will fit in a packet by itself */
if ( (HeaderSize + MessageSize) > MAX_MSG_LEN ) {
message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small (need %d) for symbol %s, SKIPPING IT.\n",
&connection, MAX_MSG_LEN,
(int)(HeaderSize + MessageSize),
vars[i]->ref->reference );
continue;
}
if ( (offset + MessageSize) < MAX_MSG_LEN ) {
if (byteswap) {
if (!binary_data_nonames) {
swap_int = trick_byteswap_int((int)len) ;
memcpy(&buf1[offset] , &swap_int , sizeof(len)) ;
offset += sizeof(len) ;
memcpy(&buf1[offset] , param_name , (size_t)len) ;
offset += len ;
}
swap_int = trick_byteswap_int(vars[i]->ref->attr->type) ;
memcpy(&buf1[offset] , &swap_int , sizeof(int)) ;
offset += sizeof(int) ;
swap_int = trick_byteswap_int((int)size) ;
memcpy(&buf1[offset] , &swap_int , sizeof(size)) ;
offset += sizeof(size) ;
/* TODO: There is a bug here, this call will want to swap the entire buffer, we may not have the whole buffer */
trick_bswap_buffer(&buf1[offset], address, vars[i]->ref->attr, 1);
offset += size ;
}
else {
int temp_i ;
unsigned int temp_ui ;
if (!binary_data_nonames) {
memcpy(&buf1[offset] , &len , sizeof(len)) ;
offset += sizeof(len) ;
memcpy(&buf1[offset] , param_name , (size_t)len) ;
offset += len ;
}
memcpy(&buf1[offset] , &vars[i]->ref->attr->type , sizeof(int)) ;
offset += sizeof(int) ;
memcpy(&buf1[offset] , &size , sizeof(size)) ;
offset += sizeof(size) ;
switch ( vars[i]->ref->attr->type ) {
case TRICK_BITFIELD:
temp_i = GET_BITFIELD(address , vars[i]->ref->attr->size ,
vars[i]->ref->attr->index[0].start, vars[i]->ref->attr->index[0].size) ;
memcpy(&buf1[offset] , &temp_i , (size_t)size) ;
break ;
case TRICK_UNSIGNED_BITFIELD:
temp_ui = GET_UNSIGNED_BITFIELD(address , vars[i]->ref->attr->size ,
vars[i]->ref->attr->index[0].start, vars[i]->ref->attr->index[0].size) ;
memcpy(&buf1[offset] , &temp_ui , (size_t)size) ;
break ;
case TRICK_NUMBER_OF_TYPES:
// TRICK_NUMBER_OF_TYPES is an error case
temp_i = 0 ;
memcpy(&buf1[offset] , &temp_i , (size_t)size) ;
break ;
default:
memcpy(&buf1[offset] , address , (size_t)size) ;
break ;
}
offset += size ;
}
}
else {
/* indicate that we're over the maximum size */
if (debug >= 2) {
message_publish(MSG_DEBUG, "%p tag=<%s> var_server buffer[%d] too small (need %d), sending multiple binary packets.\n",
&connection, connection.client_tag, MAX_MSG_LEN,
(int)(offset + MessageSize) );
}
break ;
}
}
/* adjust the header with the correct information reflecting what has been accomplished */
NumVariablesProcessed = i - Start;
offset -= sizeof(offset) ;
if (byteswap) {
swap_int = trick_byteswap_int((int)offset) ;
memcpy(buf1 + sizeof(msg_type) , &swap_int , sizeof(offset)) ;
swap_int = trick_byteswap_int( NumVariablesProcessed ) ;
memcpy( buf1 + sizeof(msg_type) + sizeof(offset), &swap_int , sizeof(swap_int)) ;
}
else {
memcpy(buf1 + sizeof(msg_type) , &offset , sizeof(offset)) ;
memcpy( buf1 + sizeof(msg_type) + sizeof(offset), &NumVariablesProcessed , sizeof( NumVariablesProcessed )) ;
}
if (debug >= 2) {
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %u binary bytes containing %d variables.\n", &connection,
connection.client_tag, (unsigned int)(offset + sizeof(offset)), NumVariablesProcessed);
}
len = offset + sizeof(msg_type) ;
ret = tc_write(&connection, (char *) buf1, len);
if ( ret != (int)len ) {
return(-1) ;
}
/* return the index to the next symbol to send or V->num_vars if all done */
return i;
}
int Trick::VariableServerThread::write_data() {
int ret;
unsigned int i ;
char buf1[ MAX_MSG_LEN ];
int len ;
// do not send anything when there are no variables!
if ( vars.size() == 0 or packets_copied == 0 ) {
return(0);
}
/* Acquire sole access to vars[ii]->buffer_in. */
if ( var_data_staged and pthread_mutex_trylock(&copy_mutex) == 0 ) {
unsigned int ii;
void * temp_p;
// Swap buffer_in and buffer_out for each vars[ii].
for ( ii = 0 ; ii < vars.size() ; ii++ ) {
temp_p = vars[ii]->buffer_in;
vars[ii]->buffer_in = vars[ii]->buffer_out;
vars[ii]->buffer_out = temp_p;
}
var_data_staged = false;
/* Relinquish sole access to vars[ii]->buffer_in. */
pthread_mutex_unlock(&copy_mutex) ;
if (binary_data) {
int Index = 0;
int PacketNumber = 0;
do {
ret = write_binary_data( Index, buf1, PacketNumber );
if ( ret >= 0 ) {
Index = ret ;
} else {
return(-1) ;
}
PacketNumber++;
} while( Index < (int)vars.size() );
} else { /* ascii mode */
char val[MAX_MSG_LEN];
sprintf(buf1, "0\t") ;
for (i = 0; i < vars.size(); i++) {
ret = vs_format_ascii( vars[i] , val);
if (ret < 0) {
message_publish(MSG_WARNING, "%p Variable Server string buffer[%d] too small for symbol %s, TRUNCATED IT.\n",
&connection, MAX_MSG_LEN, vars[i]->ref->reference );
}
/* make sure this message will fit in a packet by itself */
if( strlen( val ) + 2 > MAX_MSG_LEN ) {
message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small for symbol %s, TRUNCATED IT.\n",
&connection, MAX_MSG_LEN, vars[i]->ref->reference );
val[MAX_MSG_LEN - 1] = '\0';
}
len = strlen(buf1) ;
/* make sure there is space for the next tab or next newline and null */
if( len + strlen( val ) + 2 > MAX_MSG_LEN ) {
if (debug >= 2) {
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n",
&connection, connection.client_tag, (int)strlen(buf1), buf1) ;
}
ret = tc_write(&connection, (char *) buf1, len);
if ( ret != len ) {
return(-1) ;
}
buf1[0] = '\0';
}
strcat(buf1, val);
strcat(buf1, "\t");
}
len = strlen(buf1) ;
if ( len > 0 ) {
buf1[ strlen(buf1) - 1 ] = '\n';
if (debug >= 2) {
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n",
&connection, connection.client_tag, (int)strlen(buf1), buf1) ;
}
ret = tc_write(&connection, (char *) buf1, (int)strlen(buf1));
if ( ret != (int)strlen(buf1) ) {
return(-1) ;
}
}
}
}
return (0);
}