// pointcloud_concatenator.cpp (vulnerable)
// Each upstream publisher (ports 5556, 5557, 5558) 
// The fixed 256-byte buffer 
#include <zmq.hpp>
#include <iostream>
#include <thread>
#include <cstring>

int main() {
  zmq::context_t ctx{1};

  std::vector<zmq::socket_t> subs;
  for (int port : {5556, 5557, 5558}) {
    zmq::socket_t s(ctx, zmq::socket_type::sub);
    std::string address = "tcp://192.168.222.168:" + std::to_string(port);  
    std::cout << " Connecting SUB socket to " << address << "\n";
    s.connect(address);
    s.set(zmq::sockopt::subscribe, "");
    subs.push_back(std::move(s));
  }

  zmq::socket_t pub(ctx, zmq::socket_type::pub);
  pub.bind("tcp://*:5562");

  std::cout << "C++ concatenator running (vulnerable)…\n";

  while (true) {
    uint8_t buffer[256];           
    size_t offset = 0;
    bool overflow_imminent = false;

    for (size_t i = 0; i < subs.size(); ++i) {
      zmq::message_t m;
      std::cout << " Waiting for message on SUB[" << i << "]...\n";
      auto recv_res = subs[i].recv(m, zmq::recv_flags::none);
      std::cout << " Received " << m.size() << " bytes on SUB[" << i
                << "]  (~" << m.size() / 16 << " points)\n"; 
      (void)recv_res;

      if (offset + m.size() > sizeof(buffer)) {
        overflow_imminent = true;  
      }

      std::memcpy(buffer + offset, m.data(), m.size());
      offset += m.size();
    }

    if (!overflow_imminent) {
      std::cout << "Safe: combined size " << offset
                << " fits within buffer limit " << sizeof(buffer) << "\n";
    } else {
      std::cout << " Buffer overflow: attempted to pack "
                << offset / 16 << " points into space for only "
                << sizeof(buffer) / 16 << " points\n"; 
    }

    pub.send(zmq::buffer(buffer, offset), zmq::send_flags::none);
    std::cout << " Published combined (" << offset
              << " bytes ≈ " << offset / 16
              << " points) on tcp://*:5562\n";          
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  }

  return 0;
}

