67 lines
2.1 KiB
C++
67 lines
2.1 KiB
C++
// File: src/port/win/udp_driver_win.cpp
|
|
#include "pollobject.h"
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <span>
|
|
#include <stdexcept>
|
|
|
|
#pragma comment(lib, "Ws2_32.lib")
|
|
|
|
namespace drivers {
|
|
|
|
class UdpDriver : public poller::PollObject {
|
|
public:
|
|
explicit UdpDriver(uint16_t port) {
|
|
WSADATA wsa;
|
|
WSAStartup(MAKEWORD(2,2), &wsa);
|
|
|
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
if (sock == INVALID_SOCKET) throw std::runtime_error("Cannot create socket");
|
|
|
|
sockaddr_in addr{};
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if (bind(sock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
|
|
throw std::runtime_error("Bind failed");
|
|
|
|
winHandle = WSACreateEvent();
|
|
if (!winHandle) throw std::runtime_error("WSACreateEvent failed");
|
|
|
|
WSAEventSelect(sock, winHandle, FD_READ);
|
|
}
|
|
|
|
bool sendTo(std::span<const uint8_t> data, const std::string& addrStr, uint16_t port) {
|
|
sockaddr_in dest{};
|
|
dest.sin_family = AF_INET;
|
|
dest.sin_port = htons(port);
|
|
inet_pton(AF_INET, addrStr.c_str(), &dest.sin_addr);
|
|
|
|
int ret = sendto(sock, (const char*)data.data(), (int)data.size(), 0,
|
|
(sockaddr*)&dest, sizeof(dest));
|
|
return ret == (int)data.size();
|
|
}
|
|
|
|
bool recvPacket(std::vector<uint8_t>& out) {
|
|
out.resize(512);
|
|
sockaddr_in src{};
|
|
int len = sizeof(src);
|
|
int ret = recvfrom(sock, (char*)out.data(), (int)out.size(), MSG_PEEK,
|
|
(sockaddr*)&src, &len);
|
|
if (ret <= 0) return false; // ничего нет или ошибка
|
|
out.resize(ret);
|
|
return true;
|
|
}
|
|
|
|
~UdpDriver() override {
|
|
if (sock != INVALID_SOCKET) closesocket(sock);
|
|
if (winHandle) WSACloseEvent(winHandle);
|
|
WSACleanup();
|
|
}
|
|
};
|
|
|
|
} // namespace drivers
|