Example #1
0
void trick_error_set_send_hs_flag(TrickErrorHndlr * error_hndlr,        /* Inout: Err handler data */
                                  TrickErrorLevel level,        /* In: Err report level stream to set */
                                  int use_send_hs)
{                                      /* In: 1= use send_hs;else use fprintf */

    /* Check for setting of default error handling object. */
    if (error_hndlr == (TrickErrorHndlr *) NULL) {
        error_hndlr = &(trick_error_hndlr_default);
    }

    /* Check sanity of reporting level. */
    if (level > TRICK_ERROR_SILENT) {
        trick_error_report(error_hndlr, TRICK_ERROR_ALERT,
                           __FILE__, __LINE__,
                           "Unknown error level for " "trick_error_set_send_hs_flag; level unchanged.\n");
        return;
    }

    /* Set the appropriate use_send_hs flag */
    error_hndlr->use_send_hs[level] = use_send_hs;

    /* warn the user that send_hs has been replaced with fprintf */
    trick_error_report(error_hndlr, TRICK_ERROR_ALERT,
                       __FILE__, __LINE__,
                       "trick_error_set_send_hs_flag no longer supported.  All printouts will use fprintf\n");

    return;

}
Example #2
0
void trick_error_set_stream(TrickErrorHndlr * error_hndlr,      /* INOUT: Error handler data */
                            TrickErrorLevel level,      /* IN: Err report level stream to set */
                            FILE * stream)
{                                      /* IN: Err stream for report level */

    /* Check for setting of default error handling object. */
    if (error_hndlr == (TrickErrorHndlr *) NULL) {
        error_hndlr = &(trick_error_hndlr_default);
    }

    /* Check sanity of reporting level. */
    if (level > TRICK_ERROR_SILENT) {
        trick_error_report(error_hndlr, TRICK_ERROR_ALERT,
                           __FILE__, __LINE__, "Unknown error level for " "trick_error_set_stream; level unchanged.\n");
        return;
    }

    /* Set the appropriate file stream pointer. */
    if (stream == (FILE *) NULL) {
        error_hndlr->report_stream[level] = stderr;
    } else {
        error_hndlr->report_stream[level] = stream;
    }
    return;

}
Example #3
0
int tc_read_byteswap(TCDevice * device, char *buffer, int size, ATTRIBUTES * attr)
{
    char local_byteorder;
    int ret = 0;
    static char swap[65536];

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

    TRICK_GET_BYTE_ORDER(local_byteorder)

        if (device->byte_info[TC_BYTE_ORDER_NDX] != local_byteorder) {
        memset(swap, 0, (size_t) size);
        ret = tc_read(device, (char *) swap, size);
        trick_bswap_buffer(buffer, swap, attr, 0);
        return (ret);
    } else {
        return (tc_read(device, (char *) buffer, size));
    }

    return 0;

}
Example #4
0
int tc_error(TCDevice * device, int on_off)
{
    size_t size;

    if (!device) {
        TrickErrorHndlr *temp_error_hndlr = NULL;
        trick_error_report(temp_error_hndlr,
                           TRICK_ERROR_ALERT, __FILE__, __LINE__, "Trying to set up error handler on NULL device");
        return (-1);
    }

    /* If there is no error handler, initialize one */
    if (device->error_handler == NULL) {
        size = sizeof(TrickErrorHndlr);
        device->error_handler = (TrickErrorHndlr *) malloc(size);
        trick_error_init(device->error_handler, NULL, NULL, TRICK_ERROR_ALL);
    }

    /* Now turn on/off */
    if (on_off == 1) {
        device->error_handler->report_level = TRICK_ERROR_ALL;
    } else {
        device->error_handler->report_level = TRICK_ERROR_SILENT;
    }

    return 0;

}
Example #5
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);
}
Example #6
0
/*
 *Set a device to BLOCKIO or NOBLOCKIO - may be used as a toggle
 */
int tc_blockio(TCDevice * device, TCCommBlocking blockflag)
{
    char client_str[TC_TAG_LENGTH + 256];
    int on = 1;
    int off = 0;

    if (device == NULL) {
        return TC_EWOULDBLOCK;
    }

    /* Status message */
    sprintf(client_str, "(ID = %d  tag = %s)", device->client_id, device->client_tag);
    trick_error_report(device->error_handler, TRICK_ERROR_TRIVIAL, __FILE__,
                       __LINE__, "%s blockflag = %d\n", client_str, blockflag);


    switch (blockflag) {

        case TC_COMM_BLOCKIO:
            /* Set socket to blocking */
            if (IOCTL_SOCKET(device->socket, (unsigned long) FIONBIO, &off) < 0) {
                trick_error_report(device->error_handler,
                                   TRICK_ERROR_ALERT, __FILE__, __LINE__, "could not set socket to blocking\n");
                return (TC_EWOULDBLOCK);
            }
            device->blockio_type = blockflag;
            break;

        case TC_COMM_NOBLOCKIO:
            /* Set socket to non-blocking */
            if (IOCTL_SOCKET(device->socket, (unsigned long) FIONBIO, &on) < 0) {
                trick_error_report(device->error_handler,
                                   TRICK_ERROR_ALERT, __FILE__, __LINE__, "could not set socket to non-blocking\n");
                return (TC_EWOULDBLOCK);
            }
            device->blockio_type = blockflag;
            break;

        case TC_COMM_TIMED_BLOCKIO:
            /* Set socket to non-blocking */
            if (IOCTL_SOCKET(device->socket, (unsigned long) FIONBIO, &on) < 0) {
                trick_error_report(device->error_handler,
                                   TRICK_ERROR_ALERT, __FILE__,
                                   __LINE__, "could not set socket to software-blocking\n");
                return (TC_EWOULDBLOCK);
            }
            device->blockio_type = blockflag;
            break;

        case TC_COMM_ALL_OR_NOTHING:
            /* Set socket to non-blocking */
            if (IOCTL_SOCKET(device->socket, (unsigned long) FIONBIO, &on) < 0) {
                trick_error_report(device->error_handler,
                                   TRICK_ERROR_ALERT, __FILE__, __LINE__, "could not set socket to all_or nothing\n");
                return (TC_EWOULDBLOCK);
            }
            device->blockio_type = blockflag;
            break;

        default:
            trick_error_report(device->error_handler,
                               TRICK_ERROR_ALERT, __FILE__, __LINE__,
                               "Invalid second argument."
                               "Second argument should be one of the following:\n"
                               "  TC_COMM_BLOCKIO,\n"
                               "  TC_COMM_NOBLOCKIO,\n" "  TC_COMM_TIMED_BLOCKIO,\n" "  TC_COMM_ALL_OR_NOTHING\n\n");
            return (TC_EWOULDBLOCK);
    }

    return (0);

}
Example #7
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);

}