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); }
/* 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; }
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; }