/*
@details
-# Loop until the connection is broken or timed_out
 -# Call select to wait up to 15 seconds for a message.
 -# If a message is found, read it into the incoming_msg buffer
 -# Call parse_request on the incoming_msg buffer
-# Disconnect the socket connection
*/
void * Trick::JSONVariableServerThread::thread_body() {

    int nbytes = -1 ;
    socklen_t sock_size = sizeof(connection.remoteServAddr) ;
    fd_set rfds;
    struct timeval timeout_time = { 15, 0 };
    bool timed_out = false ;

    while (! timed_out and nbytes != 0 ) {
        FD_ZERO(&rfds);
        FD_SET(connection.socket, &rfds);
        timeout_time.tv_sec = 15 ;
        select(connection.socket + 1, &rfds, NULL, NULL, &timeout_time);

        if ( FD_ISSET(connection.socket, &rfds)) {
            nbytes = recvfrom( connection.socket, incoming_msg, MAX_CMD_LEN, 0 ,
                     (struct sockaddr *)&connection.remoteServAddr, &sock_size ) ;
            //std::cout << "nbytes = " << nbytes << std::endl ;
            if (nbytes != 0 ) {
                //std::cout << incoming_msg << std::endl ;
                parse_request() ;
            }
        } else {
            timed_out = true ;
        }
    }
    tc_disconnect(&connection) ;
    //std::cout << "closed variable server connection" << std::endl ;

    return NULL ;
}
Beispiel #2
0
/*
@details
-# If the user specified an address and port
 -# disconnect the current listen port
 -# initialize listen port to new address and port
-# else print message of current port number of listen device
*/
int Trick::JSONVariableServer::restart() {

    int ret ;

    if ( user_port_requested ) {
        char hname[80];
        static struct sockaddr_in s_in;
        gethostname(hname, (size_t) 80);
        // Test to see if the restart address is on this machine.  If it is not, it's not an error, clear source address
        if ( strcmp( source_address.c_str(), hname )) {
            if (! inet_pton(AF_INET, source_address.c_str(), (struct in_addr *)&s_in.sin_addr.s_addr) ) {
                //printf("clearing source_address\n") ;
                source_address.clear() ;
            }
        }

        printf("JSON variable server restart user_port requested set %d\n", port) ;

        tc_disconnect(&listen_dev) ;
        ret = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, source_address.c_str(), port) ;
        if (ret != TC_SUCCESS) {
            message_publish(MSG_ERROR, "ERROR: Could not establish listen port %d for JSON Variable Server. Aborting.\n", port);
            return (-1);
        }
    } else {
        struct sockaddr_in s_in;
        int s_in_size =  sizeof(s_in) ;
        getsockname( listen_dev.socket , (struct sockaddr *)&s_in, (socklen_t *)&s_in_size) ;
        printf("restart JSON variable server message port = %d\n" , ntohs(s_in.sin_port)) ;
        port = listen_dev.port = ntohs(s_in.sin_port);
    }

    return 0 ;
}
Beispiel #3
0
/** @par Detailed Design: */
int Trick::MonteCarlo::shutdown() {
    /** <ul><li> If this is a slave, run the shutdown jobs. */
    if (enabled && is_slave()) {
        connection_device.port = master_port;
        if (tc_connect(&connection_device) == TC_SUCCESS) {
            int exit_status = MonteRun::COMPLETE;
            if (verbosity >= ALL) {
                message_publish(MSG_INFO, "Monte [%s:%d] Sending run exit status to master: %d\n",
                                machine_name.c_str(), slave_id, exit_status) ;
            }
            int id = htonl(slave_id);
            tc_write(&connection_device, (char*)&id, (int)sizeof(id));
            exit_status = htonl(exit_status);
            tc_write(&connection_device, (char*)&exit_status, (int)sizeof(exit_status));
            run_queue(&slave_post_queue, "in slave_post queue");
            tc_disconnect(&connection_device);
        } else {
            if (verbosity >= ERROR)
                message_publish(
                  MSG_ERROR,
                  "Monte [%s:%d] Failed to connect to master.\n",
                  machine_name.c_str(), slave_id);
        }
    }
    return 0;
}
Beispiel #4
0
// MEMBER FUNCTION
void Trick::MessageTCDevice::update( unsigned int level , std::string header , std::string message ) {

    std::vector < TCDevice *>::iterator it ;
    int nbytes ;
    int length ;
    std::string color_code ;

    /** @par Design Details: */

    switch (level) {
        case MSG_NORMAL :
            color_code = "\033[00m" ; // normal
            break ;
        case MSG_INFO :
            color_code = "\033[32m" ; // green
            break ;
        case MSG_WARNING :
            color_code = "\033[33m" ; // yellow
            break ;
        case MSG_ERROR :
            color_code = "\033[31m" ; // red
            break ;
        case MSG_DEBUG :
            color_code = "\033[36m" ; // cyan
            break ;
        default :
            color_code = "\033[00m" ; // normal
            break ;
    }

    /** @li If this subscriber is not enabled, do nothing. Otherwise, it gets the update. */
    if ( enabled && level < 100 ) {

    	 /** @li The message is composed as message header + message text */
        if ( color ) {
            snprintf( combined_message , 20480 , "%s%s%s\033[00m" , header.c_str() , color_code.c_str() , message.c_str()) ;
        } else {
            snprintf( combined_message , 20480 , "%s%s" , header.c_str() , message.c_str()) ;
        }
        length = (int)strlen(combined_message) ;

        /** @li The message is broadcast to all socket connection this subscriber has. */
        it = connections.begin() ;
        while ( it != connections.end() ) {
            nbytes = tc_write( *it, combined_message, length) ;

            /** @li All those connections that can not receive the message get disconnected.  */
            if ( nbytes != length ) {
                tc_disconnect(*it) ;
                it = connections.erase(it) ;
            } else {
                it++ ;
            }
        }
    }

    return ;
}
/* Interupt signal handler. */
void sigint_hndlr( int sig )
{
 
   fprintf(stderr,"client: disconnected...\n" );

   if (tc_isValid(device))
      tc_disconnect(device);
 
   /* Exit the application. */
   exit( 1 );
}
Beispiel #6
0
/*
@details
-# if enabled
 -# move listen device to user specified address and port.
 -# create listening thread
*/
int Trick::JSONVariableServer::init() {
    int ret = 0 ;
    if ( enabled ) {
        ret = check_and_move_listen_device() ;
        if ( ret == 0 ) {
            create_thread() ;
        }
    } else {
        tc_disconnect(&listen_dev) ;
    }
    return ret ;
}
Beispiel #7
0
/*
@details
-# If the source address or port number does not match the current listen device
 -# disconnect current listen device
 -# initialize listen device with new source address and port
*/
int Trick::JSONVariableServer::check_and_move_listen_device() {
    int ret ;

    if ( source_address.compare(listen_dev.hostname) or port != listen_dev.port ) {
        /* The user has requested a different source address or port in the input file */
        tc_disconnect(&listen_dev) ;
        ret = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, source_address.c_str(), port) ;
        if (ret != TC_SUCCESS) {
            message_publish(MSG_ERROR, "ERROR: Could not establish variable server source_address %s: port %d. Aborting.\n",
             source_address.c_str(), port);
            return -1 ;
        }
    }
    return 0 ;
}
void Trick::MonteCarlo::dispatch_run_to_slave(MonteRun *in_run, MonteSlave *in_slave) {
    if (in_slave && in_run) {
        current_run = in_run->id;
        if (prepare_run(in_run) == -1) {
            return;
        }
        in_slave->state = MonteSlave::RUNNING;
        connection_device.hostname = (char*)in_slave->machine_name.c_str();
        connection_device.port = in_slave->port;
        if (tc_connect(&connection_device) == TC_SUCCESS) {
            std::stringstream buffer_stream;
            buffer_stream << run_directory << "/RUN_" << std::setw(5) << std::setfill('0') << in_run->id;
            std::string buffer = "";
            for (std::vector<std::string>::size_type j = 0; j < in_run->variables.size(); ++j) {
                buffer += in_run->variables[j] + "\n";
            }
            buffer += std::string("trick.set_output_dir(\"") + buffer_stream.str() + std::string("\");\n");
            buffer_stream.str("");
            buffer_stream << in_run->id ;
            buffer += std::string("trick.mc_set_current_run(") + buffer_stream.str() + std::string(");\n");

            if (verbosity >= INFORMATIONAL) {
                message_publish(MSG_INFO, "Monte [Master] Dispatching run %d to %s:%d.\n",
		     in_run->id, in_slave->machine_name.c_str(), in_slave->id) ;
            }
            int command = htonl(MonteSlave::PROCESS_RUN);
            tc_write(&connection_device, (char *)&command, (int)sizeof(command));
            int num_bytes = htonl(buffer.length());
            tc_write(&connection_device, (char*)&num_bytes, (int)sizeof(num_bytes));
            tc_write(&connection_device, (char*)buffer.c_str(), (int)buffer.length());
            tc_disconnect(&connection_device);

            ++in_slave->num_dispatches;
            in_slave->current_run = in_run;

            struct timeval time_val;
            gettimeofday(&time_val, NULL);
            in_run->start_time = time_val.tv_sec + (double)time_val.tv_usec / 1000000;
            ++in_run->num_tries;
        } else {
            in_slave->state = Trick::MonteSlave::DISCONNECTED;
            if (verbosity >= ERROR) {
                message_publish(MSG_ERROR, "Monte [Master] Lost connection to %s:%d while dispatching run.\n",
                                in_slave->machine_name.c_str(), in_slave->id) ;
            }
        }
    }
}
Beispiel #9
0
/* Interupt signal handler. */
void sigint_hndlr( int sig )
{
   int i ;
 
   if (pthread_equal(pthread_self() , thread_id)) {
      fprintf(stderr,"Disconnecting devices...\n" );

      for( i = 0 ; i < num_devices ; i++) {
         if (device[i] != (TCDevice*)NULL) {
            tc_disconnect(device[i]);
         }
      }

   }

   /* Exit the application. */
   exit(0);
    
}
Beispiel #10
0
/*
@details
-# If the user specified an address and port
 -# disconnect the current listen port
 -# initialize listen port to new address and port
-# else print message of current port number of listen device
*/
int Trick::JSONVariableServer::restart() {

    int ret ;

    if ( user_port_requested ) {
        printf("user_port_requested set %d", port) ;
        tc_disconnect(&listen_dev) ;
        ret = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, source_address.c_str(), port) ;
        if (ret != TC_SUCCESS) {
            message_publish(MSG_ERROR, "ERROR: Could not establish listen port %d for Variable Server. Aborting.\n", port);
            return (-1);
        }
    } else {
        struct sockaddr_in s_in;
        int s_in_size =  sizeof(s_in) ;
        getsockname( listen_dev.socket , (struct sockaddr *)&s_in, (socklen_t *)&s_in_size) ;
        printf("restart JSON variable server message port = %d\n" , ntohs(s_in.sin_port)) ;
        port = listen_dev.port = ntohs(s_in.sin_port);
    }

    return 0 ;
}
Beispiel #11
0
int VSTest::shutdown() {

	tc_disconnect(&bob);

	return(0);
}
Beispiel #12
0
int tc_multiconnect(TCDevice * dev_ptr, char *my_tag, char *other_tag, TrickErrorHndlr * not_used)
{
    int status;
    int num_try = 0;
    TCDevice *server_device;
    char name[80];

    int size;
    char *cptr;

    /* Multicast vars */
    struct sockaddr_in addr;
    int fd, nbytes;
    struct ip_mreq mreq;
    BC_INFO bc_info, *bc_copy;
    SEND_ME read_me;
    int i_am_client;
    int value;
    int num_attempts = 10;
    int found_conn;
#ifdef __WIN32__
    HANDLE thread;
    DWORD threadId;
    int curr_pid;
    WSADATA wsaData;
#else
    pthread_t thread;
    pid_t curr_pid;
#endif

    (void) not_used;                   /* unused */

    if (!dev_ptr) {
        TrickErrorHndlr *temp_error_hndlr = NULL;
        trick_error_report(temp_error_hndlr, TRICK_ERROR_ALERT, __FILE__, __LINE__, "Trying to connect a NULL device");
        return (-1);
    }

    if (dev_ptr->disabled != 0) {
        trick_error_report(dev_ptr->error_handler,
                           TRICK_ERROR_ALERT, __FILE__, __LINE__,
                           "%s| cannot connect disabled device %s\n", my_tag, other_tag);
        return (TC_SUCCESS);
    }

    trick_error_report(dev_ptr->error_handler,
                       TRICK_ERROR_ADVISORY, __FILE__, __LINE__,
                       "%s| multiconnecting to %s\n", my_tag, other_tag);

    /* Create a TrickComm listen device Determine port for listen device */
    server_device = (TCDevice *) malloc(sizeof(TCDevice));
    memset((void *) server_device, '\0', sizeof(TCDevice));
    server_device->error_handler = dev_ptr->error_handler;

    server_device->port = 0;
    if ((status = tc_init(server_device)) != TC_SUCCESS) {
        trick_error_report(server_device->error_handler,
                           TRICK_ERROR_ALERT, __FILE__, __LINE__, "could not open listen device!\n");
        return (status);
    }

    /* 
     * Initialize Broadcast Info Structure
     */
    gethostname(name, (size_t) 80);

    strcpy(bc_info.send_me.addr, name);
    bc_info.send_me.port = server_device->port;
    bc_info.send_me.pid = curr_pid = getpid();
    bc_info.send_me.conn_initiated = 0;

    if (my_tag != (char *) NULL) {
        strncpy(bc_info.send_me.my_tag, my_tag, (size_t) TC_TAG_LENGTH);
        bc_info.send_me.my_tag[TC_TAG_LENGTH - 1] = '\0';
    } else {
        bc_info.send_me.my_tag[0] = '\0';
    }

    if (other_tag != (char *) NULL) {
        strncpy(bc_info.send_me.other_tag, other_tag, (size_t) TC_TAG_LENGTH);
        bc_info.send_me.other_tag[TC_TAG_LENGTH - 1] = '\0';
    } else {
        bc_info.send_me.other_tag[0] = '\0';
    }

    bc_info.device = dev_ptr;

#ifdef __WIN32__
    /* Initiate use of the Windows socket DLL */
    if (WSAStartup(0x202, &wsaData) == SOCKET_ERROR) {
        perror("tc_multiconnect: WSAStartup");
        WSACleanup();
        return (TC_COULD_NOT_ACCEPT);
    }
#endif

    /* Create the broadcast socket */
    if ((bc_info.fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("tc_multiconnect socket");
    }

    /* Set up destination address */
    memset(&bc_info.addr, 0, sizeof(bc_info.addr));
    bc_info.addr.sin_family = AF_INET;
    bc_info.addr.sin_addr.s_addr = inet_addr(TC_MULT_GROUP);
    bc_info.addr.sin_port = htons(TC_MULT_PORT);

    /* 
     * Create socket to listen for connections 
     */
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("tc_multiconnect socket");
    }

    value = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &value, (socklen_t) sizeof(value)) < 0) {
        perror("setsockopt: reuseaddr");
    }
