#include "Participant.h" // #include #define BUF_SIZE 1024 #if defined(_WIN32) || defined(_WIN64) #include #include #pragma comment(lib, "ws2_32.lib") #elif defined(__unix__) || defined(__APPLE__) #include #include #include #include #endif Participant::Participant() {} Participant::Participant(const char *ipAddress, int port) { this->ipAddress = ipAddress; this->port = port; // Create a UDP socket #if defined(_WIN32) || defined(_WIN64) // Windows-specific Winsock initialization WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed" << std::endl; return; } #endif #if defined(_WIN32) || defined(_WIN64) this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); #elif defined(__unix__) || defined(__APPLE__) this->sock = socket(AF_INET, SOCK_DGRAM, 0); #endif if (this->sock < 0) { std::cerr << "Error creating socket" << std::endl; return; } // Set up the server address memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons((u_short)port); // Port to send the packet to if (inet_pton(AF_INET, ipAddress, &server_addr.sin_addr) <= 0) { std::cerr << "Invalid address" << std::endl; closesocket(sock); WSACleanup(); return; } // Set up the broadcast address memset(&broadcast_addr, 0, sizeof(broadcast_addr)); broadcast_addr.sin_family = AF_INET; broadcast_addr.sin_port = htons((u_short)port); // Port to send the packet to if (inet_pton(AF_INET, "255.255.255.255", &broadcast_addr.sin_addr) <= 0) { std::cerr << "Invalid address" << std::endl; closesocket(sock); WSACleanup(); return; } BOOL broadcast = TRUE; if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)) == SOCKET_ERROR) { std::cerr << "Setting socket option for broadcast failed" << std::endl; } } void Participant::Update(unsigned long currentTimeMs) { // std::cout << "update\n"; if (currentTimeMs > this->nextPublishMe) { ClientMsg msg = ClientMsg(this->networkId); this->Publish(&msg); // Console.WriteLine($"{this.name} Sent ClientMsg {this.networkId}"); std::cout << this->name << " sent ClientMsg\n"; this->nextPublishMe = currentTimeMs + this->publishInterval; } } #pragma region Send void Participant::SendThingInfo(Thing *thing) { std::cout << "Send thing info\n"; IMessage *msg = new ThingMsg(this->networkId, thing); this->Send(msg); delete msg; msg = new NameMsg(this->networkId, thing); this->Send(msg); delete msg; // msg = new ModelUrlMsg(this->networkId, thing); // this->Send(msg); // delete msg; this->Send(&ModelUrlMsg(this->networkId, thing)); } bool Participant::Send(IMessage *msg) { // Send the message to the specified address and port int bufferSize = msg->Serialize(this->buffer); std::cout << "buffer size " << bufferSize << "\n"; if (bufferSize <= 0) return true; // char ip_str[INET_ADDRSTRLEN]; // inet_ntop(AF_INET, &(server_addr.sin_addr), ip_str, INET_ADDRSTRLEN); // std::cout << "Publish to " << ip_str << ":" << ntohs(server_addr.sin_port) // << "\n"; int sent_bytes = sendto(sock, this->buffer, bufferSize, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (sent_bytes == SOCKET_ERROR) { int error_code = WSAGetLastError(); // Get the error code on Windows std::cerr << "sendto failed with error: " << error_code << std::endl; closesocket(sock); WSACleanup(); return false; } return true; } bool Participant::Publish(IMessage *msg) { // Send the message to the specified address and port int bufferSize = msg->Serialize(this->buffer); std::cout << "buffer size " << bufferSize << "\n"; if (bufferSize <= 0) return true; // char ip_str[INET_ADDRSTRLEN]; // inet_ntop(AF_INET, &(server_addr.sin_addr), ip_str, INET_ADDRSTRLEN); // std::cout << "Publish to " << ip_str << ":" << ntohs(server_addr.sin_port) // << "\n"; int sent_bytes = sendto(sock, this->buffer, bufferSize, 0, (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)); if (sent_bytes == SOCKET_ERROR) { int error_code = WSAGetLastError(); // Get the error code on Windows std::cerr << "sendto failed with error: " << error_code << std::endl; closesocket(sock); WSACleanup(); return false; } return true; } // Send #pragma endregion #pragma region Receive void Participant::ReceiveData(unsigned char bufferSize, Participant *remoteParticipant) { unsigned char msgId = this->buffer[0]; switch (msgId) { case ClientMsg::id: { Process(remoteParticipant, &ClientMsg(this->buffer)); } case NetworkIdMsg::id: { Process(remoteParticipant, &NetworkIdMsg(this->buffer)); } break; case InvestigateMsg::id: { InvestigateMsg msg = InvestigateMsg(this->buffer); ProcessInvestigateMsg(msg); } break; case ThingMsg::id: { ThingMsg msg = ThingMsg(this->buffer); ProcessThingMsg(msg); } break; case PoseMsg::id: { PoseMsg msg = PoseMsg(this->buffer); ProcessPoseMsg(msg); } break; case CustomMsg::id: { CustomMsg msg = CustomMsg(this->buffer); ProcessCustomMsg(msg); } break; }; } void Participant::Process(Participant *sender, ClientMsg *msg) {} void Participant::Process(Participant *sender, NetworkIdMsg *msg) { std::cout << this->name << " receive network id " << this->networkId << " " << msg->networkId << "\n"; if (this->networkId != msg->networkId) { this->networkId = msg->networkId; Thing **allThings = Thing::GetAllThings(); for (uint16_t ix = 0; ix < THING_STORE_SIZE; ix++) { Thing *thing = allThings[ix]; if (thing == nullptr) continue; sender->SendThingInfo(thing); } } } void Participant::ProcessInvestigateMsg(InvestigateMsg msg) {} void Participant::ProcessThingMsg(ThingMsg msg) {} void Passer::Control::Participant::ProcessPoseMsg(PoseMsg msg) {} void Participant::ProcessCustomMsg(CustomMsg msg) {} // Receive #pragma endregion