Communication Library for Autonomous Systems v1.0
Reliable and secure communication library for autonomous vehicle systems
Loading...
Searching...
No Matches
protocol.h
Go to the documentation of this file.
1#ifndef PROTOCOL_H
2#define PROTOCOL_H
4#include <string>
5#include <cstring>
6#include <chrono>
7#include <cstdint>
8#include <cstddef> // Ensure this is included for offsetof
9#include <stdexcept> // Ensure this is included for std::invalid_argument
10#include <cstdio> // For snprintf in debug logging
11#include <algorithm> // For std::any_of
12#include <mutex> // For std::mutex and std::lock_guard
13
14#include "api/traits.h"
15#include "api/util/debug.h"
16#include "api/util/observed.h"
19#include "api/framework/clock.h" // Include Clock for timestamping
20#include "api/framework/location_service.h" // Include LocationService
21#include "api/util/geo_utils.h" // Include GeoUtils
22#include "api/network/message.h"
24#include "api/framework/vehicleRSUManager.h" // Full definition for VehicleRSUManager
25
26// Protocol implementation that works with the real Communicator
27template <typename NIC>
28class Protocol: private NIC::Observer
29{
30 public:
32
33 typedef typename NIC::DataBuffer Buffer;
35 typedef std::uint16_t Port;
37
38 // Change to use Concurrent_Observer for Communicator interactions
41
42 // Header class for protocol messages
43 class Header {
44 public:
45 Header() : _from_port(0), _to_port(0), _size(0) {}
46
47 Port from_port() const { return _from_port; }
48 void from_port(Port p) { _from_port = p; }
49
50 Port to_port() const { return _to_port; }
51 void to_port(Port p) { _to_port = p; }
52
53 unsigned int size() const { return _size; }
54 void size(unsigned int s) { _size = s; }
55
56 private:
57 Port _from_port;
58 Port _to_port;
59 unsigned int _size;
60 };
61
62 // Timestamp fields structure for NIC-level timestamping
64 bool is_clock_synchronized; // Clock synchronization status (filled by Protocol on send)
65 TimestampType tx_timestamp; // Filled by NIC on send
66
70 };
71
72 // MAC authentication field structure
74 MacKeyType mac; // Message Authentication Code for INTEREST/RESPONSE messages
75 bool has_mac; // Flag indicating if MAC is present and valid
76
78 mac.fill(0);
79 }
80 };
81
82 static const unsigned int MTU = NIC::MTU - sizeof(Header) - sizeof(TimestampFields) - sizeof(Coordinates) - sizeof(AuthenticationFields);
83 typedef std::uint8_t Data[MTU];
84
85 // Packet class that includes header, timestamp fields, coordinates, and data
86 class Packet: public Header {
87 public:
88 Packet() {}
89
90 Header* header() { return this; }
91
93 return reinterpret_cast<TimestampFields*>(
94 reinterpret_cast<uint8_t*>(this) + sizeof(Header)
95 );
96 }
97
99 return reinterpret_cast<Coordinates*>(
100 reinterpret_cast<uint8_t*>(this) + sizeof(Header) + sizeof(TimestampFields)
101 );
102 }
103
105 return reinterpret_cast<AuthenticationFields*>(
106 reinterpret_cast<uint8_t*>(this) + sizeof(Header) + sizeof(TimestampFields) + sizeof(Coordinates)
107 );
108 }
109
110 template<typename T>
111 T* data() {
112 return reinterpret_cast<T*>(
113 reinterpret_cast<uint8_t*>(this) + sizeof(Header) + sizeof(TimestampFields) + sizeof(Coordinates) + sizeof(AuthenticationFields)
114 );
115 }
116
117 // Calculate offset to timestamp fields from start of packet
118 static constexpr unsigned int sync_status_offset() {
119 return sizeof(Header) + offsetof(TimestampFields, is_clock_synchronized);
120 }
121
122 static constexpr unsigned int tx_timestamp_offset() {
123 return sizeof(Header) + offsetof(TimestampFields, tx_timestamp);
124 }
125
126 private:
127 Data _data;
128 // Note: Actual timestamp fields, coordinates, and data are accessed via pointers
129 // to maintain proper memory layout
131
132 // Address class for Protocol layer
134 {
135 public:
136 enum Null { NULL_VALUE };
137
138 public:
142
144 const Physical_Address& paddr() const;
145
147 const Port& port() const;
148
149 const std::string to_string() const;
150
151 static const Address BROADCAST;
152
153 operator bool() const;
154 bool operator==(const Address& a) const;
155
156 private:
157 Port _port;
158 Physical_Address _paddr;
159 };
160
161 enum class EntityType { VEHICLE, RSU, UNKNOWN };
162
163 // Modified constructor
165
166 // New method to set entity manager (only for vehicles)
168
170
171 int send(Address from, Address to, const void* data, unsigned int size);
172 int receive(Buffer* buf, Address *from, void* data, unsigned int size);
173
174 // Method to free a buffer, crucial for Communicator to prevent leaks
176
177 // Method to set NIC transmission radius
178 void setRadius(double radius);
179
180 // Neighbor RSU management (for RSUs only)
181 void add_neighbor_rsu(unsigned int rsu_id, const MacKeyType& key, const Address& address);
183
184 // Get Protocol's own address
185 Address address() const;
186
187 static void attach(Observer* obs, Address address);
188 static void detach(Observer* obs, Address address);
189
190 private:
191 void update(typename NIC::Protocol_Number prot, Buffer * buf) override;
192 void handle_status_message(const typename ProtocolMessage::Type& msg_type,
193 const uint8_t* message_data, unsigned int payload_size,
195 const TimestampFields* timestamps,
196 const typename NIC::Address& sender_mac);
197
198 void handle_req_message(const uint8_t* message_data, unsigned int payload_size,
199 const typename NIC::Address& sender_mac);
200
201 void handle_resp_message(const uint8_t* message_data, unsigned int payload_size);
202
203 void send_req_message_to_leader(const void* failed_message_data, unsigned int failed_message_size,
204 const MacKeyType& failed_mac, const Header* failed_header,
205 const TimestampFields* failed_timestamps, const Coordinates* failed_coordinates);
206
207 // MAC authentication methods - Hybrid approach (message + packet fields)
208 MacKeyType calculate_mac(const void* message_data, unsigned int message_size,
209 const Header* header, const TimestampFields* timestamps,
210 const Coordinates* coordinates, const MacKeyType& key);
211 bool verify_mac(const void* message_data, unsigned int message_size,
212 const Header* header, const TimestampFields* timestamps,
214 bool requires_authentication(const void* data, unsigned int size);
215 bool is_authenticated_message_type(typename ProtocolMessage::Type type);
216
217 private:
218 // Neighbor RSU information for RSUs (used when handling REQ messages)
219 struct NeighborRSUInfo {
220 unsigned int rsu_id;
221 MacKeyType key;
222 Address address;
223
224 NeighborRSUInfo(unsigned int id, const MacKeyType& k, const Address& addr)
225 : rsu_id(id), key(k), address(addr) {}
226 };
227 std::vector<NeighborRSUInfo> _neighbor_rsus; // Only used by RSUs
228 std::mutex _neighbor_rsus_mutex; // Thread safety for neighbor RSUs
229
230 NIC* _nic;
231 static Observed _observed;
232 EntityType _entity_type;
233 VehicleRSUManager<Protocol<NIC>>* _vehicle_rsu_manager; // nullptr for RSUs
234};
235
236/******** Protocol::Address Implementation ******/
237template <typename NIC>
238Protocol<NIC>::Address::Address() : _port(0), _paddr(NIC::NULL_ADDRESS) {}
239
240template <typename NIC>
241Protocol<NIC>::Address::Address(const Null& null) : _port(0), _paddr(NIC::NULL_ADDRESS) {}
242
243template <typename NIC>
244Protocol<NIC>::Address::Address(Physical_Address paddr, Port port) : _port(port), _paddr(paddr) {}
245
246template <typename NIC>
250
251template <typename NIC>
253 return _paddr;
254}
255
256template <typename NIC>
258 _port = port;
259}
260
261template <typename NIC>
263 return _port;
264}
265
266template <typename NIC>
268 return _port != 0 || _paddr != Physical_Address();
269}
270
271template <typename NIC>
273 return (_paddr == a._paddr) && (_port == a._port);
274}
275
276template <typename NIC>
277const std::string Protocol<NIC>::Address::to_string() const {
278 std::string mac_addr = NIC::mac_to_string(_paddr);
279 return mac_addr + ":" + std::to_string(_port);
280}
281
282/********* Protocol Implementation *********/
283template <typename NIC>
285 : NIC::Observer(PROTO), _nic(nic), _entity_type(entity_type), _vehicle_rsu_manager(nullptr) {
286 if (!nic) {
287 throw std::invalid_argument("NIC pointer cannot be null");
288 }
289 _nic->attach(this, PROTO);
290 db<Protocol>(INF) << "[Protocol] created for "
291 << (entity_type == EntityType::VEHICLE ? "VEHICLE" :
292 entity_type == EntityType::RSU ? "RSU" : "UNKNOWN") << "\n";
293}
294
295template <typename NIC>
297 _nic->detach(this, PROTO);
298 db<Protocol>(INF) << "[Protocol] detached from NIC\n";
299}
300
301template <typename NIC>
302int Protocol<NIC>::send(Address from, Address to, const void* data, unsigned int size) {
303 db<Protocol>(TRC) << "Protocol<NIC>::send() called!\n";
304
305 if (!data || size == 0) {
306 db<Protocol>(WRN) << "[Protocol] SEND - Invalid data or size. Dropping message.\n";
307 return 0; // Or a specific error code
308 }
309
310 if (!_nic) {
311 db<Protocol>(TRC) << "Protocol<NIC>::send() called after release!\n";
312 return 0;
313 }
314
315 // DEBUG: Show what message we're trying to send
316 if (size > 0) {
317 const uint8_t* msg_bytes = static_cast<const uint8_t*>(data);
319 const char* type_name = "UNKNOWN";
320 switch (static_cast<typename ProtocolMessage::Type>(msg_type)) {
321 case ProtocolMessage::Type::RESPONSE: type_name = "RESPONSE"; break;
322 case ProtocolMessage::Type::INTEREST: type_name = "INTEREST"; break;
323 case ProtocolMessage::Type::STATUS: type_name = "STATUS"; break;
324 case ProtocolMessage::Type::REQ: type_name = "REQ"; break;
325 case ProtocolMessage::Type::KEY_RESPONSE: type_name = "KEY_RESPONSE"; break;
326 default: type_name = "OTHER"; break;
327 }
328 db<Protocol>(INF) << "[Protocol] SEND - Message type: " << static_cast<int>(msg_type)
329 << " (" << type_name << "), size: " << size << " bytes\n";
330 }
331
332 // Check if message requires authentication and we have the necessary keys
333 if (requires_authentication(data, size)) {
334 db<Protocol>(INF) << "[Protocol] SEND - Message requires authentication - checking key availability\n";
335
336 bool has_auth_keys = false;
337
338 if (_entity_type == EntityType::VEHICLE) {
339 // For vehicles: check if we have any known RSUs (leaders)
340 if (_vehicle_rsu_manager) {
341 auto known_rsus = _vehicle_rsu_manager->get_known_rsus();
342 has_auth_keys = !known_rsus.empty();
343 db<Protocol>(INF) << "[Protocol] SEND - Vehicle has " << known_rsus.size() << " known RSUs for authentication\n";
344
345 // DEBUG: Show which RSUs are known and their keys
346 for (size_t i = 0; i < known_rsus.size(); ++i) {
347 std::string rsu_key_hex = "";
348 for (size_t j = 0; j < 16; ++j) {
349 char hex_byte[4];
350 snprintf(hex_byte, sizeof(hex_byte), "%02X ", known_rsus[i].group_key[j]);
352 }
353 db<Protocol>(INF) << "[Protocol] SEND - Known RSU " << i << " (" << known_rsus[i].address.to_string()
354 << ") key: " << rsu_key_hex << "\n";
355 }
356 } else {
357 db<Protocol>(WRN) << "[Protocol] SEND - Vehicle has no RSU manager - no authentication possible\n";
358 }
359 } else {
360 // For RSUs: check if we have a valid leader key (not all zeros)
362 has_auth_keys = std::any_of(leader_key.begin(), leader_key.end(), [](uint8_t b) { return b != 0; });
363
364 std::string leader_key_hex = "";
365 for (size_t i = 0; i < 16; ++i) {
366 char hex_byte[4];
367 snprintf(hex_byte, sizeof(hex_byte), "%02X ", leader_key[i]);
369 }
370 db<Protocol>(INF) << "[Protocol] SEND - RSU leader key: " << leader_key_hex
371 << " (valid: " << (has_auth_keys ? "YES" : "NO") << ")\n";
372 }
373
374 if (!has_auth_keys) {
375 db<Protocol>(WRN) << "[Protocol] SEND - DROPPING authenticated message - no authentication keys available\n";
376 return 0; // Drop the message
377 }
378
379 db<Protocol>(INF) << "[Protocol] SEND - Authentication keys available - proceeding with message send\n";
380 } else {
381 db<Protocol>(INF) << "[Protocol] SEND - Message does NOT require authentication\n";
382 }
383
384 // Allocate buffer for the entire frame -> NIC alloc adds Frame Header size (this is better for independency)
385 unsigned int packet_size = size + sizeof(Header) + sizeof(TimestampFields) + sizeof(Coordinates) + sizeof(AuthenticationFields);
386 Buffer* buf = _nic->alloc(to.paddr(), PROTO, packet_size);
387
388 // Get pointer to where Protocol packet starts (within the Ethernet payload)
389 // Assumes buf->data() returns Ethernet::Frame* and payload follows header
390 Packet* packet = reinterpret_cast<Packet*>(buf->data()->payload);
391
392 // Set up Protocol Packet Header
393 packet->from_port(from.port());
394 packet->to_port(to.port());
395 packet->size(size); // Set the size of the *user data*
396
397 // Copy user data into the packet's data section
398 std::memcpy(packet->template data<void>(), data, size);
399
400 // Set clock synchronization status in the packet
401 auto& clock = Clock::getInstance();
402 bool sync_status;
403 clock.getSynchronizedTime(&sync_status); // We only need the status
404 packet->timestamps()->is_clock_synchronized = sync_status;
405
406 // TX timestamp will be set by NIC during transmission - not used in MAC calculation
407 packet->timestamps()->tx_timestamp = TimestampType::min(); // Will be overwritten by NIC
408
409 // Set sender location and communication radius
411 coords.radius = _nic->radius();
413 std::memcpy(packet->coordinates(), &coords, sizeof(Coordinates));
414
415 // Initialize authentication fields
416 packet->authentication()->has_mac = false;
417 packet->authentication()->mac.fill(0);
418
419 // Calculate MAC for INTEREST and RESPONSE messages
420 if (requires_authentication(data, size)) {
421 db<Protocol>(INF) << "[Protocol] SEND - Calculating Hybrid MAC for authenticated message\n";
422
423 // Get leader key from storage
425
426 // DEBUG: Show packet fields being authenticated
427 db<Protocol>(INF) << "[Protocol] SEND - MAC Auth Header: from_port=" << packet->header()->from_port()
428 << ", to_port=" << packet->header()->to_port() << ", size=" << packet->header()->size() << "\n";
429 db<Protocol>(INF) << "[Protocol] SEND - MAC Auth Coordinates: x=" << packet->coordinates()->x
430 << ", y=" << packet->coordinates()->y << ", radius=" << packet->coordinates()->radius << "\n";
431
432 // DEBUG: Show key being used
433 std::string key_hex = "";
434 for (size_t i = 0; i < 16; ++i) {
435 char hex_byte[4];
436 snprintf(hex_byte, sizeof(hex_byte), "%02X ", leader_key[i]);
437 key_hex += hex_byte;
438 }
439 db<Protocol>(INF) << "[Protocol] SEND - MAC Auth Key: " << key_hex << "\n";
440
441 // Calculate MAC over the message payload + packet fields (hybrid approach)
442 MacKeyType calculated_mac = calculate_mac(data, size, packet->header(),
443 packet->timestamps(), packet->coordinates(), leader_key);
444
445 // DEBUG: Show calculated MAC
446 std::string mac_hex = "";
447 for (size_t i = 0; i < 16; ++i) {
448 char hex_byte[4];
449 snprintf(hex_byte, sizeof(hex_byte), "%02X ", calculated_mac[i]);
450 mac_hex += hex_byte;
451 }
452 db<Protocol>(INF) << "[Protocol] SEND - Final calculated MAC: " << mac_hex << "\n";
453
454 // Set MAC in packet
455 packet->authentication()->mac = calculated_mac;
456 packet->authentication()->has_mac = true;
457
458 db<Protocol>(INF) << "[Protocol] SEND - Added MAC authentication to outgoing packet\n";
459 } else {
460 db<Protocol>(INF) << "[Protocol] SEND - No authentication required - MAC left as zeros\n";
461 }
462
463 // Send the packet via NIC, passing the packet size for timestamp offset calculation
464 int result = _nic->send(buf, packet_size); // Pass packet size to NIC
465 db<Protocol>(INF) << "[Protocol] SEND - NIC::send() returned " << result << ", clock_synchronized=" << packet->timestamps()->is_clock_synchronized << "\n";
466
467 // NIC should release buffer after use
468 return result;
469}
470
471template <typename NIC>
472int Protocol<NIC>::receive(Buffer* buf, Address *from, void* data, unsigned int size) {
473 db<Protocol>(TRC) << "Protocol<NIC>::receive() called!\n";
474
475 if (!buf) {
476 db<Protocol>(WRN) << "[Protocol] receive() called with a null buffer.\n";
477 return -1;
478 }
479
480 typename NIC::Address src_mac;
481 typename NIC::Address dst_mac;
482
483 std::uint8_t temp_buffer[size + sizeof(Header) + sizeof(TimestampFields) + sizeof(Coordinates) + sizeof(AuthenticationFields)];
484
485 if (!_nic) {
486 db<Protocol>(TRC) << "Protocol<NIC>::receive() called after release!\n";
487 return -1;
488 }
489
490 int packet_size = _nic->receive(buf, &src_mac, &dst_mac, temp_buffer, NIC::MTU);
491 db<Protocol>(INF) << "[Protocol] NIC::receive() returned " << packet_size << ".\n";
492
493 if (packet_size <= 0) {
494 db<Protocol>(WRN) << "[Protocol] No data received or error occurred.\n";
495 return -1; // No data received or error
496 }
497
498 // Reinterpretation as packet
499 Packet* pkt = reinterpret_cast<Packet*>(temp_buffer);
500
501 if (from) {
502 from->paddr(src_mac);
503 from->port(pkt->header()->from_port());
504 }
505
506 // Payload size (accounting for Coordinates and AuthenticationFields)
507 int payload_size = packet_size - sizeof(Header) - sizeof(TimestampFields) - sizeof(Coordinates) - sizeof(AuthenticationFields);
508
509 // Copies only useful data
510 std::memcpy(data, pkt->template data<void>(), payload_size);
511
512 db<Protocol>(INF) << "[Protocol] received packet from " << Ethernet::mac_to_string(src_mac) << " to " << Ethernet::mac_to_string(dst_mac) << " with size " << packet_size << "\n";
513
514 return payload_size;
515}
516
517template <typename NIC>
519 _observed.attach(obs, address.port());
520 db<Protocol>(INF) << "[Protocol] Attached observer to port " << address.port() << "\n";
521}
522
523template <typename NIC>
525 _observed.detach(obs, address.port());
526 db<Protocol>(INF) << "[Protocol] Detached observer from port " << address.port() << "\n";
527}
528
529template <typename NIC>
531 db<Protocol>(TRC) << "Protocol<NIC>::update() called!\n";
532
533 if (!buf) {
534 db<Protocol>(INF) << "[Protocol] data received, but buffer is null. Releasing buffer.\n";
535 return;
536 }
537
538 Packet* pkt = reinterpret_cast<Packet*>(buf->data()->payload);
539
540 // Radius-based collision domain filtering - FIRST CHECK
541 Coordinates* coords = pkt->coordinates();
542 // Get receiver location
543 double rx_x, rx_y;
545 // Check if packet is within sender's communication range
547 if (distance > coords->radius) {
548 db<Protocol>(INF) << "[Protocol] Packet dropped: out of range (" << distance << "m > " << coords->radius << "m)\n";
549 free(buf);
550 return;
551 }
552
553 // RSU message filtering - drop INTEREST, RESPONSE, STATUS, and KEY_RESPONSE messages for RSUs ONLY
554 int payload_size = buf->size() - Ethernet::HEADER_SIZE - sizeof(Header) - sizeof(TimestampFields) - sizeof(Coordinates) - sizeof(AuthenticationFields);
555 if (_entity_type == EntityType::RSU && payload_size > 0) {
556 const uint8_t* message_data = pkt->template data<uint8_t>();
557 if (payload_size >= 1) {
559
560 if (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::INTEREST) ||
561 raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::RESPONSE) ||
562 raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::STATUS) ||
563 raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::KEY_RESPONSE)) {
564
565 const char* msg_type_str = (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::INTEREST)) ? "INTEREST" :
566 (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::RESPONSE)) ? "RESPONSE" :
567 (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::STATUS)) ? "STATUS" : "KEY_RESPONSE";
568
569 db<Protocol>(INF) << "[Protocol] RSU dropping " << msg_type_str << " message - not intended for RSUs\n";
570 free(buf);
571 return;
572 }
573 }
574 }
575
576 // Extract timestamps and update Clock if this is a PTP-relevant message
577 TimestampFields* timestamps = pkt->timestamps();
578 db<Protocol>(INF) << "[Protocol] Received packet with sender_clock_synchronized="
579 << timestamps->is_clock_synchronized << "\n";
580 TimestampType rx_timestamp(std::chrono::microseconds(buf->rx()));
581 typename NIC::Address src_mac = buf->data()->src;
583 ptp_data.sender_id = static_cast<LeaderIdType>(src_mac.bytes[5]);
584 ptp_data.ts_tx_at_sender = timestamps->tx_timestamp;
585 ptp_data.ts_local_rx = rx_timestamp;
586 auto& clock = Clock::getInstance();
587 clock.activate(&ptp_data);
588
589 // Authentication verification for INTEREST and RESPONSE messages
590 if (payload_size > 0) {
591 const uint8_t* message_data = pkt->template data<uint8_t>();
592 if (payload_size >= 1) {
594
595 // Check if this message type requires authentication
596 auto msg_type = static_cast<typename ProtocolMessage::Type>(raw_msg_type);
597
598 if (is_authenticated_message_type(msg_type)) {
599
600 // Verify MAC authentication (hybrid approach: message + packet fields)
601 // Note: TX timestamp is excluded from MAC calculation for architectural cleanliness
602 if (!verify_mac(message_data, payload_size, pkt->header(),
603 pkt->timestamps(), pkt->coordinates(), pkt->authentication()->mac)) {
604 db<Protocol>(WRN) << "[Protocol] Hybrid MAC verification failed - packet may be tampered\n";
605
606 // For vehicles: Send REQ message to leader RSU instead of just dropping
607 if (_entity_type == EntityType::VEHICLE && _vehicle_rsu_manager) {
608 db<Protocol>(INF) << "[Protocol] Sending REQ message to leader RSU for failed authentication\n";
609 send_req_message_to_leader(message_data, payload_size, pkt->authentication()->mac,
610 pkt->header(), pkt->timestamps(), pkt->coordinates());
611 } else {
612 db<Protocol>(INF) << "[Protocol] RSU dropping message with failed MAC\n";
613 }
614
615 free(buf);
616 return;
617 }
618
619 db<Protocol>(INF) << "[Protocol] Hybrid MAC verification successful - packet integrity confirmed\n";
620 }
621
622 // STATUS message interception (no authentication required)
623 if (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::STATUS)) {
624 db<Protocol>(INF) << "[Protocol] Intercepted STATUS message\n";
625 auto msg_type = static_cast<typename ProtocolMessage::Type>(raw_msg_type);
626 handle_status_message(msg_type, message_data, payload_size, pkt->coordinates(), pkt->timestamps(), buf->data()->src);
627 free(buf);
628 return;
629 }
630
631 // REQ message interception (for RSUs only, no authentication required)
632 if (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::REQ) && _entity_type == EntityType::RSU) {
633 db<Protocol>(INF) << "[Protocol] Intercepted REQ message at RSU\n";
634 handle_req_message(message_data, payload_size, buf->data()->src);
635 free(buf);
636 return;
637 }
638
639 // KEY_RESPONSE message interception (for vehicles only, no authentication required)
640 if (raw_msg_type == static_cast<uint8_t>(ProtocolMessage::Type::KEY_RESPONSE) && _entity_type == EntityType::VEHICLE) {
641 db<Protocol>(INF) << "[Protocol] Intercepted KEY_RESPONSE message at vehicle\n";
642 handle_resp_message(message_data, payload_size);
643 free(buf);
644 return;
645 }
646 }
647 }
648
649 // For non-STATUS messages, continue normal flow
650 if (!Protocol::_observed.notify(buf)) {
651 db<Protocol>(INF) << "[Protocol] data received, but no one was notified for port. Releasing buffer.\n";
652 free(buf);
653 }
654 db<Protocol>(INF) << "[Protocol] data received, notify succeeded.\n";
655}
656
657// STATUS message handler
658
659template <typename NIC>
660void Protocol<NIC>::handle_status_message(const typename ProtocolMessage::Type& msg_type,
661 const uint8_t* message_data, unsigned int payload_size,
663 const TimestampFields* timestamps,
664 const typename NIC::Address& sender_mac) {
665 db<Protocol>(INF) << "[Protocol] Processing STATUS message from "
667 // Only vehicles process STATUS messages from RSUs
668 if (_entity_type != EntityType::VEHICLE || !_vehicle_rsu_manager) {
669 db<Protocol>(INF) << "[Protocol] Ignoring STATUS message (not a vehicle or no RSU manager)\n";
670 return;
671 }
672
673 // Deserialize the STATUS message to extract payload
674 ProtocolMessage status_msg = ProtocolMessage::deserialize(message_data, payload_size);
675 if (status_msg.message_type() != ProtocolMessage::Type::STATUS) {
676 db<Protocol>(WRN) << "[Protocol] Failed to deserialize STATUS message\n";
677 return;
678 }
679
680 // Extract RSU information from STATUS message payload
681 const uint8_t* payload = status_msg.value();
682 unsigned int value_size = status_msg.value_size();
683 if (value_size < (sizeof(double) * 3 + sizeof(MacKeyType))) {
684 db<Protocol>(WRN) << "[Protocol] STATUS message payload too small: " << value_size << "\n";
685 return;
686 }
687
688 // Debug: print out the HEX for the payload
689 std::string payload_hex = "";
690 for (size_t i = 0; i < value_size; ++i) {
691 char hex_byte[4];
692 snprintf(hex_byte, sizeof(hex_byte), "%02X ", message_data[i]);
694 }
695 db<Protocol>(INF) << "[Protocol] STATUS message payload: " << payload_hex << "\n";
696
697 // Parse payload
698 unsigned int offset = 0;
699 double rsu_x, rsu_y, rsu_radius;
701 std::memcpy(&rsu_x, payload + offset, sizeof(double));
702 offset += sizeof(double);
703 std::memcpy(&rsu_y, payload + offset, sizeof(double));
704 offset += sizeof(double);
705 std::memcpy(&rsu_radius, payload + offset, sizeof(double));
706 offset += sizeof(double);
707 std::memcpy(&rsu_key, payload + offset, sizeof(MacKeyType));
708
709 // Create Protocol address for the RSU
710 Address rsu_address(sender_mac, status_msg.origin().port());
711
712 // Forward to RSU manager - this will be linked at compile time when VehicleRSUManager is fully defined
713 if (_vehicle_rsu_manager) {
714 _vehicle_rsu_manager->process_rsu_status(rsu_address, rsu_x, rsu_y, rsu_radius, rsu_key);
715 db<Protocol>(INF) << "[Protocol] Forwarded RSU info to manager: x=" << rsu_x
716 << ", y=" << rsu_y << ", radius=" << rsu_radius << "\n";
717 }
718}
719
720// Implementation for the new free method
721template <typename NIC>
723 if (_nic) {
724 _nic->free(buf);
725 }
726}
727
728// Implementation for setRadius method
729template <typename NIC>
730void Protocol<NIC>::setRadius(double radius) {
731 if (_nic) {
732 _nic->setRadius(radius);
733 db<Protocol>(INF) << "[Protocol] NIC transmission radius set to " << radius << "m\n";
734 }
735}
736
737// MAC Authentication Implementation - Hybrid Approach
738template <typename NIC>
740 const Header* header, const TimestampFields* timestamps,
741 const Coordinates* coordinates, const MacKeyType& key) {
743 result.fill(0);
744
745 // Create a buffer containing all authenticated fields in deterministic order
746 std::vector<uint8_t> auth_data;
747 unsigned int total_size = 0;
748
749 // 1. Add Header fields (from_port, to_port - excluding size to avoid circular dependency)
750 unsigned int header_auth_size = sizeof(Port) * 2; // from_port + to_port
752
753 // 2. Add TimestampFields (only sync status, exclude tx_timestamp for architectural cleanliness)
754 unsigned int timestamp_auth_size = sizeof(bool); // Only is_clock_synchronized
756
757 // 3. Add Coordinates (full structure for location integrity)
758 unsigned int coords_auth_size = sizeof(Coordinates);
760
761 // 4. Add message payload
763
764 // Allocate buffer for all authenticated data
765 auth_data.resize(total_size);
766 unsigned int offset = 0;
767
768 // Serialize Header fields
769 Port from_port = header->from_port();
770 Port to_port = header->to_port();
771 std::memcpy(auth_data.data() + offset, &from_port, sizeof(Port));
772 offset += sizeof(Port);
773 std::memcpy(auth_data.data() + offset, &to_port, sizeof(Port));
774 offset += sizeof(Port);
775
776 // Serialize TimestampFields (only sync status, exclude tx_timestamp)
777 bool sync_status = timestamps->is_clock_synchronized;
778 std::memcpy(auth_data.data() + offset, &sync_status, sizeof(bool));
779 offset += sizeof(bool);
780 // Note: tx_timestamp is intentionally excluded from MAC calculation
781
782 // Serialize Coordinates
783 std::memcpy(auth_data.data() + offset, coordinates, sizeof(Coordinates));
784 offset += sizeof(Coordinates);
785
786 // Serialize message payload
787 std::memcpy(auth_data.data() + offset, message_data, message_size);
788
789 // Debug logging: Show what's being authenticated
790 db<Protocol>(INF) << "[Protocol] Hybrid MAC - Authenticating " << total_size << " bytes total:\n";
791 db<Protocol>(INF) << "[Protocol] Hybrid MAC - Header: from_port=" << from_port
792 << ", to_port=" << to_port << " (" << header_auth_size << " bytes)\n";
793 db<Protocol>(INF) << "[Protocol] Hybrid MAC - Timestamps: sync=" << sync_status
794 << " (" << timestamp_auth_size << " bytes, tx_timestamp excluded)\n";
795 db<Protocol>(INF) << "[Protocol] Hybrid MAC - Coordinates: x=" << coordinates->x
796 << ", y=" << coordinates->y << ", radius=" << coordinates->radius
797 << " (" << coords_auth_size << " bytes)\n";
798 db<Protocol>(INF) << "[Protocol] Hybrid MAC - Message payload: " << message_size << " bytes\n";
799
800 // XOR-based MAC calculation on combined authenticated data
801 const uint8_t* combined_data = auth_data.data();
802 for (unsigned int i = 0; i < total_size; ++i) {
803 result[i % 16] ^= combined_data[i];
804 }
805
806 // XOR with the key
807 for (size_t i = 0; i < 16; ++i) {
808 result[i] ^= key[i];
809 }
810
811 // Debug logging: Show computed MAC
812 std::string computed_mac_hex = "";
813 for (size_t i = 0; i < 16; ++i) {
814 char hex_byte[4];
815 snprintf(hex_byte, sizeof(hex_byte), "%02X ", result[i]);
817 }
818 db<Protocol>(INF) << "[Protocol] Hybrid MAC - Computed MAC: " << computed_mac_hex << "\n";
819
820 return result;
821}
822
823template <typename NIC>
824bool Protocol<NIC>::verify_mac(const void* message_data, unsigned int message_size,
825 const Header* header, const TimestampFields* timestamps,
827 // Debug logging: Show received MAC
828 std::string received_mac_hex = "";
829 for (size_t i = 0; i < 16; ++i) {
830 char hex_byte[4];
831 snprintf(hex_byte, sizeof(hex_byte), "%02X ", received_mac[i]);
833 }
834 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Received MAC: " << received_mac_hex << "\n";
835
836 // Debug logging: Show packet fields being verified
837 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Header: from_port=" << header->from_port()
838 << ", to_port=" << header->to_port() << ", size=" << header->size() << "\n";
839 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Timestamps: sync=" << timestamps->is_clock_synchronized
840 << " (tx_timestamp excluded from MAC calculation)\n";
841 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Coordinates: x=" << coordinates->x
842 << ", y=" << coordinates->y << ", radius=" << coordinates->radius << "\n";
843 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Message payload size: " << message_size << " bytes\n";
844
845 // Debug logging: Show message data being verified
846 const uint8_t* msg_bytes = static_cast<const uint8_t*>(message_data);
847 std::string msg_hex = "";
848 for (unsigned int i = 0; i < std::min(message_size, 32u); ++i) { // Log first 32 bytes
849 char hex_byte[4];
850 snprintf(hex_byte, sizeof(hex_byte), "%02X ", msg_bytes[i]);
851 msg_hex += hex_byte;
852 }
853 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Message data (first " << std::min(message_size, 32u) << " bytes): " << msg_hex << "\n";
854
855 // For vehicles: Check MAC against all known RSU keys AND neighbor RSU keys
856 if (_entity_type == EntityType::VEHICLE && _vehicle_rsu_manager) {
857 auto known_rsus = _vehicle_rsu_manager->get_known_rsus();
858 auto neighbor_keys = _vehicle_rsu_manager->get_neighbor_rsu_keys();
859
860 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Vehicle checking against " << known_rsus.size()
861 << " known RSU keys and " << neighbor_keys.size() << " neighbor RSU keys\n";
862
863 // First check known RSUs
864 for (size_t idx = 0; idx < known_rsus.size(); ++idx) {
865 const auto& rsu = known_rsus[idx];
866
867 // Debug logging: Show RSU key being tested
868 std::string rsu_key_hex = "";
869 for (size_t i = 0; i < 16; ++i) {
870 char hex_byte[4];
871 snprintf(hex_byte, sizeof(hex_byte), "%02X ", rsu.group_key[i]);
873 }
874 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Testing known RSU " << idx << " (" << rsu.address.to_string() << ") key: " << rsu_key_hex << "\n";
875
877
878 // Debug logging: Show calculated MAC for this key
879 std::string calc_mac_hex = "";
880 for (size_t i = 0; i < 16; ++i) {
881 char hex_byte[4];
882 snprintf(hex_byte, sizeof(hex_byte), "%02X ", calculated_mac[i]);
884 }
885 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Known RSU " << idx << " calculated MAC: " << calc_mac_hex << "\n";
886
888 db<Protocol>(TRC) << "[Protocol] Hybrid MAC verified with known RSU " << rsu.address.to_string() << " key\n";
889 return true;
890 }
891 }
892
893 // Then check neighbor RSU keys
894 for (size_t idx = 0; idx < neighbor_keys.size(); ++idx) {
895 const auto& neighbor_key = neighbor_keys[idx];
896
897 // Debug logging: Show neighbor key being tested
898 std::string neighbor_key_hex = "";
899 for (size_t i = 0; i < 16; ++i) {
900 char hex_byte[4];
901 snprintf(hex_byte, sizeof(hex_byte), "%02X ", neighbor_key[i]);
903 }
904 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Testing neighbor RSU " << idx << " key: " << neighbor_key_hex << "\n";
905
907
908 // Debug logging: Show calculated MAC for this neighbor key
909 std::string calc_mac_hex = "";
910 for (size_t i = 0; i < 16; ++i) {
911 char hex_byte[4];
912 snprintf(hex_byte, sizeof(hex_byte), "%02X ", calculated_mac[i]);
914 }
915 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - Neighbor RSU " << idx << " calculated MAC: " << calc_mac_hex << "\n";
916
918 db<Protocol>(TRC) << "[Protocol] Hybrid MAC verified with neighbor RSU key " << idx << "\n";
919 return true;
920 }
921 }
922
923 db<Protocol>(TRC) << "[Protocol] Hybrid MAC verification failed - no matching RSU or neighbor key found\n";
924 return false;
925 }
926
927 // For RSUs: Check MAC against current leader key
929
930 // Debug logging: Show leader key being used
931 std::string leader_key_hex = "";
932 for (size_t i = 0; i < 16; ++i) {
933 char hex_byte[4];
934 snprintf(hex_byte, sizeof(hex_byte), "%02X ", leader_key[i]);
936 }
937 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - RSU checking with leader key: " << leader_key_hex << "\n";
938
940
941 // Debug logging: Show calculated MAC
942 std::string calc_mac_hex = "";
943 for (size_t i = 0; i < 16; ++i) {
944 char hex_byte[4];
945 snprintf(hex_byte, sizeof(hex_byte), "%02X ", calculated_mac[i]);
947 }
948 db<Protocol>(INF) << "[Protocol] Hybrid MAC Verify - RSU calculated MAC: " << calc_mac_hex << "\n";
949
951
952 db<Protocol>(TRC) << "[Protocol] Hybrid MAC verification " << (is_valid ? "successful" : "failed") << " with leader key\n";
953 return is_valid;
954}
955
956template <typename NIC>
957bool Protocol<NIC>::requires_authentication(const void* data, unsigned int size) {
958 if (size < 1) return false;
959
960 const uint8_t* message_bytes = static_cast<const uint8_t*>(data);
962
963 return is_authenticated_message_type(static_cast<typename ProtocolMessage::Type>(msg_type));
964}
965
966template <typename NIC>
967bool Protocol<NIC>::is_authenticated_message_type(typename ProtocolMessage::Type type) {
968 //return (type == ProtocolMessage::Type::INTEREST ||
969 // type == ProtocolMessage::Type::RESPONSE);
970
971 return (type == ProtocolMessage::Type::RESPONSE);
972}
973
974// REQ message handler implementation
975template <typename NIC>
977 const typename NIC::Address& sender_mac) {
978 db<Protocol>(INF) << "[Protocol] RSU processing REQ message from "
980
981 if (_entity_type != EntityType::RSU) {
982 db<Protocol>(WRN) << "[Protocol] Non-RSU entity received REQ message - ignoring\n";
983 return;
984 }
985
986 ProtocolMessage req_msg = ProtocolMessage::deserialize(message_data, payload_size);
987 if (req_msg.message_type() != ProtocolMessage::Type::REQ) {
988 db<Protocol>(WRN) << "[Protocol] Failed to deserialize REQ message\n";
989 return;
990 }
991
992 const uint8_t* req_payload = req_msg.value();
993 unsigned int req_value_size = req_msg.value_size();
994
995 // Expected payload size check
996 unsigned int min_payload_size = sizeof(Header) + sizeof(TimestampFields) + sizeof(Coordinates) + sizeof(MacKeyType);
998 db<Protocol>(WRN) << "[Protocol] REQ message payload too small: " << req_value_size << ", expected at least " << min_payload_size << "\n";
999 return;
1000 }
1001
1002 // Deserialize the REQ payload: [Header][Timestamps][Coordinates][OriginalMsg][FailedMAC]
1003 Header failed_header;
1004 TimestampFields failed_timestamps;
1007 unsigned int offset = 0;
1008
1009 std::memcpy(&failed_header, req_payload + offset, sizeof(Header));
1010 offset += sizeof(Header);
1011
1012 std::memcpy(&failed_timestamps, req_payload + offset, sizeof(TimestampFields));
1013 offset += sizeof(TimestampFields);
1014
1015 std::memcpy(&failed_coordinates, req_payload + offset, sizeof(Coordinates));
1016 offset += sizeof(Coordinates);
1017
1019
1020 // BUG FIX: Use the size from the deserialized header of the failed message.
1021 // This is more reliable than calculating from the REQ payload's total size,
1022 // which can be prone to errors from padding/sizeof inconsistencies across modules.
1023 unsigned int original_msg_size = failed_header.size();
1024
1025 // Defensive check: ensure the reported size doesn't exceed the actual payload buffer
1026 if ((offset + original_msg_size + sizeof(MacKeyType)) > req_value_size) {
1027 db<Protocol>(WRN) << "[Protocol] REQ payload validation failed: original message size (" << original_msg_size
1028 << ") from header is too large for the received REQ payload size (" << req_value_size << "). Dropping.\n";
1029 return;
1030 }
1031
1032 std::vector<uint8_t> msg(payload_size);
1033 std::memcpy(msg.data(), message_data, req_msg.value_size());
1034 // DEBUG: Show the failed MAC we're trying to match
1035 std::string msg_hex = "";
1036 for (size_t i = 0; i < payload_size; ++i) {
1037 char hex_byte[4];
1038 snprintf(hex_byte, sizeof(hex_byte), "%02X ", msg[i]);
1039 msg_hex += hex_byte;
1040 }
1041 db<Protocol>(INF) << "[Protocol] received message: " << msg_hex << "\n";
1042
1044 std::memcpy(failed_mac.data(), req_payload + offset, sizeof(MacKeyType));
1045
1046 // DEBUG: Show the failed MAC we're trying to match
1047 std::string failed_mac_hex = "";
1048 for (size_t i = 0; i < 16; ++i) {
1049 char hex_byte[4];
1050 snprintf(hex_byte, sizeof(hex_byte), "%02X ", failed_mac[i]);
1052 }
1053 db<Protocol>(INF) << "[Protocol] REQ - Failed MAC to match: " << failed_mac_hex << "\n";
1054
1055 // DEBUG: Show original message data details
1056 db<Protocol>(INF) << "[Protocol] REQ - Original message size: " << original_msg_size << " bytes\n";
1057 db<Protocol>(INF) << "[Protocol] REQ - Original header: from_port=" << failed_header.from_port()
1058 << ", to_port=" << failed_header.to_port() << ", size=" << failed_header.size() << "\n";
1059 db<Protocol>(INF) << "[Protocol] REQ - Original coordinates: x=" << failed_coordinates.x
1060 << ", y=" << failed_coordinates.y << ", radius=" << failed_coordinates.radius << "\n";
1061
1062 bool found_match = false;
1064 unsigned int matching_rsu_id = 0;
1065
1066 {
1067 std::lock_guard<std::mutex> lock(_neighbor_rsus_mutex);
1068 db<Protocol>(INF) << "[Protocol] REQ - Searching through " << _neighbor_rsus.size() << " neighbor RSUs for a matching key.\n";
1069 for (const auto& neighbor : _neighbor_rsus) {
1070 // DEBUG: Show each neighbor RSU key before testing
1071 std::string neighbor_key_hex = "";
1072 for (size_t i = 0; i < 16; ++i) {
1073 char hex_byte[4];
1074 snprintf(hex_byte, sizeof(hex_byte), "%02X ", neighbor.key[i]);
1076 }
1077 db<Protocol>(INF) << "[Protocol] REQ - Testing neighbor RSU " << neighbor.rsu_id << " key: " << neighbor_key_hex << "\n";
1078
1082
1083 // DEBUG: Show the calculated MAC for this neighbor
1084 std::string calc_mac_hex = "";
1085 for (size_t i = 0; i < 16; ++i) {
1086 char hex_byte[4];
1087 snprintf(hex_byte, sizeof(hex_byte), "%02X ", calculated_mac[i]);
1089 }
1090 db<Protocol>(INF) << "[Protocol] REQ - Neighbor RSU " << neighbor.rsu_id << " calculated MAC: " << calc_mac_hex << "\n";
1091
1092 if (calculated_mac == failed_mac) {
1093 matching_key = neighbor.key;
1094 matching_rsu_id = neighbor.rsu_id;
1095 found_match = true;
1096 db<Protocol>(INF) << "[Protocol] REQ - Found matching key from neighbor RSU " << neighbor.rsu_id << ".\n";
1097 break;
1098 } else {
1099 db<Protocol>(INF) << "[Protocol] REQ - No match for neighbor RSU " << neighbor.rsu_id << "\n";
1100 }
1101 }
1102 }
1103
1104 if (found_match) {
1105 Address vehicle_address(sender_mac, req_msg.origin().port());
1106 ProtocolMessage* resp_msg = new ProtocolMessage(ProtocolMessage::Type::KEY_RESPONSE,
1107 address(), 0, ProtocolMessage::ZERO,
1108 &matching_key, sizeof(MacKeyType));
1109
1110 db<Protocol>(INF) << "[Protocol] Sending KEY_RESPONSE to vehicle "
1111 << vehicle_address.to_string() << " with key from RSU " << matching_rsu_id << ".\n";
1112
1113 int result = send(address(), vehicle_address, resp_msg->data(), resp_msg->size());
1114
1115 if (result > 0) {
1116 db<Protocol>(INF) << "[Protocol] Successfully sent KEY_RESPONSE message.\n";
1117 } else {
1118 db<Protocol>(WRN) << "[Protocol] Failed to send KEY_RESPONSE message for RSU " << matching_rsu_id << ".\n";
1119 }
1120
1121 delete resp_msg;
1122 } else {
1123 db<Protocol>(INF) << "[Protocol] REQ - No matching neighbor RSU key found for the failed message.\n";
1124
1125 // DEBUG: Let's also check our own key to see if it would match
1127 std::string leader_key_hex = "";
1128 for (size_t i = 0; i < 16; ++i) {
1129 char hex_byte[4];
1130 snprintf(hex_byte, sizeof(hex_byte), "%02X ", leader_key[i]);
1132 }
1133 db<Protocol>(INF) << "[Protocol] REQ - For comparison, our own leader key: " << leader_key_hex << "\n";
1134
1138 std::string self_calc_mac_hex = "";
1139 for (size_t i = 0; i < 16; ++i) {
1140 char hex_byte[4];
1141 snprintf(hex_byte, sizeof(hex_byte), "%02X ", self_calculated_mac[i]);
1143 }
1144 db<Protocol>(INF) << "[Protocol] REQ - Our own key would produce MAC: " << self_calc_mac_hex << "\n";
1145 }
1146}
1147
1148// KEY_RESPONSE message handler implementation
1149template <typename NIC>
1151 db<Protocol>(INF) << "[Protocol] Vehicle processing KEY_RESPONSE message\n";
1152
1153 // Only vehicles should handle KEY_RESPONSE messages
1154 if (_entity_type != EntityType::VEHICLE || !_vehicle_rsu_manager) {
1155 db<Protocol>(WRN) << "[Protocol] Non-vehicle entity or no RSU manager for KEY_RESPONSE message - ignoring\n";
1156 return;
1157 }
1158
1159 // Deserialize the KEY_RESPONSE message
1160 ProtocolMessage resp_msg = ProtocolMessage::deserialize(message_data, payload_size);
1161 if (resp_msg.message_type() != ProtocolMessage::Type::KEY_RESPONSE) {
1162 db<Protocol>(WRN) << "[Protocol] Failed to deserialize KEY_RESPONSE message\n";
1163 return;
1164 }
1165
1166 // KEY_RESPONSE message payload contains the neighbor RSU key
1167 const uint8_t* resp_payload = resp_msg.value();
1168 unsigned int resp_value_size = resp_msg.value_size();
1169
1170 if (resp_value_size != sizeof(MacKeyType)) {
1171 db<Protocol>(WRN) << "[Protocol] KEY_RESPONSE message payload size mismatch: expected "
1172 << sizeof(MacKeyType) << ", got " << resp_value_size << "\n";
1173 return;
1174 }
1175
1176 // Extract the neighbor RSU key
1178 std::memcpy(&neighbor_key, resp_payload, sizeof(MacKeyType));
1179
1180 // Debug logging: Show received neighbor key
1181 std::string neighbor_key_hex = "";
1182 for (size_t i = 0; i < 16; ++i) {
1183 char hex_byte[4];
1184 snprintf(hex_byte, sizeof(hex_byte), "%02X ", neighbor_key[i]);
1186 }
1187 db<Protocol>(INF) << "[Protocol] KEY_RESPONSE - Received neighbor RSU key: " << neighbor_key_hex << "\n";
1188
1189 // Add the neighbor RSU key to our collection
1190 _vehicle_rsu_manager->add_neighbor_rsu_key(neighbor_key);
1191
1192 db<Protocol>(INF) << "[Protocol] Successfully added neighbor RSU key to vehicle storage\n";
1193}
1194
1195// REQ message sending implementation
1196template <typename NIC>
1198 const MacKeyType& failed_mac, const Header* failed_header,
1199 const TimestampFields* failed_timestamps, const Coordinates* failed_coordinates) {
1200 db<Protocol>(INF) << "[Protocol] Preparing REQ message for leader RSU\n";
1201
1202 // Only vehicles should send REQ messages
1203 if (_entity_type != EntityType::VEHICLE || !_vehicle_rsu_manager) {
1204 db<Protocol>(WRN) << "[Protocol] Non-vehicle entity or no RSU manager - cannot send REQ\n";
1205 return;
1206 }
1207
1208 // Get current leader
1209 auto current_leader = _vehicle_rsu_manager->get_current_leader();
1210 if (!current_leader) {
1211 db<Protocol>(WRN) << "[Protocol] No current leader RSU - cannot send REQ message\n";
1212 return;
1213 }
1214
1215 db<Protocol>(INF) << "[Protocol] Sending REQ to leader RSU: " << current_leader->address.to_string() << "\n";
1216
1217 // Create REQ message payload: failed_header + failed_timestamps + failed_coordinates + failed_message_data + failed_mac
1218 unsigned int req_payload_size = sizeof(Header) + sizeof(TimestampFields) + sizeof(Coordinates) + failed_message_size + sizeof(MacKeyType);
1219 std::vector<uint8_t> req_payload(req_payload_size);
1220 unsigned int offset = 0;
1221
1222 // Copy original header
1223 std::memcpy(req_payload.data() + offset, failed_header, sizeof(Header));
1224 offset += sizeof(Header);
1225
1226 // Copy original timestamps
1227 std::memcpy(req_payload.data() + offset, failed_timestamps, sizeof(TimestampFields));
1228 offset += sizeof(TimestampFields);
1229
1230 // Copy original coordinates
1231 std::memcpy(req_payload.data() + offset, failed_coordinates, sizeof(Coordinates));
1232 offset += sizeof(Coordinates);
1233
1234 // Copy original message data
1237
1238 // Append failed MAC
1239 std::memcpy(req_payload.data() + offset, &failed_mac, sizeof(MacKeyType));
1240
1241 // Create REQ message
1242 ProtocolMessage* req_msg = new ProtocolMessage(ProtocolMessage::Type::REQ,
1243 address(), 0, ProtocolMessage::ZERO,
1245
1246 // Send unicast REQ message to leader RSU
1247 int result = send(address(), current_leader->address, req_msg->data(), req_msg->size());
1248
1249 if (result > 0) {
1250 db<Protocol>(INF) << "[Protocol] Successfully sent REQ message to leader\n";
1251 } else {
1252 db<Protocol>(WRN) << "[Protocol] Failed to send REQ message to leader\n";
1253 }
1254
1255 delete req_msg;
1256}
1257
1258// Initialize static members
1259template <typename NIC>
1261
1262// Initialize BROADCASTs addresses
1263template <typename NIC>
1265 typename Protocol<NIC>::Address(
1266 Ethernet::BROADCAST, // MAC broadcast
1267 0 // Broadcast port
1268 );
1269
1270template <typename NIC>
1272 if (_entity_type == EntityType::VEHICLE) {
1273 _vehicle_rsu_manager = manager;
1274 db<Protocol>(INF) << "[Protocol] RSU manager attached to vehicle protocol\n";
1275 } else {
1276 db<Protocol>(WRN) << "[Protocol] Attempted to attach RSU manager to non-vehicle entity\n";
1277 }
1278}
1279
1280// Neighbor RSU management implementation
1281template <typename NIC>
1282void Protocol<NIC>::add_neighbor_rsu(unsigned int rsu_id, const MacKeyType& key, const Address& address) {
1283 if (_entity_type != EntityType::RSU) {
1284 db<Protocol>(WRN) << "[Protocol] Attempted to add neighbor RSU to non-RSU entity\n";
1285 return;
1286 }
1287
1288 std::lock_guard<std::mutex> lock(_neighbor_rsus_mutex);
1289
1290 // Check if already exists
1291 for (const auto& neighbor : _neighbor_rsus) {
1292 if (neighbor.rsu_id == rsu_id) {
1293 db<Protocol>(INF) << "[Protocol] Neighbor RSU " << rsu_id << " already known\n";
1294 return;
1295 }
1296 }
1297
1298 _neighbor_rsus.emplace_back(rsu_id, key, address);
1299
1300 db<Protocol>(INF) << "[Protocol] Added neighbor RSU " << rsu_id << " to protocol (total: " << _neighbor_rsus.size() << ")\n";
1301}
1302
1303template <typename NIC>
1305 if (_entity_type != EntityType::RSU) {
1306 return;
1307 }
1308
1309 std::lock_guard<std::mutex> lock(_neighbor_rsus_mutex);
1310 _neighbor_rsus.clear();
1311 db<Protocol>(INF) << "[Protocol] Cleared all neighbor RSUs from protocol\n";
1312}
1313
1314template <typename NIC>
1316 if (!_nic) {
1317 return Address(); // Return null address if no NIC
1318 }
1319
1320 // Use NIC's physical address and a default port based on entity type
1321 Port protocol_port = (_entity_type == EntityType::RSU) ? 9999 : 8888;
1322 return Address(_nic->address(), protocol_port);
1323}
1324
1325#endif // PROTOCOL_H
static Clock & getInstance()
Get the singleton instance.
Definition clock.h:145
Definition observer.h:13
Definition observed.h:13
void attach(Observer *o, Condition c)
Definition observed.h:35
static std::string mac_to_string(Address addr)
Definition ethernet.h:36
static const Ethernet::Address BROADCAST
Definition ethernet.h:54
static constexpr unsigned int HEADER_SIZE
Definition ethernet.h:26
static constexpr unsigned int MTU
Definition ethernet.h:12
static double euclideanDistance(double x1, double y1, double x2, double y2)
Definition geo_utils.h:16
MacKeyType getGroupMacKey() const
Get the current group MAC key.
Definition leaderKeyStorage.h:124
static LeaderKeyStorage & getInstance()
Get the singleton instance.
Definition leaderKeyStorage.h:54
static void getCurrentCoordinates(double &x, double &y)
Definition location_service.h:91
Template class for network messages with Clock integration.
Definition message.h:31
Type
Definition message.h:35
Definition nic.h:28
Ethernet::Protocol Protocol_Number
Definition nic.h:36
Definition protocol.h:134
void port(Port port)
Definition protocol.h:257
Null
Definition protocol.h:136
@ NULL_VALUE
Definition protocol.h:136
bool operator==(const Address &a) const
Definition protocol.h:272
const Port & port() const
Definition protocol.h:262
Address()
Definition protocol.h:238
static const Address BROADCAST
Definition protocol.h:151
const std::string to_string() const
Definition protocol.h:277
const Physical_Address & paddr() const
Definition protocol.h:252
Definition protocol.h:43
void to_port(Port p)
Definition protocol.h:51
void from_port(Port p)
Definition protocol.h:48
Port to_port() const
Definition protocol.h:50
Header()
Definition protocol.h:45
unsigned int size() const
Definition protocol.h:53
Port from_port() const
Definition protocol.h:47
void size(unsigned int s)
Definition protocol.h:54
Definition protocol.h:86
T * data()
Definition protocol.h:111
AuthenticationFields * authentication()
Definition protocol.h:104
TimestampFields * timestamps()
Definition protocol.h:92
static constexpr unsigned int sync_status_offset()
Definition protocol.h:118
static constexpr unsigned int tx_timestamp_offset()
Definition protocol.h:122
Coordinates * coordinates()
Definition protocol.h:98
Packet()
Definition protocol.h:88
Header * header()
Definition protocol.h:90
Definition protocol.h:29
int receive(Buffer *buf, Address *from, void *data, unsigned int size)
Definition protocol.h:472
Conditional_Data_Observer< Buffer, Port > Observer
Definition protocol.h:39
int send(Address from, Address to, const void *data, unsigned int size)
Definition protocol.h:302
void free(Buffer *buf)
Definition protocol.h:722
void setRadius(double radius)
Definition protocol.h:730
NIC::Address Physical_Address
Definition protocol.h:34
std::uint16_t Port
Definition protocol.h:35
void set_vehicle_rsu_manager(VehicleRSUManager< Protocol< NIC > > *manager)
Definition protocol.h:1271
EntityType
Definition protocol.h:161
std::uint8_t Data[MTU]
Definition protocol.h:83
void clear_neighbor_rsus()
Definition protocol.h:1304
NIC::DataBuffer Buffer
Definition protocol.h:33
~Protocol()
Definition protocol.h:296
static void detach(Observer *obs, Address address)
Definition protocol.h:524
static const NIC::Protocol_Number PROTO
Definition protocol.h:31
Protocol(NIC *nic, EntityType entity_type=EntityType::UNKNOWN)
Definition protocol.h:284
void add_neighbor_rsu(unsigned int rsu_id, const MacKeyType &key, const Address &address)
Definition protocol.h:1282
Message< Protocol< NIC > > ProtocolMessage
Definition protocol.h:36
static const unsigned int MTU
Definition protocol.h:82
static void attach(Observer *obs, Address address)
Definition protocol.h:518
Address address() const
Definition protocol.h:1315
Conditionally_Data_Observed< Buffer, Port > Observed
Definition protocol.h:40
class Protocol::Address __attribute__
Definition vehicleRSUManager.h:33
uint32_t LeaderIdType
Definition clock.h:26
std::chrono::time_point< std::chrono::steady_clock, std::chrono::microseconds > TimestampType
Definition clock.h:16
@ INF
Definition debug.h:208
Select_Debug<(Traits< T >::debugged &&Traits< Debug >::error)> db(Debug_Error l)
Definition debug.h:166
@ TRC
Definition debug.h:231
@ WRN
Definition debug.h:185
Protocol prot
Definition ethernet.h:2
std::uint8_t payload[MTU]
Definition ethernet.h:3
std::array< uint8_t, 16 > MacKeyType
Definition leaderKeyStorage.h:15
Coordinates * coordinates()
Definition protocol.h:11
TimestampFields * timestamps()
Definition protocol.h:5
T * data()
Definition protocol.h:24
Header * header()
Definition protocol.h:3
Packet()
Definition protocol.h:1
Definition location_service.h:15
double x
Definition location_service.h:16
double radius
Definition location_service.h:18
double y
Definition location_service.h:17
Definition ethernet.h:16
Definition protocol.h:73
bool has_mac
Definition protocol.h:75
MacKeyType mac
Definition protocol.h:74
AuthenticationFields()
Definition protocol.h:77
Definition protocol.h:63
bool is_clock_synchronized
Definition protocol.h:64
TimestampFields()
Definition protocol.h:67
TimestampType tx_timestamp
Definition protocol.h:65
Definition clock.h:30
LeaderIdType sender_id
Definition clock.h:31
Definition traits.h:45