#ifdef SO_REUSEPORT
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &value, sizeof(value)) < 0) {
        perror("setsockopt: reuseport");
    }
#endif

    /* Set up destination address */
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(TC_MULT_PORT);

    /* Bind to receive address */
    if (bind(fd, (struct sockaddr *) &addr, (socklen_t) sizeof(addr)) < 0) {
        perror("tc_multiconnect bind");
    }

    /* Use setsockopt() to request that the kernel join a multicast group */
    mreq.imr_multiaddr.s_addr = inet_addr(TC_MULT_GROUP);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    size = sizeof(mreq);
    cptr = (char *) &mreq;
    if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, cptr, (socklen_t) size) < 0) {
#ifdef __WIN32__
        TCHAR szError[100];     // Error message string

        wsprintf(szError, TEXT("setsockopt failed! Error: %d"), WSAGetLastError());
        MessageBox(NULL, szError, TEXT("Error"), MB_OK);
#endif
        perror("setsockopt: ip_add_membership");
    }

    /* Create thread that will continually broadcast connection info on multicast port for prospective clients. */
    /* make a copy of info to broadcast */
    bc_copy = (BC_INFO *) malloc(sizeof(BC_INFO));
    memcpy(bc_copy, &bc_info, sizeof(BC_INFO));
#ifdef __WIN32__
    thread = CreateThread(NULL, 0, tc_broadcast_conninfo, &bc_copy, 0, &threadId);
