diff --git a/ModelUrlMsg.cpp b/ModelUrlMsg.cpp index 1d4f0da..5aa233c 100644 --- a/ModelUrlMsg.cpp +++ b/ModelUrlMsg.cpp @@ -1,5 +1,7 @@ #include "ModelUrlMsg.h" +#include + namespace Passer { namespace Control { @@ -25,7 +27,11 @@ ModelUrlMsg::ModelUrlMsg(const char *buffer) { ModelUrlMsg::ModelUrlMsg(unsigned char networkId, Thing *thing) { this->networkId = networkId; this->thingId = thing->id; - this->urlLength = strlen(thing->modelUrl); + if (thing->modelUrl == nullptr) + this->urlLength = 0; + else + this->urlLength = strlen(thing->modelUrl); + this->url = thing->modelUrl; // dangerous! } diff --git a/NameMsg.cpp b/NameMsg.cpp index a49dbc0..6f06dc7 100644 --- a/NameMsg.cpp +++ b/NameMsg.cpp @@ -1,5 +1,7 @@ #include "NameMsg.h" +#include + namespace Passer { namespace Control { @@ -15,7 +17,10 @@ NameMsg::NameMsg(const char *buffer) { NameMsg::NameMsg(unsigned char networkId, Thing *thing) { this->networkId = networkId; this->thingId = thing->id; - this->nameLength = strlen(thing->name); + if (thing->name == nullptr) + this->nameLength = 0; + else + this->nameLength = strlen(thing->name); this->name = thing->name; // dangerous! } diff --git a/Participant.cpp b/Participant.cpp index 6637209..433b240 100644 --- a/Participant.cpp +++ b/Participant.cpp @@ -4,20 +4,32 @@ #define BUF_SIZE 1024 +#include "UdpArduino.h" + #if defined(_WIN32) || defined(_WIN64) #include #include #pragma comment(lib, "ws2_32.lib") #elif defined(__unix__) || defined(__APPLE__) #include +#include // For fcntl #include #include #include -#include // For fcntl #endif Participant::Participant() {} +Participant::Participant(int port) { + this->ipAddress = "0.0.0.0"; + this->port = port; + + this->participants.push_back(this); + + int randomPort = (rand() % (65535 - 49152 + 1)) + 49152; + SetupUDP(randomPort, ipAddress, port); +} + Participant::Participant(const char *ipAddress, int port) { this->ipAddress = ipAddress; this->port = port; @@ -31,125 +43,18 @@ Participant::Participant(const char *ipAddress, int port) { void Passer::Control::Participant::SetupUDP(int localPort, const char *remoteIpAddress, int remotePort) { - // 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 the socket to non-blocking mode -#if defined(_WIN32) || defined(_WIN64) - u_long mode = 1; // 1 to enable non-blocking socket - ioctlsocket(this->sock, FIONBIO, &mode); -#elif defined(__unix__) || defined(__APPLE__) - int flags = fcntl(this->sock, F_GETFL, 0); - fcntl(this->sock, F_SETFL, flags | O_NONBLOCK); -#endif - - if (remotePort != 0) { - // Set up the address to send to - memset(&remote_addr, 0, sizeof(remote_addr)); - remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons((u_short)remotePort); - if (inet_pton(AF_INET, remoteIpAddress, &remote_addr.sin_addr) <= 0) { - std::cerr << "Invalid address" << std::endl; -#if defined(_WIN32) || defined(_WIN64) - closesocket(sock); - WSACleanup(); -#elif defined(__unix__) || defined(__APPLE__) - close(sock); -#endif - return; - } - } - - // Set up the receiving address - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons((u_short)localPort); - if (inet_pton(AF_INET, "0.0.0.0", &server_addr.sin_addr) <= 0) { - std::cerr << "Invalid address" << std::endl; -#if defined(_WIN32) || defined(_WIN64) - closesocket(sock); - WSACleanup(); -#elif defined(__unix__) || defined(__APPLE__) - close(sock); -#endif - return; - } - - // Bind the socket to the specified port - if (bind(this->sock, (const struct sockaddr *)&server_addr, - sizeof(server_addr)) < 0) { - std::cerr << "Bind failed" << std::endl; -#if defined(_WIN32) || defined(_WIN64) - closesocket(sock); - WSACleanup(); -#elif defined(__unix__) || defined(__APPLE__) - close(sock); -#endif - return; - } - - // Bind the socket to the specified port -// if (bind(this->sock, (const struct sockaddr *)&server_addr, -// sizeof(server_addr)) < 0) { -// std::cerr << "Bind failed" << std::endl; -// #if defined(_WIN32) || defined(_WIN64) -// closesocket(sock); -// WSACleanup(); -// #elif defined(__unix__) || defined(__APPLE__) -// close(sock); -// #endif -// 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)remotePort); - if (inet_pton(AF_INET, "255.255.255.255", &broadcast_addr.sin_addr) <= 0) { - std::cerr << "Invalid address" << std::endl; -#if defined(_WIN32) || defined(_WIN64) - closesocket(sock); - WSACleanup(); -#elif defined(__unix__) || defined(__APPLE__) - close(sock); -#endif - return; - } -#if defined(_WIN32) || defined(_WIN64) - 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; - } -#elif defined(__unix__) || defined(__APPLE__) - int broadcastEnable = 1; - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable)) < 0) { - std::cerr << "Failed to set socket options" << std::endl; - } + UdpWindows *thisWindows = static_cast(this); + thisWindows->Setup(localPort, remoteIpAddress, remotePort); +#elif defined(ARDUINO) + UdpArduino *thisArduino = static_cast(this); + thisArduino->Setup(localPort, remoteIpAddress, remotePort); #endif } void Participant::Update(unsigned long currentTimeMs) { - if (currentTimeMs > this->nextPublishMe) { - ClientMsg* msg = new ClientMsg(this->networkId); + if (this->publishInterval > 0 && currentTimeMs > this->nextPublishMe) { + ClientMsg *msg = new ClientMsg(this->networkId); this->Publish(msg); delete msg; std::cout << this->name << " published ClientMsg\n"; @@ -161,47 +66,13 @@ void Participant::Update(unsigned long currentTimeMs) { } void Participant::ReceiveUDP() { - // char ip_str[INET_ADDRSTRLEN]; - // inet_ntop(AF_INET, &(server_addr.sin_addr), ip_str, INET_ADDRSTRLEN); - // std::cout << this->name << " Receive on " << ip_str << ":" - // << ntohs(server_addr.sin_port) << "\n"; - - sockaddr_in client_addr; #if defined(_WIN32) || defined(_WIN64) - int len = sizeof(client_addr); -#elif defined(__unix__) || defined(__APPLE__) - socklen_t len = sizeof(client_addr); + UdpWindows *thisWindows = static_cast(this); + thisWindows->Receive(); +#elif defined(ARDUINO) + UdpArduino *thisArduino = static_cast(this); + thisArduino->Receive(); #endif - int packetSize = recvfrom(this->sock, buffer, sizeof(buffer), 0, - (struct sockaddr *)&client_addr, &len); - // std::cout << "received data " << packetSize << "\n"; - if (packetSize < 0) { -#if defined(_WIN32) || defined(_WIN64) - int error_code = WSAGetLastError(); // Get the error code on Windows - if (error_code != WSAEWOULDBLOCK) - std::cerr << "recvfrom failed with error: " << error_code << std::endl; -#else - //std::cerr << "recvfrom failed with error: " << packetSize << std::endl; -#endif - } else if (packetSize > 0) { - char sender_ipAddress[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(client_addr.sin_addr), sender_ipAddress, - INET_ADDRSTRLEN); - int sender_port = ntohs(client_addr.sin_port); - - Participant *remoteParticipant = - this->GetParticipant(sender_ipAddress, sender_port); - if (remoteParticipant == nullptr) { - remoteParticipant = this->AddParticipant(sender_ipAddress, sender_port); - // std::cout << "New sender " << sender_ipAddress << ":" - // << sender_port << "\n"; - // std::cout << "New remote participant " << remoteParticipant->ipAddress << ":" - // << remoteParticipant->port << " " - // << (int)remoteParticipant->networkId << "\n"; - } - - ReceiveData(packetSize, remoteParticipant); - } } Participant *Participant::GetParticipant(const char *ipAddress, int port) { @@ -232,68 +103,41 @@ void Participant::SendThingInfo(Thing *thing) { msg = new ModelUrlMsg(this->networkId, thing); this->Send(msg); delete msg; - // this->Send(&ModelUrlMsg(this->networkId, thing)); +} + +void Passer::Control::Participant::PublishThingInfo(Thing *thing) { + std::cout << "Publish thing info\n"; + // Strange, when publishing, the network id is irrelevant, because it is + // connected to a specific site... + ThingMsg *thingMsg = new ThingMsg(this->networkId, thing); + this->Publish(thingMsg); + delete thingMsg; + NameMsg *nameMsg = new NameMsg(this->networkId, thing); + this->Publish(nameMsg); + delete nameMsg; + ModelUrlMsg *modelMsg = new ModelUrlMsg(this->networkId, thing); + this->Publish(modelMsg); + delete modelMsg; } 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, &(remote_addr.sin_addr), ip_str, INET_ADDRSTRLEN); - std::cout << "Send to " << ip_str << ":" << ntohs(remote_addr.sin_port) - << "\n"; - int sent_bytes = sendto(sock, this->buffer, bufferSize, 0, - (struct sockaddr *)&remote_addr, sizeof(remote_addr)); #if defined(_WIN32) || defined(_WIN64) - 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; - } -#elif defined(__unix__) || defined(__APPLE__) - if (sent_bytes < 0) { - std::cerr << "sendto failed with error: " << sent_bytes << std::endl; - close(sock); - return false; - } + UdpWindows *thisWindows = static_cast(this); + return thisWindows->Send(msg); +#elif defined(ARDUINO) + UdpArduino *thisArduino = static_cast(this); + return thisArduino->Send(msg); #endif - return true; } bool Participant::Publish(IMessage *msg) { - int bufferSize = msg->Serialize(this->buffer); - if (bufferSize <= 0) - return true; - - char ip_str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(broadcast_addr.sin_addr), ip_str, INET_ADDRSTRLEN); - std::cout << "Publish to " << ip_str << ":" << ntohs(broadcast_addr.sin_port) - << "\n"; - int sent_bytes = - sendto(sock, this->buffer, bufferSize, 0, - (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)); #if defined(_WIN32) || defined(_WIN64) - 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; - } -#elif defined(__unix__) || defined(__APPLE__) - if (sent_bytes < 0) { - std::cerr << "sendto failed with error: " << sent_bytes << std::endl; - close(sock); - return false; - } + UdpWindows *thisWindows = static_cast(this); + return thisWindows->Publish(msg); +#elif defined(ARDUINO) + UdpArduino *thisArduino = static_cast(this); + return thisArduino->Publish(msg); #endif - return true; } // Send @@ -306,12 +150,12 @@ void Participant::ReceiveData(unsigned char bufferSize, unsigned char msgId = this->buffer[0]; switch (msgId) { case ClientMsg::id: { - ClientMsg* msg = new ClientMsg(this->buffer); + ClientMsg *msg = new ClientMsg(this->buffer); Process(remoteParticipant, msg); delete msg; } case NetworkIdMsg::id: { - NetworkIdMsg* msg = new NetworkIdMsg(this->buffer); + NetworkIdMsg *msg = new NetworkIdMsg(this->buffer); Process(remoteParticipant, msg); delete msg; } break; @@ -349,7 +193,7 @@ void Participant::Process(Participant *sender, NetworkIdMsg *msg) { // sender->SendThingInfo(thing); // } - for (Thing* thing : allThings) { + for (Thing *thing : allThings) { sender->SendThingInfo(thing); } } diff --git a/Participant.h b/Participant.h index 68ec9e1..41a1149 100644 --- a/Participant.h +++ b/Participant.h @@ -16,6 +16,8 @@ #include #include #include +#elif defined(ARDUINO) +#include #endif namespace Passer { @@ -33,21 +35,36 @@ public: const char *ipAddress = "0.0.0.0"; int port = 0; +#if defined(ARDUINO) + const char *remoteIpAddress = nullptr; + unsigned short remotePort = 0; + char *broadcastIpAddress = nullptr; + + WiFiUDP udp; +#else + #if defined(_WIN32) || defined(_WIN64) SOCKET sock; #elif defined(__unix__) || defined(__APPLE__) int sock; -#endif +#endif sockaddr_in remote_addr; sockaddr_in server_addr; sockaddr_in broadcast_addr; +#endif + Participant(); + Participant(int port); Participant(const char *ipAddress, int port); + // Bad design, you cannot use constructor in global scope + // i.e. + // Participant p = Participant("127.0.0.1", 8000); virtual void Update(unsigned long currentTimeMs); void SendThingInfo(Thing *thing); + void PublishThingInfo(Thing *thing); bool Send(IMessage *msg); bool Publish(IMessage *msg); diff --git a/Thing.cpp b/Thing.cpp index 9c45426..7c0ea52 100644 --- a/Thing.cpp +++ b/Thing.cpp @@ -1,7 +1,9 @@ #include "Thing.h" #include "Participant.h" +#include #include +#include #include Thing::Thing(unsigned char networkId, unsigned char thingType) { @@ -165,9 +167,11 @@ Thing *Thing::Get(unsigned char networkId, unsigned char thingId) { // return thing; // } // return nullptr; - std::find_if(allThings.begin(), allThings.end(), [networkId, thingId](Thing* thing){ - return thing->networkId == networkId && thing->id == thingId; - }); + std::find_if(allThings.begin(), allThings.end(), + [networkId, thingId](Thing *thing) { + return thing->networkId == networkId && thing->id == thingId; + }); + return nullptr; } int Thing::Add(Thing *newThing) { @@ -181,17 +185,18 @@ int Thing::Add(Thing *newThing) { // return ix; // } // } - for (Thing* thing : allThings) { + for (Thing *thing : allThings) { if (thing == newThing) return thing->id; } allThings.push_back(newThing); + return allThings.size() - 1; } void Thing::Remove(Thing *thing) { // std::cout << " remove " << (int)thing->id << "\n"; // allThings[thing->id] = nullptr; - allThings.remove_if([thing](Thing* obj) { return obj == thing; }); + allThings.remove_if([thing](Thing *obj) { return obj == thing; }); } void Thing::UpdateAll(unsigned long currentTimeMs) { @@ -205,7 +210,7 @@ void Thing::UpdateAll(unsigned long currentTimeMs) { // thing->Update(currentTimeMs); // } // } - for (Thing* thing : allThings) { + for (Thing *thing : allThings) { if (thing != nullptr && thing->parent == nullptr) { // update all root things // std::cout << " update " << (int)ix << " thingid " << (int)thing->id diff --git a/UdpArduino.cpp b/UdpArduino.cpp new file mode 100644 index 0000000..ceb3f7b --- /dev/null +++ b/UdpArduino.cpp @@ -0,0 +1,91 @@ +#include "UdpArduino.h" + +#if defined(ARDUINO) +#include +#endif +namespace Passer { +namespace Control { + +void UdpArduino::Setup(int localPort, const char *remoteIpAddress, + int remotePort) { +#if ARDUINO + this->remoteIpAddress = remoteIpAddress; + this->remotePort = remotePort; + GetBroadcastAddress(); + + if (WiFi.isConnected() == false) { + std::cout << "No network available!\n"; + return; + } + udp.begin(this->remotePort); + + std::cout << "Wifi sync started to port " << this->remotePort << "\n"; +#endif +} + +void UdpArduino::GetBroadcastAddress() { + IPAddress broadcastAddress = WiFi.localIP(); + broadcastAddress[3] = 255; + String broadcastIpString = broadcastAddress.toString(); + this->broadcastIpAddress = new char[broadcastIpString.length() + 1]; + broadcastIpString.toCharArray(this->broadcastIpAddress, + broadcastIpString.length() + 1); + std::cout << "Broadcast address: " << broadcastIpAddress << "\n"; +} + +void UdpArduino::Receive() { + int packetSize = udp.parsePacket(); + while (packetSize > 0) { + udp.read(buffer, packetSize); + + String senderAddress = udp.remoteIP().toString(); + char sender_ipAddress[16]; + senderAddress.toCharArray(sender_ipAddress, 16); + int sender_port = udp.remotePort(); + + Participant *remoteParticipant = + this->GetParticipant(sender_ipAddress, sender_port); + if (remoteParticipant == nullptr) { + remoteParticipant = this->AddParticipant(sender_ipAddress, sender_port); + std::cout << "New sender " << sender_ipAddress << ":" << sender_port + << "\n"; + std::cout << "New remote participant " << remoteParticipant->ipAddress + << ":" << remoteParticipant->port << " " + << (int)remoteParticipant->networkId << "\n"; + } + + ReceiveData(packetSize, remoteParticipant); + packetSize = udp.parsePacket(); + } +} + +bool UdpArduino::Send(IMessage *msg) { + int bufferSize = msg->Serialize(this->buffer); + if (bufferSize <= 0) + return true; + + udp.beginPacket(this->remoteIpAddress, this->remotePort); + udp.write(buffer, bufferSize); + udp.endPacket(); + + // std::cout << "Sent to " << this->remoteIpAddress << ":" + // << this->remotePort << "\n"; + return true; +} + +bool UdpArduino::Publish(IMessage *msg) { + int bufferSize = msg->Serialize(this->buffer); + if (bufferSize <= 0) + return true; + + udp.beginPacket(this->broadcastIpAddress, this->remotePort); + udp.write(buffer, bufferSize); + udp.endPacket(); + + // std::cout << "Publish to " << this->broadcastIpAddress << ":" + // << this->remotePort << "\n"; + return true; +}; + +} // namespace Control +} // namespace Passer \ No newline at end of file diff --git a/UdpArduino.h b/UdpArduino.h new file mode 100644 index 0000000..62328b0 --- /dev/null +++ b/UdpArduino.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Participant.h" + +namespace Passer { +namespace Control { + +class UdpArduino : public Participant { +public: + void Setup(int localPort, const char *remoteIpAddress, int remotePort); + void Receive(); + bool Send(IMessage *msg); + bool Publish(IMessage *msg); + +protected: + void GetBroadcastAddress(); +}; + +} // namespace Control +} // namespace Passer \ No newline at end of file diff --git a/UdpWindows.cpp b/UdpWindows.cpp new file mode 100644 index 0000000..14348f3 --- /dev/null +++ b/UdpWindows.cpp @@ -0,0 +1,201 @@ +#include "UdpWindows.h" + +namespace Passer { +namespace Control { + +void UdpWindows::Setup(int localPort, const char *remoteIpAddress, + int remotePort) { +#if defined(_WIN32) || defined(_WIN64) + + // 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 the socket to non-blocking mode +#if defined(_WIN32) || defined(_WIN64) + u_long mode = 1; // 1 to enable non-blocking socket + ioctlsocket(this->sock, FIONBIO, &mode); +#elif defined(__unix__) || defined(__APPLE__) + int flags = fcntl(this->sock, F_GETFL, 0); + fcntl(this->sock, F_SETFL, flags | O_NONBLOCK); +#endif + + if (remotePort != 0) { + // Set up the address to send to + memset(&remote_addr, 0, sizeof(remote_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons((u_short)remotePort); + if (inet_pton(AF_INET, remoteIpAddress, &remote_addr.sin_addr) <= 0) { + std::cerr << "Invalid address" << std::endl; +#if defined(_WIN32) || defined(_WIN64) + closesocket(sock); + WSACleanup(); +#elif defined(__unix__) || defined(__APPLE__) + close(sock); +#endif + return; + } + } + + // Set up the receiving address + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons((u_short)localPort); + if (inet_pton(AF_INET, "0.0.0.0", &server_addr.sin_addr) <= 0) { + std::cerr << "Invalid address" << std::endl; +#if defined(_WIN32) || defined(_WIN64) + closesocket(sock); + WSACleanup(); +#elif defined(__unix__) || defined(__APPLE__) + close(sock); +#endif + return; + } + + // Bind the socket to the specified port + if (bind(this->sock, (const struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + std::cerr << "Bind failed" << std::endl; +#if defined(_WIN32) || defined(_WIN64) + closesocket(sock); + WSACleanup(); +#elif defined(__unix__) || defined(__APPLE__) + close(sock); +#endif + } + +#endif +} + +void UdpWindows::Receive() { +#if defined(_WIN32) || defined(_WIN64) + // char ip_str[INET_ADDRSTRLEN]; + // inet_ntop(AF_INET, &(server_addr.sin_addr), ip_str, INET_ADDRSTRLEN); + // std::cout << this->name << " Receive on " << ip_str << ":" + // << ntohs(server_addr.sin_port) << "\n"; + + sockaddr_in client_addr; +#if defined(_WIN32) || defined(_WIN64) + int len = sizeof(client_addr); +#elif defined(__unix__) || defined(__APPLE__) + socklen_t len = sizeof(client_addr); +#endif + int packetSize = recvfrom(this->sock, buffer, sizeof(buffer), 0, + (struct sockaddr *)&client_addr, &len); + // std::cout << "received data " << packetSize << "\n"; + if (packetSize < 0) { +#if defined(_WIN32) || defined(_WIN64) + int error_code = WSAGetLastError(); // Get the error code on Windows + if (error_code != WSAEWOULDBLOCK) + std::cerr << "recvfrom failed with error: " << error_code << std::endl; +#else + // std::cerr << "recvfrom failed with error: " << packetSize << std::endl; +#endif + } else if (packetSize > 0) { + char sender_ipAddress[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(client_addr.sin_addr), sender_ipAddress, + INET_ADDRSTRLEN); + int sender_port = ntohs(client_addr.sin_port); + + Participant *remoteParticipant = + this->GetParticipant(sender_ipAddress, sender_port); + if (remoteParticipant == nullptr) { + remoteParticipant = this->AddParticipant(sender_ipAddress, sender_port); + // std::cout << "New sender " << sender_ipAddress << ":" + // << sender_port << "\n"; + // std::cout << "New remote participant " << + // remoteParticipant->ipAddress + // << ":" + // << remoteParticipant->port << " " + // << (int)remoteParticipant->networkId << "\n"; + } + + ReceiveData(packetSize, remoteParticipant); + } +#endif +} + +bool UdpWindows::Send( + IMessage *msg) { // Send the message to the specified address and port +#if defined(_WIN32) || defined(_WIN64) + 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, &(remote_addr.sin_addr), ip_str, INET_ADDRSTRLEN); + std::cout << "Send to " << ip_str << ":" << ntohs(remote_addr.sin_port) + << "\n"; + int sent_bytes = sendto(sock, this->buffer, bufferSize, 0, + (struct sockaddr *)&remote_addr, sizeof(remote_addr)); +#if defined(_WIN32) || defined(_WIN64) + 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; + } +#elif defined(__unix__) || defined(__APPLE__) + if (sent_bytes < 0) { + std::cerr << "sendto failed with error: " << sent_bytes << std::endl; + close(sock); + return false; + } +#endif +#endif + return true; +} + +bool UdpWindows::Publish(IMessage *msg) { +#if defined(_WIN32) || defined(_WIN64) + int bufferSize = msg->Serialize(this->buffer); + if (bufferSize <= 0) + return true; + + char ip_str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(broadcast_addr.sin_addr), ip_str, INET_ADDRSTRLEN); + std::cout << "Publish to " << ip_str << ":" << ntohs(broadcast_addr.sin_port) + << "\n"; + int sent_bytes = + sendto(sock, this->buffer, bufferSize, 0, + (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)); +#if defined(_WIN32) || defined(_WIN64) + 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; + } +#elif defined(__unix__) || defined(__APPLE__) + if (sent_bytes < 0) { + std::cerr << "sendto failed with error: " << sent_bytes << std::endl; + close(sock); + return false; + } +#endif +#endif + return true; +} + +} // namespace Control +} // namespace Passer \ No newline at end of file diff --git a/UdpWindows.h b/UdpWindows.h new file mode 100644 index 0000000..f284347 --- /dev/null +++ b/UdpWindows.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Participant.h" + +namespace Passer { +namespace Control { + +class UdpWindows : public Participant { +public: + void Setup(int localPort, const char *remoteIpAddress, int remotePort); + void Receive(); + bool Send(IMessage *msg); + bool Publish(IMessage *msg); +}; + +} // namespace Control +} // namespace Passer \ No newline at end of file