02-udp.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "limbo/errc.h"
  2. #include "limbo/ip/state.hpp"
  3. #include "limbo/udp/state.hpp"
  4. #include "test-utils.h"
  5. using namespace limbo;
  6. using IpState = ip::State<void>;
  7. using IpContext = typename IpState::Context;
  8. using State = udp::State<IpState>;
  9. using Context = typename State::Context;
  10. using Packet = typename State::Packet;
  11. static_assert(!details::has_lower_state_v<IpState>, "check0");
  12. static_assert(details::has_lower_state_v<State>, "check1");
  13. static_assert(std::is_same_v<typename Context::LowerContext, IpContext>,
  14. "check2");
  15. uint8_t example_raw[]{0x14, 0xe9, 0x14, 0xe9, 0x00, 0x24, 0x00, 0x00, 0x00,
  16. 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  17. 0x00, 0x00, 0x04, 0x77, 0x70, 0x61, 0x64, 0x05, 0x6c,
  18. 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x01};
  19. auto example_chunk = Chunk(example_raw, sizeof(example_raw));
  20. uint8_t payload[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  21. 0x00, 0x00, 0x04, 0x77, 0x70, 0x61, 0x64, 0x05, 0x6c, 0x6f,
  22. 0x63, 0x61, 0x6c, 0x00, 0x00, 0x01, 0x00, 0x01};
  23. auto payload_chunk = Chunk(payload, sizeof(payload));
  24. auto src = make_address("10.0.31.124");
  25. auto dst = make_address("224.0.0.251");
  26. TEST_CASE("send", "[udp]") {
  27. char buff[8 + sizeof(payload)];
  28. auto ip_ctx = IpContext{src, dst, 1, ip::Proto::udp, 0, nullptr};
  29. auto ctx = Context{5353, 5353, &ip_ctx};
  30. auto state = State{};
  31. SECTION("no enough space") {
  32. auto zero_chunk = Chunk(buff, 0);
  33. auto result = Packet::send(state, ctx, zero_chunk, payload_chunk);
  34. REQUIRE(!result);
  35. CHECK(result.state() == &state);
  36. CHECK(result.error_code() == (uint32_t)Errc::no_enough_space);
  37. }
  38. auto buff_chunk = Chunk(buff, example_chunk.size());
  39. auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
  40. REQUIRE(result);
  41. auto res_buff = result.consumed();
  42. CHECK((void *)res_buff.data() == (void *)buff);
  43. CHECK(res_buff.size() == example_chunk.size());
  44. CHECK(res_buff == example_chunk);
  45. }
  46. TEST_CASE("recv", "[udp]") {
  47. auto ip_state = IpState();
  48. auto state = State{};
  49. auto result = state.recv(example_chunk, &ip_state);
  50. REQUIRE(result);
  51. CHECK(result.state() == &state);
  52. CHECK(result.consumed() == example_chunk);
  53. auto &packet = state.get_parsed();
  54. CHECK(packet.source_port == 5353);
  55. CHECK(packet.dest_port == 5353);
  56. CHECK(packet.length == example_chunk.size());
  57. CHECK(packet.checksum == 0);
  58. CHECK(packet.container == &ip_state.get_parsed());
  59. CHECK(packet.payload == payload_chunk);
  60. }
  61. TEST_CASE("recv/incomplete", "[udp]") {
  62. auto ip_state = IpState();
  63. auto state = State{};
  64. auto empty_chunk = Chunk(example_raw, 0);
  65. SECTION("less then header sz") {
  66. auto result = state.recv(Chunk(example_raw, 6), &ip_state);
  67. CHECK(result);
  68. CHECK(result.consumed() == empty_chunk);
  69. CHECK(result.demand() == 2);
  70. }
  71. SECTION("incomplete payload") {
  72. auto chunk = Chunk(example_raw, example_chunk.size() - 1);
  73. auto result = state.recv(chunk, &ip_state);
  74. CHECK(result);
  75. CHECK(result.consumed() == empty_chunk);
  76. CHECK(result.demand() == 1);
  77. }
  78. }
  79. TEST_CASE("checksums", "[udp]") {
  80. using State = udp::State<IpState, udp::Opts::validate_checksum>;
  81. uint8_t example_raw[]{0x00, 0x14, 0x00, 0x0a, 0x00,
  82. 0x0A, 0x35, 0xC5, 0x48, 0x69};
  83. auto example_chunk = Chunk(example_raw, sizeof(example_raw));
  84. auto ip_state = IpState();
  85. auto &ip = ip_state.get_parsed();
  86. ip.source = ip::IPv4Address::from_native(0xC0A8001F);
  87. ip.destination = ip::IPv4Address::from_native(0xC0A8001E);
  88. auto state = State();
  89. auto result = state.recv(example_chunk, &ip_state);
  90. REQUIRE(result);
  91. CHECK(result.state() == &state);
  92. CHECK(result.consumed() == example_chunk);
  93. }
  94. TEST_CASE("send/recv + checksum", "[udp]") {
  95. constexpr auto opts =
  96. udp::Opts::calculate_checksum | udp::Opts::validate_checksum;
  97. using IpState = ip::State<void>;
  98. using IpContext = typename IpState::Context;
  99. using State = udp::State<IpState, opts>;
  100. using Context = typename State::Context;
  101. using Packet = typename State::Packet;
  102. auto ip_state = IpState();
  103. char buff[8 + sizeof(payload)];
  104. auto ip_ctx = IpContext{src, dst, 1, ip::Proto::udp, 0, nullptr};
  105. auto ctx = Context{5353, 5353, &ip_ctx};
  106. auto state = State{};
  107. auto buff_chunk = Chunk(buff, example_chunk.size());
  108. auto result = Packet::send(state, ctx, buff_chunk, payload_chunk);
  109. REQUIRE(result);
  110. auto res_buff = result.consumed();
  111. CHECK((void *)res_buff.data() == (void *)buff);
  112. CHECK(res_buff.size() == example_chunk.size());
  113. /* needed for correct pseudo header calculation */
  114. ip_state.init(0x6155);
  115. auto &ip_packet = ip_state.get_parsed();
  116. ip_packet.source = src;
  117. ip_packet.destination = dst;
  118. result = state.recv(buff_chunk, &ip_state);
  119. REQUIRE(result);
  120. CHECK(result.state() == &state);
  121. }