コード例 #1
0
bool rfs_uc_tcp_gro::rx_dispatch_packet(mem_buf_desc_t* p_rx_pkt_mem_buf_desc_info, void* pv_fd_ready_array /* = NULL */)
{
	struct iphdr* p_ip_h = p_rx_pkt_mem_buf_desc_info->path.rx.p_ip_h;
	struct tcphdr* p_tcp_h = p_rx_pkt_mem_buf_desc_info->path.rx.p_tcp_h;

	if (!m_b_active) {
		if (!m_b_reserved && m_p_gro_mgr->is_stream_max()) {
			goto out;
		}
	}

	if (!tcp_ip_check(p_rx_pkt_mem_buf_desc_info, p_ip_h, p_tcp_h)) {
		if (m_b_active) {
			flush_gro_desc(pv_fd_ready_array);
		}
		goto out;
	}

	if (!m_b_active) {
		if (!m_b_reserved) {
			m_b_reserved = m_p_gro_mgr->reserve_stream(this);
		}
		init_gro_desc(p_rx_pkt_mem_buf_desc_info, p_ip_h, p_tcp_h);
		m_b_active = true;
	} else {
		if (ntohl(p_tcp_h->seq) != m_gro_desc.next_seq) {
			flush_gro_desc(pv_fd_ready_array);
			goto out;
		}

		if (!timestamp_check(p_tcp_h)) {
			flush_gro_desc(pv_fd_ready_array);
			goto out;
		}

		add_packet(p_rx_pkt_mem_buf_desc_info, p_ip_h, p_tcp_h);
	}

	if (m_gro_desc.buf_count >= m_n_buf_max || m_gro_desc.ip_tot_len >= m_n_byte_max) {
		flush_gro_desc(pv_fd_ready_array);
	}

	return true;

out:
	return rfs_uc::rx_dispatch_packet(p_rx_pkt_mem_buf_desc_info, pv_fd_ready_array);
}
コード例 #2
0
/* feed implementation for Beast-format data (including Radarcape) */
static PyObject *feed_beast(modesreader *self, Py_buffer *buffer, int max_messages)
{
    PyObject *rv = NULL;
    uint8_t *buffer_start, *p, *eod;
    int message_count = 0;
    PyObject *message_tuple = NULL;
    PyObject **messages = NULL;
    int error_pending = 0;

    buffer_start = buffer->buf;

    if (max_messages <= 0) {
        /* allocate the maximum size we might need, given a minimal encoding of:
         *   <1A> <'1'> <6 bytes timestamp> <1 byte signal> <2 bytes message> = 11 bytes total
         */
        max_messages = buffer->len / 11 + 2;
    }

    messages = calloc(max_messages, sizeof(PyObject*));
    if (!messages) {
        PyErr_NoMemory();
        goto out;
    }

    /* parse messages */
    p = buffer_start;
    eod = buffer_start + buffer->len;
    while (p+2 <= eod && message_count+2 < max_messages) {
        int message_len = -1;
        uint64_t timestamp;
        uint8_t signal;
        uint8_t data[14];
        uint8_t *m, *eom;
        int i;
        uint8_t type;
        PyObject *message;
        int wanted;

        if (p[0] != 0x1a) {
            error_pending = 1;
            if (message_count > 0)
                goto nomoredata;
            PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected a 0x1A marker at offset %d but found 0x%02x instead", (int) (p - buffer_start), (int)p[0]);
            goto out;
        }

        type = p[1];
        switch (type) {
        case '1': message_len = 2; break; /* mode A/C */
        case '2': message_len = 7; break; /* mode S short */
        case '3': message_len = 14; break; /* mode S long */
        case '4': message_len = 14; break; /* radarcape status message */
        default:
            error_pending = 1;
            if (message_count > 0)
                goto nomoredata;
            PyErr_Format(PyExc_ValueError, "Lost sync with input stream: unexpected message type 0x%02x after 0x1A marker at offset %d", (int)p[1], (int) (p - buffer_start));
            goto out;
        }

        m = p + 2;
        eom = m + 7 + message_len;
        if (eom > eod)
            break;

#define ADVANCE \
        do {                                                            \
            if (*m++ == 0x1a) {                                         \
                if (m < eod && *m != 0x1a) {                            \
                    error_pending = 1;                                  \
                    if (message_count > 0)                              \
                        goto nomoredata;                                \
                    PyErr_SetString(PyExc_ValueError, "Lost sync with input stream: expected 0x1A after 0x1A escape"); \
                    goto out;                                           \
                }                                                       \
                ++m, ++eom;                                             \
                if (eom > eod)                                          \
                    goto nomoredata;                                    \
            }                                                           \
        } while(0)

        /* timestamp, 6 bytes */
        timestamp = *m;
        ADVANCE;
        timestamp = (timestamp << 8) | *m;
        ADVANCE;
        timestamp = (timestamp << 8) | *m;
        ADVANCE;
        timestamp = (timestamp << 8) | *m;
        ADVANCE;
        timestamp = (timestamp << 8) | *m;
        ADVANCE;
        timestamp = (timestamp << 8) | *m;
        ADVANCE;

        /* signal, 1 byte */
        signal = *m;
        ADVANCE;

        /* message, N bytes */
        for (i = 0; i < message_len; ++i) {
            data[i] = *m;
            ADVANCE;
        }

        /* do some filtering */

        if (type == '4') {
            /* radarcape-style status message, use this to switch our decoder type */

            self->radarcape_utc_bugfix = (data[2] & 0x80) == 0x80;

            if (self->allow_mode_change) {
                decoder_mode newmode;
                if (data[0] & 0x10) {
                    /* radarcape in GPS timestamp mode */
                    if ((data[2] & 0x20) == 0x20) {
                        newmode = DECODER_RADARCAPE_EMULATED;
                    } else {
                        newmode = DECODER_RADARCAPE;
                    }
                } else {
                    /* radarcape in 12MHz timestamp mode */
                    newmode = DECODER_BEAST;
                }

                /* handle mode changes by inserting an event message */
                if (newmode != self->decoder_mode) {
                    set_decoder_mode(self, newmode);
                    if (self->want_events) {
                        if (! (messages[message_count++] = make_mode_change_event(self)))
                        goto out;
                    }
                }
            }
        }

        if (self->decoder_mode == DECODER_BEAST) {
            /* 12MHz mode */

            /* check for very out of range value
             * (dump1090 can hold messages for up to 60 seconds! so be conservative here)
             * also work around dump1090-mutability issue #47 which can send very stale Mode A/C messages
             */
            if (self->want_events && type != '1' && !timestamp_check(self, timestamp)) {
                if (! (messages[message_count++] = make_timestamp_jump_event(self, timestamp)))
                    goto out;
            }
        } else {
            /* gps mode */

            /* adjust timestamp so that it is a contiguous nanoseconds-since-
             * midnight value, rather than the raw form which skips values once
             * a second
             */
            uint64_t nanos = timestamp & 0x00003FFFFFFF;
            uint64_t secs = timestamp >> 30;

            if (!self->radarcape_utc_bugfix) {
                /* fix up the timestamp so it is UTC, not 1 second ahead */
                --secs;
            }

            timestamp = nanos + secs * 1000000000;

            /* adjust for the timestamp being at the _end_ of the frame;
             * we don't really care about getting a particular starting point
             * (that's just a fixed offset), so long as it is _the same in
             * every frame_.
             *
             * (but don't do this for status messages as they have a timestamp
             * as at the start of the message, which is basically the time of
             * the PPS)
             */
            if (type != '4') {
                uint64_t adjust = (8000 + message_len * 8000); /* each byte takes 8us to transmit, plus 8us preamble */
                if (adjust <= timestamp) {
                    timestamp = timestamp - adjust;
                } else {
                    /* wrap it to the previous day */
                    timestamp = timestamp + 86400 * 1000000000ULL - adjust;
                }
            }

            /* check for end of day rollover */
            if (self->want_events && self->last_timestamp >= (86340 * 1000000000ULL) && timestamp <= (60 * 1000000000ULL)) {
                if (! (messages[message_count++] = make_epoch_rollover_event(self, timestamp)))
                    goto out;
            } else if (self->want_events && type != '1' && !timestamp_check(self, timestamp)) {
                if (! (messages[message_count++] = make_timestamp_jump_event(self, timestamp)))
                    goto out;
            }
        }

        if (type != '1') {
            timestamp_update(self, timestamp);
        }

        if (type == '4') {
            /* radarcape-style status message, emit the status event if wanted */
            if (self->want_events) {
                if (! (messages[message_count++] = make_radarcape_status_event(self, timestamp, data)))
                    goto out;
            }

            /* don't try to process this as a Mode S message */
            p = m;
            continue;
        }

        /* it's a Mode A/C or Mode S message, parse it */
        if (! (message = modesmessage_from_buffer(timestamp, signal, data, message_len)))
            goto out;

        /* apply filters, update seen-set */
        ++self->received_messages;
        wanted = filter_message(self, message);
        if (wanted < 0)
            goto out;
        else if (wanted)
            messages[message_count++] = message;
        else {
            ++self->suppressed_messages;
            Py_DECREF(message);
        }

        p = m;
    }

 nomoredata:
    if (! (message_tuple = PyTuple_New(message_count)))
        goto out;

    while (--message_count >= 0) {
        PyTuple_SET_ITEM(message_tuple, message_count, messages[message_count]); /* steals ref */
    }

    rv = Py_BuildValue("(l,N,N)", (long) (p - buffer_start), message_tuple, PyBool_FromLong(error_pending));

 out:
    while (--message_count >= 0) {
        Py_XDECREF(messages[message_count]);
    }
    free(messages);
    return rv;
}
コード例 #3
0
static PyObject *feed_avr(modesreader *self, Py_buffer *buffer, int max_messages)
{
    PyObject *rv = NULL;
    uint8_t *buffer_start, *p, *eod;
    int message_count = 0;
    PyObject *message_tuple = NULL;
    PyObject **messages = NULL;
    int error_pending = 0;

    buffer_start = buffer->buf;

    if (max_messages <= 0) {
        /* allocate the maximum size we might need, given a minimal encoding of:
         *   '*' <2 bytes message> ';' LF
         */
        max_messages = buffer->len / 5 + 1;
    }

    messages = calloc(max_messages, sizeof(PyObject*));
    if (!messages) {
        PyErr_NoMemory();
        goto out;
    }

    p = buffer_start;
    eod = buffer_start + buffer->len;
    while (p+17 <= eod && message_count+1 < max_messages) {
        int message_len = -1;
        uint64_t timestamp;
        uint8_t data[14];
        uint8_t message_format;
        int i;
        uint8_t *m;
        PyObject *message;

        message_format = p[0];
        if (message_format != '@' &&
            message_format != '%' &&
            message_format != '<' &&
            message_format != '*' &&
            message_format != ':') {
            error_pending = 1;
            if (message_count > 0)
                goto nomoredata;
            PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected '@'/'%%'/'<'/'*'/':' at offset %d but found 0x%02x instead",
                         (int) (p - buffer_start), (int)p[0]);
            goto out;
        }

        m = p + 1;
        if (message_format == '@' ||
            message_format == '%' ||
            message_format == '<') {
            /* read 6 bytes of timestamp */
            timestamp = 0;
            for (i = 0; i < 12; ++i, ++m) {
                int c;

                if (m >= eod) {
                    goto nomoredata;
                }

                timestamp <<= 4;
                c = hexvalue(*m);
                if (c >= 0) {
                    timestamp |= c;
                } else {
                    error_pending = 1;
                    if (message_count > 0)
                        goto nomoredata;
                    PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected a hex digit at offset %d but found 0x%02x instead",
                                 (int) (m - buffer_start), (int)*m);
                    goto out;
                }
            }
        } else {
            /* AVR format with no timestamp */
            timestamp = 0;
        }

        if (message_format == '<') {
            /* in format '<', skip 1 byte of signal */
            m += 2;
            if (m >= eod)
                goto nomoredata;
        }

        /* read 2-14 bytes of data */
        message_len = 0;
        while (message_len < 14) {
            int c0, c1;

            if (m+1 >= eod) {
                goto nomoredata;
            }

            if (m[0] == ';') {
                break; /* end of message marker */
            } else {
                c0 = hexvalue(m[0]);
                if (c0 < 0) {
                    error_pending = 1;
                    if (message_count > 0)
                        goto nomoredata;

                    PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected a hex digit at offset %d but found 0x%02x instead",
                                 (int) (m - buffer_start), (int)m[0]);
                    goto out;
                }
            }

            c1 = hexvalue(m[1]);
            if (c1 < 0) {
                error_pending = 1;
                if (message_count > 0)
                    goto nomoredata;

                PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected a hex digit at offset %d but found 0x%02x instead",
                             (int) (m - buffer_start), (int)m[1]);
                goto out;
            }

            if (message_len < 14) {
                data[message_len] = (c0 << 4) | c1;
            }
            ++message_len;
            m += 2;
        }

        /* consume ';' */
        if (m >= eod)
            goto nomoredata;
        if (*m != ';') {
            error_pending = 1;
            if (message_count > 0)
                goto nomoredata;

            PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected ';' at offset %d but found 0x%02x instead",
                         (int) (m - buffer_start), (int)*m);
            goto out;
        }

        /* CR LF, LF CR, LF all seen! ugh. */

        /* skip until CR or LF */
        while (m < eod && *m != '\r' && *m != '\n')
            ++m;

        /* consume however many CRs and LFs */
        while (m < eod && (*m == '\r' || *m == '\n'))
            ++m;

        /* check length */
        if (message_len != 2 && message_len != 7 && message_len != 14) {
            error_pending = 1;
            if (message_count > 0)
                goto nomoredata;

            PyErr_Format(PyExc_ValueError, "Lost sync with input stream: unexpected %d-byte message starting at offset %d",
                         message_len, (int) (p - buffer_start));
            goto out;
        }

        /* check for very out of range value
         * (dump1090 can hold messages for up to 60 seconds! so be conservative here)
         * also work around dump1090-mutability issue #47 which can send very stale Mode A/C messages
         */
        if (self->want_events && message_len != 2 && !timestamp_check(self, timestamp)) {
            if (! (messages[message_count++] = make_timestamp_jump_event(self, timestamp)))
                goto out;
        }

        timestamp_update(self, timestamp);

        /* decode it */
        if (! (message = modesmessage_from_buffer(timestamp, 0, data, message_len)))
            goto out;

        /* apply filters, update seen-set */
        ++self->received_messages;
        int wanted = filter_message(self, message);
        if (wanted < 0)
            goto out;
        else if (wanted)
            messages[message_count++] = message;
        else {
            ++self->suppressed_messages;
            Py_DECREF(message);
        }

        /* next message */
        p = m;
    }

 nomoredata:
    if (! (message_tuple = PyTuple_New(message_count)))
        goto out;

    while (--message_count >= 0) {
        PyTuple_SET_ITEM(message_tuple, message_count, messages[message_count]); /* steals ref */
    }

    rv = Py_BuildValue("(l,N,N)", (long) (p - buffer_start), message_tuple, PyBool_FromLong(error_pending));

 out:
    while (--message_count >= 0) {
        Py_XDECREF(messages[message_count]);
    }
    free(messages);
    return rv;
}