trick/trick_source/sim_services/MasterSlave/MSSocket.cpp
2021-08-27 19:38:56 -05:00

231 lines
6.3 KiB
C++

#include <iostream>
#include <sstream>
#include <string.h>
#include <unistd.h>
#include "trick/MSSocket.hh"
#include "trick/Master.hh"
#include "trick/tc_proto.h"
#include "trick/exec_proto.h"
#include "trick/command_line_protos.h"
Trick::MSSocket::MSSocket() : tc_dev() {
tc_dev.disabled = TC_COMM_FALSE ;
tc_dev.error_handler = NULL ;
tc_dev.blockio_type = TC_COMM_TIMED_BLOCKIO ;
tc_dev.blockio_type = TC_COMM_BLOCKIO ;
tc_dev.port = 0 ; // tc_multiconnect needs this so that it will send broadcast msg !
// default is a non-zero sync wait limit; helpful when slave reading initial data from master
sync_wait_limit = 5.0 ;
}
int Trick::MSSocket::set_sync_wait_limit(double in_limit) {
/** @par Detailed Design */
sync_wait_limit = in_limit ;
if ( in_limit > 0.0 ) {
/** @li if the incoming limit time is greater than zero, set the socket
to TC_COMM_TIMED_BLOCKIO with the time limit of in_limit */
tc_blockio(&tc_dev, TC_COMM_TIMED_BLOCKIO);
tc_set_blockio_timeout_limit(&tc_dev, sync_wait_limit);
} else {
/** @li if the incoming limit time is less than or equal to zero, set the socket
to TC_COMM_BLOCKIO (infinite block) */
tc_blockio(&tc_dev, TC_COMM_BLOCKIO);
}
return(0) ;
}
std::string Trick::MSSocket::add_sim_args( std::string slave_type ) {
char master_host[80];
std::stringstream temp_stream ;
/** @par Detailed Design */
/** @li create a unique identifier based on the <machine>_<current pid>. */
gethostname(master_host, (size_t) 80);
temp_stream << master_host << "_" << getpid() ;
sync_port_tag = temp_stream.str() ;
/** @li return the unique identifier with the "-p" argument that is
specific to master/slave communications. */
return("-p " + temp_stream.str()) ;
}
int Trick::MSSocket::process_sim_args() {
int ii ;
int argc ;
char ** argv ;
argc = command_line_args_get_argc() ;
argv = command_line_args_get_argv() ;
/** @par Detailed Design */
/** @li search for the "-p" argument. If found get the master identifier as the next argument */
for (ii = 1; ii < argc; ii++) {
if (!strncmp("-p", argv[ii], (size_t) 2)) {
if (argc >= ii + 1) {
sync_port_tag = argv[ii+1] ;
return(1) ;
}
}
}
return(0) ;
}
int Trick::MSSocket::accept() {
int ret ;
/** @par Detailed Design */
/** @li Call tc_multiconnect to connect this master. Use "master" as the my_tag argument */
ret = tc_multiconnect(&tc_dev, (char *)"master", (char *)sync_port_tag.c_str(), NULL);
return(ret) ;
}
int Trick::MSSocket::connect() {
int ret ;
/** @par Detailed Design */
/** @li Call tc_multiconnect to connect this slave. Use "slave" as the my_tag argument */
ret = tc_multiconnect(&tc_dev, (char *)"slave", (char *)sync_port_tag.c_str(), NULL);
return(ret) ;
}
int Trick::MSSocket::disconnect() {
int ret;
/** @par Detailed Design */
/** @li Call tc_disconnect to disconnect this device. */
ret = tc_disconnect( &tc_dev );
tc_dev.disabled = TC_COMM_FALSE ;
tc_dev.error_handler = NULL ;
tc_dev.blockio_type = TC_COMM_TIMED_BLOCKIO ;
tc_dev.blockio_type = TC_COMM_BLOCKIO ;
tc_dev.port = 0 ;
return(ret);
}
long long Trick::MSSocket::read_time() {
long long in_time = 0 ;
int ret ;
/** @par Detailed Design */
/** @li Call tc_read to get the time */
ret = tc_read(&tc_dev , (char *)&in_time, sizeof(long long));
/** @li If the read call returned the correct number of bytes return the read in time */
if ( ret == sizeof(long long)) {
return(in_time) ;
}
/** @li Else return the special "error" time */
return (MS_ERROR_TIME) ;
}
MS_SIM_COMMAND Trick::MSSocket::read_command() {
MS_SIM_COMMAND command ;
int ret ;
/** @par Detailed Design */
/** @li Call tc_read to get the command */
ret = tc_read(&tc_dev , (char *)&command, sizeof(MS_SIM_COMMAND));
/** @li If the read call returned the correct number of bytes return the read in command */
if ( ret == sizeof(MS_SIM_COMMAND)) {
return(command) ;
}
/** @li Else return ErrorCmd */
return(MS_ErrorCmd) ;
}
int Trick::MSSocket::read_port() {
int in_port = 0 ;
int ret ;
/** @par Detailed Design */
/** @li Call tc_read to get the port number */
ret = tc_read(&tc_dev , (char *)&in_port, sizeof(int));
/** @li If the read call returned the correct number of bytes return the read in port */
if ( ret == sizeof(int)) {
return(in_port) ;
}
/** @li Else return the special "error" port */
return (MS_ERROR_PORT) ;
}
char Trick::MSSocket::read_name(char * read_data, size_t size) {
int ret ;
/** @par Detailed Design */
/** @li Call tc_read to get the name (character array) */
ret = tc_read(&tc_dev , (char *)read_data, (int)size);
/** @li If the read call returned the correct number of bytes return 1st character read */
if ( ret == int(size)) {
return(read_data[0]) ;
}
/** @li Else return the special "error" name character */
return (MS_ERROR_NAME) ;
}
int Trick::MSSocket::write_time(long long in_time) {
int ret ;
/** @par Detailed Design */
/** @li Call tc_write to write the time */
ret = tc_write(&tc_dev , (char *)&in_time, sizeof(long long));
/** @li Return the number of bytes written */
return(ret) ;
}
int Trick::MSSocket::write_command(MS_SIM_COMMAND command) {
int ret ;
/** @par Detailed Design */
/** @li Call tc_write to write the command */
ret = tc_write(&tc_dev , (char *)&command, sizeof(unsigned int));
/** @li Return the number of bytes written */
return(ret) ;
}
int Trick::MSSocket::write_port(int in_port) {
int ret ;
/** @par Detailed Design */
/** @li Call tc_write to write the port number */
ret = tc_write(&tc_dev , (char *)&in_port, sizeof(int));
/** @li Return the number of bytes written */
return(ret) ;
}
int Trick::MSSocket::write_name(char * in_data, size_t size) {
/** @par Detailed Design */
/** @li Call tc_write to write the name (character array) */
tc_write(&tc_dev , (char *)in_data, size);
/** @li Return the number of bytes written */
return(size) ;
}