delay all new TCP PSH frames until timeout or ACK is received
This commit is contained in:
+15
-10
@@ -1302,7 +1302,7 @@ void IPStackSimulator::on_client_tcp_frame(
|
|||||||
|
|
||||||
if (conn_valid && acked_seq_changed) {
|
if (conn_valid && acked_seq_changed) {
|
||||||
// Try to send some more data if the client is waiting on it
|
// Try to send some more data if the client is waiting on it
|
||||||
this->send_pending_push_frame(c, *conn);
|
this->send_pending_push_frame(c, *conn, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1356,19 +1356,28 @@ void IPStackSimulator::open_server_connection(shared_ptr<IPClient> c, IPClient::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPStackSimulator::send_pending_push_frame(shared_ptr<IPClient> c, IPClient::TCPConnection& conn) {
|
void IPStackSimulator::send_pending_push_frame(
|
||||||
|
shared_ptr<IPClient> c, IPClient::TCPConnection& conn, bool always_send) {
|
||||||
size_t pending_bytes = evbuffer_get_length(conn.pending_data.get());
|
size_t pending_bytes = evbuffer_get_length(conn.pending_data.get());
|
||||||
if (!pending_bytes) {
|
if (!pending_bytes) {
|
||||||
|
event_del(conn.resend_push_event.get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're waiting to receive an ACK from the client, don't send another PSH
|
||||||
|
// until we get the ACK (unless this is a resend of a previous PSH due to a
|
||||||
|
// timeout)
|
||||||
|
if (!always_send && event_pending(conn.resend_push_event.get(), EV_TIMEOUT, nullptr)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytes_to_send = min<size_t>(pending_bytes, conn.next_push_max_frame_size);
|
size_t bytes_to_send = min<size_t>(pending_bytes, conn.next_push_max_frame_size);
|
||||||
if ((c->protocol == Protocol::HDLC_TAPSERVER) && (bytes_to_send > 200)) {
|
if (c->protocol == Protocol::HDLC_TAPSERVER) {
|
||||||
// There is a bug in Dolphin's modem implementation (which I wrote, so it's
|
// There is a bug in Dolphin's modem implementation (which I wrote, so it's
|
||||||
// my fault) that causes commands to be dropped when too much data is sent
|
// my fault) that causes commands to be dropped when too much data is sent
|
||||||
// at once. To work around this, we only send up to 200 bytes in each push
|
// at once. To work around this, we only send up to 200 bytes in each push
|
||||||
// frame.
|
// frame.
|
||||||
bytes_to_send = 200;
|
bytes_to_send = min<size_t>(bytes_to_send, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
ip_stack_simulator_log.debug("Sending PSH frame with seq_num %08" PRIX32 ", 0x%zX/0x%zX data bytes",
|
ip_stack_simulator_log.debug("Sending PSH frame with seq_num %08" PRIX32 ", 0x%zX/0x%zX data bytes",
|
||||||
@@ -1448,15 +1457,11 @@ void IPStackSimulator::dispatch_on_resend_push(evutil_socket_t, short, void* ctx
|
|||||||
if (!sim) {
|
if (!sim) {
|
||||||
ip_stack_simulator_log.warning("Resend push event triggered for client on deleted simulator; ignoring");
|
ip_stack_simulator_log.warning("Resend push event triggered for client on deleted simulator; ignoring");
|
||||||
} else {
|
} else {
|
||||||
sim->on_resend_push(c, *conn);
|
sim->send_pending_push_frame(c, *conn, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPStackSimulator::on_resend_push(shared_ptr<IPClient> c, IPClient::TCPConnection& conn) {
|
|
||||||
this->send_pending_push_frame(c, conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IPStackSimulator::dispatch_on_server_input(struct bufferevent*, void* ctx) {
|
void IPStackSimulator::dispatch_on_server_input(struct bufferevent*, void* ctx) {
|
||||||
auto* conn = reinterpret_cast<IPClient::TCPConnection*>(ctx);
|
auto* conn = reinterpret_cast<IPClient::TCPConnection*>(ctx);
|
||||||
auto c = conn->client.lock();
|
auto c = conn->client.lock();
|
||||||
@@ -1483,7 +1488,7 @@ void IPStackSimulator::on_server_input(shared_ptr<IPClient> c, IPClient::TCPConn
|
|||||||
event_add(c->idle_timeout_event.get(), &tv);
|
event_add(c->idle_timeout_event.get(), &tv);
|
||||||
|
|
||||||
evbuffer_add_buffer(conn.pending_data.get(), buf);
|
evbuffer_add_buffer(conn.pending_data.get(), buf);
|
||||||
this->send_pending_push_frame(c, conn);
|
this->send_pending_push_frame(c, conn, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPStackSimulator::dispatch_on_server_error(
|
void IPStackSimulator::dispatch_on_server_error(
|
||||||
|
|||||||
@@ -144,15 +144,13 @@ private:
|
|||||||
void on_client_udp_frame(std::shared_ptr<IPClient> c, const FrameInfo& fi);
|
void on_client_udp_frame(std::shared_ptr<IPClient> c, const FrameInfo& fi);
|
||||||
void on_client_tcp_frame(std::shared_ptr<IPClient> c, const FrameInfo& fi);
|
void on_client_tcp_frame(std::shared_ptr<IPClient> c, const FrameInfo& fi);
|
||||||
|
|
||||||
static void dispatch_on_resend_push(evutil_socket_t fd, short events, void* ctx);
|
|
||||||
void on_resend_push(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn);
|
|
||||||
|
|
||||||
static void dispatch_on_server_input(struct bufferevent* bev, void* ctx);
|
static void dispatch_on_server_input(struct bufferevent* bev, void* ctx);
|
||||||
void on_server_input(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn);
|
void on_server_input(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn);
|
||||||
static void dispatch_on_server_error(struct bufferevent* bev, short events, void* ctx);
|
static void dispatch_on_server_error(struct bufferevent* bev, short events, void* ctx);
|
||||||
void on_server_error(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn, short events);
|
void on_server_error(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn, short events);
|
||||||
|
|
||||||
void send_pending_push_frame(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn);
|
static void dispatch_on_resend_push(evutil_socket_t, short, void* ctx);
|
||||||
|
void send_pending_push_frame(std::shared_ptr<IPClient> c, IPClient::TCPConnection& conn, bool always_send);
|
||||||
void send_tcp_frame(
|
void send_tcp_frame(
|
||||||
std::shared_ptr<IPClient> c,
|
std::shared_ptr<IPClient> c,
|
||||||
IPClient::TCPConnection& conn,
|
IPClient::TCPConnection& conn,
|
||||||
|
|||||||
Reference in New Issue
Block a user