49 static const ULONG baddr = htonl(INADDR_BROADCAST);
60 std::move(iface_name));
65 PIP_ADAPTER_INFO adapter_info;
66 adapter_info =
static_cast<IP_ADAPTER_INFO *
>(malloc(
sizeof(IP_ADAPTER_INFO)));
67 ULONG buflen =
sizeof(IP_ADAPTER_INFO);
69 if(GetAdaptersInfo(adapter_info, &buflen) == ERROR_BUFFER_OVERFLOW)
72 adapter_info =
static_cast<IP_ADAPTER_INFO *
>(malloc(buflen));
75 std::map<int, std::string> result;
76 if(GetAdaptersInfo(adapter_info, &buflen) == NO_ERROR)
78 PIP_ADAPTER_INFO adapter = adapter_info;
81 result.emplace(adapter->Index, adapter->AdapterName);
82 adapter = adapter->Next;
91 std::vector<SocketWindows> sockets;
99 PMIB_IPFORWARDTABLE table =
nullptr;
101 int result = NO_ERROR;
102 for (
int i = 0; i < 5; ++i)
104 result = GetIpForwardTable(table, &table_size,
false);
106 if (result == NO_ERROR)
110 else if (result == ERROR_INSUFFICIENT_BUFFER)
113 table = (PMIB_IPFORWARDTABLE)malloc(table_size);
116 if (result != NO_ERROR)
119 ::WSAGetLastError());
122 for (
unsigned int i = 0; i < table->dwNumEntries; ++i)
124 PMIB_IPFORWARDROW row = &table->table[i];
127 row->dwForwardMask == ULONG_MAX &&
128 row->dwForwardType == MIB_IPROUTE_TYPE_DIRECT)
130 const auto iface = interface_names.find(row->dwForwardIfIndex);
131 if (iface != interface_names.end())
135 sockaddr_in src_addr;
136 src_addr.sin_family = AF_INET;
137 src_addr.sin_port = 0;
138 src_addr.sin_addr.s_addr = row->dwForwardNextHop;
140 sockets.back().bind(src_addr);
149 PMIB_IPADDRTABLE table =
nullptr;
150 ULONG table_size = 0;
152 int result = NO_ERROR;
153 for (
int i = 0; i < 5; ++i)
155 result = GetIpAddrTable(table, &table_size,
false);
157 if (result == NO_ERROR)
161 else if (result == ERROR_INSUFFICIENT_BUFFER)
164 table = (PMIB_IPADDRTABLE)malloc(table_size);
167 if (result != NO_ERROR)
170 ::WSAGetLastError());
173 for (
unsigned int i = 0; i < table->dwNumEntries; ++i)
175 PMIB_IPADDRROW row = &table->table[i];
177 if (row->dwAddr == htonl(INADDR_LOOPBACK))
182 const auto iface = interface_names.find(row->dwIndex);
183 if (iface != interface_names.end())
185 const ULONG baddr = row->dwAddr | (~row->dwMask);
189 sockaddr_in src_addr;
190 src_addr.sin_family = AF_INET;
191 src_addr.sin_port = 0;
192 src_addr.sin_addr.s_addr = htonl(INADDR_ANY);
194 sockets.back().bind(src_addr);
206 std::string iface_name) :
207 Socket(std::move(iface_name)),
208 sock_(INVALID_SOCKET),
211 sock_ = ::WSASocket(domain, type, protocol,
nullptr, 0, 0);
212 if (
sock_ == INVALID_SOCKET)
214 throw SocketException(
"Error while creating socket", ::WSAGetLastError());
224 sock_(INVALID_SOCKET),
227 std::swap(
sock_, other.sock_);
232 std::swap(
sock_, other.sock_);
238 if(
sock_ != INVALID_SOCKET)
240 ::closesocket(
sock_);
252 reinterpret_cast<const struct sockaddr *>(&addr),
253 sizeof(addr)) == SOCKET_ERROR)
255 throw SocketException(
"Error while binding to socket", ::WSAGetLastError());
264 wsa_buffer.len = sb.size();
265 wsa_buffer.buf =
reinterpret_cast<char *
>(sb.data());
268 if (::WSASendTo(
sock_,
273 reinterpret_cast<const struct sockaddr *>(&
dst_addr_),
276 nullptr) == SOCKET_ERROR)
278 int err = ::WSAGetLastError();
280 if (err == WSAENETUNREACH || err == WSAEHOSTUNREACH)
283 "Error while sending data - network unreachable", err);
292 if (::setsockopt(
sock_,
295 reinterpret_cast<const char *>(&yes),
296 sizeof(yes)) == SOCKET_ERROR)
299 ::WSAGetLastError());
306 if (::ioctlsocket(
sock_, FIONBIO, &imode) == SOCKET_ERROR)
309 ::WSAGetLastError());
SocketWindows & operator=(SocketWindows &&other)
void bindImpl(const sockaddr_in &addr)
Binds the socket to a specific sockaddr.
void enableNonBlockingImpl()
Enables non-blocking operation for this socket.
Exception representing an invalid socket operation.
static std::vector< SocketWindows > createAndBindForAllInterfaces(uint16_t port)
Creates sockets for all interfaces and binds them to the respective interface.
static const ULONG & getBroadcastAddr()
Returns the broadcast address.
CRTP class for platform specific socket implementation.
Exception representing a Network Unreachable error (code 101 on Unix).
void enableBroadcastImpl()
Enables broadcast for this socket.
void bind(const sockaddr_in &addr)
Binds the socket to an interface.
static SocketWindows create(ULONG dst_ip, uint16_t port, std::string iface_name)
Create a new socket.
SocketWindows(int domain, int type, int protocol, ULONG dst_ip, uint16_t port, std::string iface_name)
Constructor.
void sendImpl(const std::vector< uint8_t > &sendbuf)
Sends data.
static std::map< int, std::string > getInterfaceNames()
const SOCKET & getHandleImpl() const
Returns the native socket handle.