/* PURPOSE: (Allows clients to get and set Trick parameters) PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--))) */ #include #include #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(©_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(©_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); }