Clean up callback_list, remove sentinel/active/tail, callbacks return bool for removal, register before send

This commit is contained in:
Ian Gulliver
2026-04-11 15:01:37 +09:00
parent 938b4b8a4c
commit 1c8c645878
5 changed files with 66 additions and 72 deletions

View File

@@ -38,13 +38,12 @@ static void discover_peer(peer_callback on_found, fail_callback on_timeout) {
udp::prepend(buf, mcast_mac, ns.mac, ns.ip, igmp::PICOMAP_DISCOVERY_GROUP,
PICOMAP_PORT, PICOMAP_PORT, *encoded, 1);
net_send_raw(buf.span());
ipv4::ip4_addr our_ip = ns.ip;
auto timer = std::make_shared<timer_handle>(nullptr);
auto cb_id = std::make_shared<frame_cb_handle>(nullptr);
*cb_id = net_add_frame_callback([our_ip, timer, cb_id, on_found = std::move(on_found)](std::span<const uint8_t> frame) -> bool {
auto cb = std::make_shared<frame_cb_handle>(nullptr);
*cb = net_add_frame_callback([our_ip, timer, on_found = std::move(on_found)](std::span<const uint8_t> frame) -> bool {
parse_buffer pb(frame);
auto* eth_hdr = pb.consume<eth::header>();
if (!eth_hdr || eth_hdr->ethertype != eth::ETH_IPV4) return false;
@@ -60,10 +59,12 @@ static void discover_peer(peer_callback on_found, fail_callback on_timeout) {
return true;
});
*timer = dispatch_schedule_ms(5000, [cb_id, on_timeout = std::move(on_timeout)]() {
net_remove_frame_callback(*cb_id);
*timer = dispatch_schedule_ms(5000, [cb, on_timeout = std::move(on_timeout)]() {
net_remove_frame_callback(*cb);
on_timeout();
});
net_send_raw(buf.span());
}
static void test_discovery_igmp(const responder& resp) {
@@ -71,11 +72,10 @@ static void test_discovery_igmp(const responder& resp) {
prepend_buffer<4096> buf;
igmp::prepend_query(buf, ns.mac, ns.ip, igmp::PICOMAP_DISCOVERY_GROUP);
net_send_raw(buf.span());
auto timer = std::make_shared<timer_handle>(nullptr);
auto cb_id = std::make_shared<frame_cb_handle>(nullptr);
*cb_id = net_add_frame_callback([resp, timer](std::span<const uint8_t> frame) -> bool {
auto cb = std::make_shared<frame_cb_handle>(nullptr);
*cb = net_add_frame_callback([resp, timer](std::span<const uint8_t> frame) -> bool {
ipv4::ip4_addr group;
if (!igmp::parse_report(frame, group)) return false;
if (group != igmp::PICOMAP_DISCOVERY_GROUP) return false;
@@ -84,10 +84,12 @@ static void test_discovery_igmp(const responder& resp) {
return true;
});
*timer = dispatch_schedule_ms(5000, [cb_id, resp]() {
net_remove_frame_callback(*cb_id);
*timer = dispatch_schedule_ms(5000, [cb, resp]() {
net_remove_frame_callback(*cb);
resp.respond(ResponseTest{false, {"no IGMP report within 5s"}});
});
net_send_raw(buf.span());
}
static void test_discovery_info(const responder& resp) {
@@ -107,13 +109,12 @@ static void test_ping(const responder& resp, ipv4::ip4_addr dst_ip) {
prepend_buffer<4096> buf;
icmp::prepend_echo_request(buf, ns.mac, ns.ip,
eth::MAC_BROADCAST, dst_ip, ping_id, 1);
net_send_raw(buf.span());
ipv4::ip4_addr our_ip = ns.ip;
auto timer = std::make_shared<timer_handle>(nullptr);
auto cb_id = std::make_shared<frame_cb_handle>(nullptr);
*cb_id = net_add_frame_callback([resp, ping_id, our_ip, timer](std::span<const uint8_t> frame) -> bool {
auto cb = std::make_shared<frame_cb_handle>(nullptr);
*cb = net_add_frame_callback([resp, ping_id, our_ip, timer](std::span<const uint8_t> frame) -> bool {
ipv4::ip4_addr src_ip;
if (!icmp::parse_echo_reply(frame, src_ip, ping_id)) return false;
dispatch_cancel_timer(*timer);
@@ -125,10 +126,12 @@ static void test_ping(const responder& resp, ipv4::ip4_addr dst_ip) {
return true;
});
*timer = dispatch_schedule_ms(5000, [cb_id, resp]() {
net_remove_frame_callback(*cb_id);
*timer = dispatch_schedule_ms(5000, [cb, resp]() {
net_remove_frame_callback(*cb);
resp.respond(ResponseTest{false, {"no reply from non-self host within 5s"}});
});
net_send_raw(buf.span());
}
static void test_ping_subnet(const responder& resp) {
@@ -187,9 +190,6 @@ static void start_ping_rate(const responder& resp, uint16_t target,
st->peer = peer;
st->start_us = time_us_32();
for (uint16_t i = 0; i < st->pipeline && st->sent < st->target; i++)
ping_rate_send_one(st);
st->cb_handle = net_add_frame_callback([st](std::span<const uint8_t> frame) -> bool {
ipv4::ip4_addr src_ip;
if (!icmp::parse_echo_reply(frame, src_ip, st->ping_id)) return false;
@@ -229,6 +229,9 @@ static void start_ping_rate(const responder& resp, uint16_t target,
static_cast<unsigned long>(elapsed_us / 1000));
st->resp.respond(ResponseTest{false, {msg}});
});
for (uint16_t i = 0; i < st->pipeline && st->sent < st->target; i++)
ping_rate_send_one(st);
},
[resp]() {
resp.respond(ResponseTest{false, {"no peer found"}});