#else
    pthread_create(&thread, NULL, tc_broadcast_conninfo, bc_copy);
#endif

    /* Wait for other peers wanting to connect to me */
    i_am_client = 0;
    found_conn = 0;
    while (found_conn == 0) {

        do {
            nbytes = recvfrom(fd, &read_me, sizeof(SEND_ME), 0, NULL, NULL);
        } while ((nbytes == -1) && (tc_errno == TRICKCOMM_EINTR));

        if (nbytes == sizeof(read_me)) {

            /* 
             * Read information from peer
             */
            read_me.port = ntohl((uint32_t) read_me.port);
            read_me.pid = ntohl((uint32_t) read_me.pid);
            read_me.conn_initiated = ntohl((uint32_t) read_me.conn_initiated);

            /* May I connect with this peer? Rules: Don't connect to myself! Don't connect to someone with same tag as 
               myself Do connect to someone with same "other tag" */
            if (curr_pid != read_me.pid &&
                strcmp(bc_info.send_me.my_tag, read_me.my_tag) &&
                !strcmp(bc_info.send_me.other_tag, read_me.other_tag)) {

                /* Decide who will function as client Whoever has smaller pid will be the client If same pid, decide by 
                   a string compare */
                if (curr_pid < read_me.pid) {
                    i_am_client = 1;
                } else if (curr_pid == read_me.pid) {
                    i_am_client = (strcmp(name, read_me.addr) > 0) ? 1 : 0;
                }

                /* 
                 * Client Peer initiates the connection 
                 */
                if (i_am_client == 1) {

                    /* Save off addr and port to connect */
                    size = strlen(read_me.addr) + 1;
                    dev_ptr->hostname = (char *) malloc((size_t) size);
                    strcpy(dev_ptr->hostname, read_me.addr);
                    dev_ptr->port = read_me.port;

                    read_me.conn_initiated = 1;
                    read_me.port = htonl((uint32_t) read_me.port);
                    read_me.pid = htonl((uint32_t) read_me.pid);
                    read_me.conn_initiated = htonl((uint32_t) read_me.conn_initiated);
                    sendto(bc_info.fd, (char *) &read_me, sizeof(SEND_ME), 0,
                           (struct sockaddr *) &bc_info.addr, (socklen_t) sizeof(bc_info.addr));
                    found_conn = 1;
                }

            } else if (curr_pid == read_me.pid &&
                       !strcmp(bc_info.send_me.addr, read_me.addr) &&
                       !strcmp(bc_info.send_me.my_tag, read_me.my_tag) &&
                       !strcmp(bc_info.send_me.other_tag, read_me.other_tag) && read_me.conn_initiated == 1) {

                found_conn = 1;
            }
        }
    }

    if (other_tag != (char *) NULL) {
        strncpy(dev_ptr->client_tag, other_tag, (size_t) TC_TAG_LENGTH);
        dev_ptr->client_tag[TC_TAG_LENGTH - 1] = '\0';
    }

    if (i_am_client == 1) {

        /* Client connects */

        /* Disconnect unneeded listen device */
        tc_disconnect(server_device);
        free((void *) server_device);

        tc_set_blockio_timeout_limit(dev_ptr, MAX_BLOCKIO_TIMEOUT_LIMIT);
        status = 1;
        while ((status != TC_SUCCESS) && (num_try < num_attempts)) {
            status = tc_connect(dev_ptr);
#if __WIN32__
            Sleep(200);
#else
            usleep(200000);
#endif
            num_try++;
        }
    } else {

        /* 
         * Server accepts
         */
        status = 1;
        while (status != TC_SUCCESS && (num_try < num_attempts)) {
            if (tc_listen(server_device)) {
                status = tc_accept(server_device, dev_ptr);
                if (dev_ptr != NULL) {
                    tc_set_blockio_timeout_limit(dev_ptr, MAX_BLOCKIO_TIMEOUT_LIMIT);
                }
            }
            num_try++;
#if __WIN32__
            Sleep(200);
#else
            usleep(200000);
#endif
        }
        tc_disconnect(server_device);
        free((void *) server_device);
    }

    if (status != TC_SUCCESS) {
        trick_error_report(server_device->error_handler,
                           TRICK_ERROR_ALERT, __FILE__, __LINE__, "could not open connection!\n");
        return (status);
    }

    /* Shutdown the broadcast */
    shutdown(bc_info.fd, 2);

    /* Return the pointer to the TCDevice as the tc_id. */
    return (TC_SUCCESS);
}
int main( int argc, char *argv[] ) {

   int       ctr;
   int       tc_rc;
   BUFFER    buffer ;
   char      other_tag[256] = "test_tag" ;
   TrickErrorHndlr   err_hndlr;
   int       *me ;
   int       status ;

   if (argc >= 2) {
      if (!strcmp(argv[1] , "-h")) {
         fprintf(stderr,"usage: %s [tag_name]\n",argv[0]);  
         exit(0) ;
      }
      else {
         strcpy(other_tag , argv[1]) ;
      }
   }

#ifndef __WIN32__
   /* Register the interupt signal handler. */
   {
     struct sigaction sigact; /* sigaction() sys call parm */
     memset ( &sigact , 0 , sizeof(struct sigaction)) ;
     sigact.sa_flags = 0;
     sigact.sa_handler = (void(*)())sigint_hndlr;
     if ( sigaction( SIGINT, &sigact, NULL ) < 0 )
        perror("sigaction() failed for SIGINT");
#if (__sun)
     sigact.sa_handler = (void(*)())stupid;
     if ( sigaction( SIGALRM, &sigact, NULL ) < 0 )
        perror("sigaction() failed for SIGALRM");
#endif

   }
#endif

   memset((void *)&err_hndlr,'\0',sizeof(TrickErrorHndlr));
   trick_error_init(&err_hndlr,
                    (TrickErrorFuncPtr)NULL,
                    (TrickErrorDataPtr)NULL,
                    TRICK_ERROR_TRIVIAL);

   /* It is possible for multiple multiconnects to try and 
      initiate simultaneously causing some of the connects 
      to fail.  This happens if all of the clients have the 
      same tag and are connecting to the same server.  This is
      the V.R. scenario.  Continue trying to connect 
      until successful.
    */
   do {
      device = malloc(sizeof(TCDevice)) ;
      memset((void *)device,'\0',sizeof(TCDevice));
      status = tc_multiconnect(device , "client" , other_tag , &err_hndlr);
      if (status != TC_SUCCESS) {
         fprintf(stderr,"Error from tc_multiconnect... trying again\n");
      }
   } while (status != TC_SUCCESS) ;

   ctr = 1;
   me = ((int *)&buffer.f1 +1) ;
   while( 1 ) {
      while ( (tc_isValid(device)) && (!tc_pending(device)) )
#if __WIN32__
         Sleep(1);
#else
         usleep(1000);
#endif
      if (tc_isValid(device)) {
         tc_rc = tc_read(device,(char *)&buffer,sizeof(buffer));
         if (tc_rc != 0) {
            fprintf(stderr,"client: read msg %d from server:\n",ctr++);
            fprintf(stderr,"        i1 = %08x, s1 = %d, c1 = %d, f1 = %f, d1 = %f\n",
             buffer.i1, buffer.s1, buffer.c1, buffer.f1, buffer.d1 ) ;
            fprintf(stderr,"        b1 = %d , b2 = %d, b3 = %d, b4 = %d, b5 = %d\n",
             buffer.b1, buffer.b2, buffer.b3, buffer.b4, buffer.b5 ) ;
            fprintf(stderr,"        me = %08x\n", *me ) ;
#if __WIN32__
            Sleep(500) ;
#else
            usleep(500000);
#endif
         }
      }
      else {
         fprintf(stderr,"Server side disconnected... exiting\n");
         tc_disconnect(device);
         break ;
      }
   }

} /* end main */
Beispiel #14
0
TEST_F( TCDisconnectTest, testSuccess ) {

   int disconnect_status = tc_disconnect( device );

   EXPECT_EQ( disconnect_status, TC_SUCCESS );
} 
Beispiel #15
0
TEST_F( TCDisconnectTest, testNoDevice ) {

   int disconnect_status = tc_disconnect( NULL );

   EXPECT_EQ( disconnect_status, TC_DRIVER_ALREADY_DISCONNECTED );
} 
Beispiel #16
0
int tc_read_(TCDevice * device, char *buffer, int size, const char *file, int line)
{
    long nbytes = 0;

    char client_str[TC_TAG_LENGTH + 20];
    long tmp_nbytes = 0;
    long tmp_size = (long) size;
    void *data = (void *) buffer;
    double ref_time = 0;
    double delta = 0;
    int error = TC_SUCCESS;
    char error_str[512];

    // To support UDP
    unsigned int cliLen = sizeof(struct sockaddr_in);

    if (!device) {
        TrickErrorHndlr *temp_error_hndlr = NULL;
        trick_error_report(temp_error_hndlr,
                           TRICK_ERROR_ALERT, file, line, "tc_read: Trying to read from a NULL device");
        return (-1);
    }

    if (device->disabled) {
        trick_error_report(device->error_handler,
                           TRICK_ERROR_ALERT, file, line, "tc_read: Trying to read from a disabled device");
        return (-1);
    }

    if (device->socket == TRICKCOMM_INVALID_SOCKET) {
        trick_error_report(device->error_handler,
                           TRICK_ERROR_ALERT, file, line, "tc_read: Trying to read from an invalid socket");
        return (-1);
    }

    sprintf(client_str, "(ID = %d  tag = %s)", device->client_id, device->client_tag);

    trick_error_report(device->error_handler, TRICK_ERROR_ALL, file, line,
                       "tc_read: %s reading %d bytes\n", client_str, size);

    /* If this is a software blocking read get the current time from the system */
    if (device->blockio_type == TC_COMM_TIMED_BLOCKIO) {
        ref_time = tc_clock_init();
    }

    /* 
     * Spin until all requested data is 
     * available, an error is returned from recv, or a timeout 
     * limit has been reached. This code is needed for the 
     * socket because sockets can return less
     * data than what was requested when data packets 
     * cross block boundries.  
     */
    while (nbytes != size) {

        /* 
         * recvfrom will return -1 with tc_errno set to TC_EWOULDBLOCK 
         * if this is a non-blocking socket (blockio = NOBLOCKIO) 
         * and no data is available.  recvfrom will usually return 0 
         * for a broken connection. 
         */
        while ((tmp_nbytes = recvfrom(device->socket, data, (size_t) tmp_size,
                                      TC_NOSIGNAL, (struct sockaddr *) &device->cliAddr, &cliLen)) < 0
               && tc_errno == TRICKCOMM_EINTR);

        /* if tmp_nbytes == 0, that is a broken pipe, break out */
        if (tmp_nbytes == 0) {
            trick_error_report(device->error_handler, TRICK_ERROR_ALERT, file, line,
                               "tc_read: %s Other side disconnected. (recvfrom returned 0)", client_str);
            tc_disconnect(device);
            return (nbytes);
        } else if (tmp_nbytes == -1) {
            error = tc_errno;
            if (error != TRICKCOMM_EAGAIN && error != TRICKCOMM_EWOULDBLOCK) {
                sprintf(error_str, "tc_read: %s %s (tc_errno = %d)", client_str, strerror(error), error);
                trick_error_report(device->error_handler, TRICK_ERROR_ALERT, file, line, error_str);
                tc_disconnect(device);
                return (nbytes);
            }
        }
        /* Keep track of total number of bytes read */
        else if (tmp_nbytes > 0) {

#if 0
            /* This indicates the socket protocol: SOCK_STREAM (1) or SOCK_DGRAM (2). */
            int proto_for_socket;
            int opt_len = 4;
            int retval;

            /* Get the socket protocol */
            retval = getsockopt(device->socket, SOL_SOCKET, SO_TYPE,
                                (void *) &proto_for_socket, (socklen_t *) & opt_len);
            if (retval < 0) {
                perror("tc_read: getsockopt");

                trick_error_report(device->error_handler,
                                   TRICK_ERROR_ALERT, file, line,
                                   "Couldn't get the socket protocol. Assumed TCP/IP (not UDP)");
                proto_for_socket = SOCK_STREAM;
            }
#endif

            nbytes += tmp_nbytes;
            /* For UDP (SOCK_DGRAM) just return data with whatever number of bytes were received. */
            if (device->socket_type == SOCK_DGRAM)
                break;

        }

        /* Adjust data pointers for partial reads */
        if (tmp_nbytes > 0 && tmp_nbytes != tmp_size) {
            data = (void *) ((char *) data + tmp_nbytes);
            tmp_size -= tmp_nbytes;
        }

        if (device->blockio_type == TC_COMM_TIMED_BLOCKIO) {

            delta = tc_clock_time(ref_time);

            /* Check for timeouts; this prevents hanging here if the writer dies */
            if (device->blockio_limit < delta && nbytes != size) {
                error = TC_READWRITE_TIMEOUT;
                break;
            }

        } else if (device->blockio_type == TC_COMM_ALL_OR_NOTHING) {

            /* If nothing read and nothing pending break out */
            if (nbytes == 0 && tmp_nbytes == -1 && (tc_errno == TRICKCOMM_EWOULDBLOCK || tc_errno == TRICKCOMM_EAGAIN)) {
                nbytes = -1;
                error = TC_EWOULDBLOCK;
                break;
            }

            /* If something read release processor and loop back for more */
            else if (tmp_nbytes == -1 && tc_errno == TRICKCOMM_EWOULDBLOCK) {
                /* Yield the processor so queued proceses may run */
                TC_RELEASE();
            }
        } else if (device->blockio_type == TC_COMM_NOBLOCKIO) {
            if (tmp_nbytes == -1 && (tc_errno == TRICKCOMM_EWOULDBLOCK || tc_errno == TRICKCOMM_EAGAIN)) {
                if (nbytes == 0) {
                    nbytes = -1;
                }
                error = TC_EWOULDBLOCK;
                break;
            }
        }

    }

    /* If read doesn't capture all data, handle it. */
    switch (error) {
        case TC_READWRITE_TIMEOUT:
            trick_error_report(device->error_handler,
                               TRICK_ERROR_ADVISORY, file, line,
                               "tc_read: %s Failed to read within the specified "
                               "time limit of %f seconds. delta = %f", client_str, device->blockio_limit, delta);
            break;
        case TC_EWOULDBLOCK:
            trick_error_report(device->error_handler,
                               TRICK_ERROR_ALL, file, line,
                               "tc_read: %s %d of %d bytes read during "
                               "non-blocking read.", client_str, nbytes, size);
            break;
        case TC_SUCCESS:
            trick_error_report(device->error_handler,
                               TRICK_ERROR_ALL, file, line,
                               "tc_read: %s: %d bytes successfully read\n", client_str, nbytes);
            break;
    }

    return ((int) nbytes);

}