コード例 #1
0
fronius_error_t fronius_pkt_validate(const struct fronius_pkt * pkt)
{
    uint8_t *p = (uint8_t *) & pkt->length;
    uint8_t checksum = 0;
    fronius_error_t err;
    int i;

    err = fronius_pkt_validate_header(pkt);
    if (err)
        return err;

    /* validate checksum */
    i = FRONIUS_HEADERLEN + pkt->length;

    while (i--)
        checksum += *p++;

    if (pkt->checksum != checksum)
        return FRONIUS_ERR_CHECKSUM;

    /* packet is valid */
    return FRONIUS_ERR_NOERROR;
}
コード例 #2
0
ファイル: fronius_pkt_recv.c プロジェクト: mhei/libfronius
int fronius_pkt_recv(struct fronius_dev *dev,
                     const struct fronius_pkt *pkt)
{
    uint8_t buf[FRONIUS_MAX_PKTLEN];
    uint8_t crc;
    size_t pktlen = FRONIUS_MAX_PKTLEN;
    size_t bytes_read = 0;
    fd_set rfds;
    struct timeval tv;
    int rv;

    memset(&buf, 0, sizeof(buf));

    do {
        FD_ZERO(&rfds);
        FD_SET(dev->fd, &rfds);
        tv.tv_sec = FRONIUS_RECV_TIMEOUT;
        tv.tv_usec = 0;

        rv = select(dev->fd + 1, &rfds, NULL, NULL, &tv);

    } while (rv == -1 && errno == EINTR);

    if (rv == -1)
        return rv;

    /* timed out */
    if (rv == 0) {
        errno = ETIMEDOUT;
        return -1;
    }

    do {
        ssize_t c = read(dev->fd, &buf[bytes_read], pktlen - bytes_read);
        if (c <= -1) {
            if (errno == EINTR)
                continue;
            return c;
        }

        /* got some bytes */
        bytes_read += c;
        dev->bytes_received += c;

        /* does the buffer looks like a packet? */
        if (bytes_read >= FRONIUS_MIN_PKTLEN) {
            switch (fronius_pkt_validate_header((struct fronius_pkt *) buf)) {
            case FRONIUS_ERR_NOERROR:
                /* trim read to real packet length after
                   fronius_pkt_validate_header ensured maximum packet length */
                pktlen = buf[FRONIUS_OF_LENGTH] + FRONIUS_MIN_PKTLEN;
                break;
            default:
                /* read data looks strange */
#if 0
                fprintf(stderr, "strange data\n");
                dump_buf(buf, bytes_read);
#endif
                errno = EIO;
                return -1;
            }
        }

    } while (bytes_read < pktlen);

    /* move crc to end of buffer (use buffer to not override it accidently) */
    crc = buf[pktlen - 1];
    buf[pktlen - 1] = 0;
    buf[FRONIUS_MAX_PKTLEN - 1] = crc;

    /* copy buffer to packet */
    memcpy((void *) pkt, buf, sizeof(*pkt));

    /* update packet counter */
    dev->pkts_received++;
    gettimeofday(&dev->last_received, NULL);

    /* dump packet */
    if (dev->debug)
        fronius_pkt_dump(NULL, "fronius_pkt_recv", pkt, dev->rawdump);

    /* deep packet validation */
    switch (fronius_pkt_validate(pkt)) {
    case FRONIUS_ERR_NOERROR:
        break;
    case FRONIUS_ERR_CHECKSUM:
        dev->checksum_errors++;
        /* fallthrough */
    default:
        errno = EIO;
        return -1;
    }

    return 0;
}