int StreamIterator(Flow *f, TcpStream *stream, int close, void *cbdata, uint8_t iflags) { SCLogDebug("called with %p, %d, %p, %02x", f, close, cbdata, iflags); int logged = 0; /* optimization: don't iterate list if we've logged all, * so check the last segment's flags */ if (stream->seg_list_tail != NULL && (!(stream->seg_list_tail->flags & SEGMENTTCP_FLAG_LOGAPI_PROCESSED))) { TcpSegment *seg = stream->seg_list; while (seg) { uint8_t flags = iflags; if (seg->flags & SEGMENTTCP_FLAG_LOGAPI_PROCESSED) { seg = seg->next; continue; } if (SEQ_GT(seg->seq + seg->payload_len, stream->last_ack)) { SCLogDebug("seg not (fully) acked yet"); break; } if (seg->seq == stream->isn + 1) flags |= OUTPUT_STREAMING_FLAG_OPEN; /* if we need to close and we're at the last segment in the list * we add the 'close' flag so the logger can close up. */ if (close && seg->next == NULL) flags |= OUTPUT_STREAMING_FLAG_CLOSE; Streamer(cbdata, f, seg->payload, (uint32_t)seg->payload_len, 0, flags); seg->flags |= SEGMENTTCP_FLAG_LOGAPI_PROCESSED; seg = seg->next; logged = 1; } } /* if we need to close we need to invoke the Streamer for sure. If we * logged no segments, we call the Streamer with NULL data so it can * close up. */ if (logged == 0 && close) { Streamer(cbdata, f, NULL, 0, 0, OUTPUT_STREAMING_FLAG_CLOSE); } return 0; }
TSharedPtr< INetworkReplayStreamer > FHttpNetworkReplayStreamingFactory::CreateReplayStreamer() { TSharedPtr< FHttpNetworkReplayStreamer > Streamer( new FHttpNetworkReplayStreamer ); HttpStreamers.Add( Streamer ); return Streamer; }
void visit(const Dumper &dumper, std::ostream &os, std::unordered_set<const Node *> &visited, const Node &node) { if (visited.count(&node)) return; visited.insert(&node); os << nn(node) << ' ' << Streamer(dumper.nodeStyle(node)) << ";\n"; const auto &cs = node.allChildren(); for (auto it = cs.cbegin(); it != cs.cend(); ++it) { const auto &child = *it->second; os << nn(node) << "->" << nn(child) << ' ' << Streamer(dumper.edgeStyle(it->first)) << ";\n"; visit(dumper, os, visited, child); } const auto &ts = node.tallies<AndTally>(); for (auto it = ts.cbegin(); it != ts.cend(); ++it) { const auto &tally = **it; os << nn(node) << "->" << nn(tally) << ' ' << Streamer(dumper.tallyEdgeStyle()) << ";\n"; if (!visited.count(&tally.node())) { os << nn(tally) << ' ' << Streamer(dumper.tallyStyle(tally)) << ";\n"; os << nn(tally) << "->" << nn(tally.node()) << ' ' << Streamer(dumper.tallyEdgeStyle()) << ";\n"; visit(dumper, os, visited, tally.node()); } } const auto &ts2 = node.tallies<OrTally>(); for (auto it = ts2.cbegin(); it != ts2.cend(); ++it) { const auto &tally = **it; os << nn(node) << "->" << nn(tally) << ' ' << Streamer(dumper.tallyEdgeStyle()) << ";\n"; if (!visited.count(&tally.node())) { os << nn(tally) << ' ' << Streamer(dumper.tallyStyle(tally)) << ";\n"; os << nn(tally) << "->" << nn(tally.node()) << ' ' << Streamer(dumper.tallyEdgeStyle()) << ";\n"; visit(dumper, os, visited, tally.node()); } } }
int HttpBodyIterator(Flow *f, int close, void *cbdata, uint8_t iflags) { SCLogDebug("called with %p, %d, %p, %02x", f, close, cbdata, iflags); HtpState *s = f->alstate; if (s != NULL && s->conn != NULL) { int tx_progress_done_value_ts = AppLayerParserGetStateProgressCompletionStatus(IPPROTO_TCP, ALPROTO_HTTP, STREAM_TOSERVER); int tx_progress_done_value_tc = AppLayerParserGetStateProgressCompletionStatus(IPPROTO_TCP, ALPROTO_HTTP, STREAM_TOCLIENT); // for each tx uint64_t tx_id = 0; uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, f->alproto, f->alstate); SCLogDebug("s->conn %p", s->conn); for (tx_id = 0; tx_id < total_txs; tx_id++) { // TODO optimization store log tx htp_tx_t *tx = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, tx_id); if (tx != NULL) { int tx_done = 0; int tx_logged = 0; int tx_progress_ts = AppLayerParserGetStateProgress( IPPROTO_TCP, ALPROTO_HTTP, tx, FlowGetDisruptionFlags(f, STREAM_TOSERVER)); if (tx_progress_ts >= tx_progress_done_value_ts) { int tx_progress_tc = AppLayerParserGetStateProgress( IPPROTO_TCP, ALPROTO_HTTP, tx, FlowGetDisruptionFlags(f, STREAM_TOCLIENT)); if (tx_progress_tc >= tx_progress_done_value_tc) { tx_done = 1; } } SCLogDebug("tx %p", tx); HtpTxUserData *htud = (HtpTxUserData *) htp_tx_get_user_data(tx); if (htud != NULL) { SCLogDebug("htud %p", htud); HtpBody *body = NULL; if (iflags & OUTPUT_STREAMING_FLAG_TOCLIENT) body = &htud->request_body; else if (iflags & OUTPUT_STREAMING_FLAG_TOSERVER) body = &htud->response_body; if (body == NULL) { SCLogDebug("no body"); goto next; } if (body->first == NULL) { SCLogDebug("no body chunks"); goto next; } if (body->last->logged == 1) { SCLogDebug("all logged already"); goto next; } // for each chunk HtpBodyChunk *chunk = body->first; for ( ; chunk != NULL; chunk = chunk->next) { if (chunk->logged) { SCLogDebug("logged %d", chunk->logged); continue; } uint8_t flags = iflags | OUTPUT_STREAMING_FLAG_TRANSACTION; if (chunk->stream_offset == 0) flags |= OUTPUT_STREAMING_FLAG_OPEN; /* if we need to close and we're at the last segment in the list * we add the 'close' flag so the logger can close up. */ if ((tx_done || close) && chunk->next == NULL) { flags |= OUTPUT_STREAMING_FLAG_CLOSE; } // invoke Streamer Streamer(cbdata, f, chunk->data, (uint32_t)chunk->len, tx_id, flags); //PrintRawDataFp(stdout, chunk->data, chunk->len); chunk->logged = 1; tx_logged = 1; } next: /* if we need to close we need to invoke the Streamer for sure. If we * logged no chunks, we call the Streamer with NULL data so it can * close up. */ if (tx_logged == 0 && (close||tx_done)) { Streamer(cbdata, f, NULL, 0, tx_id, OUTPUT_STREAMING_FLAG_CLOSE|OUTPUT_STREAMING_FLAG_TRANSACTION); } } } } } return 0; }