1
0
mirror of https://github.com/solemnwarning/directplay-lite synced 2024-12-30 16:45:37 +01:00

Implement IDirectPlay8Peer::GetLocalHostAddresses() method

This commit is contained in:
Daniel Collins 2018-10-21 20:52:24 +01:00
parent b04735e8ea
commit 780a37965b
4 changed files with 136 additions and 3 deletions

View File

@ -58,7 +58,7 @@ SET TEST_OBJS=^
tests/PacketSerialiser.obj^
tests/SendQueue.obj
SET TEST_LIBS=ws2_32.lib dxguid.lib ole32.lib
SET TEST_LIBS=ws2_32.lib dxguid.lib ole32.lib iphlpapi.lib
SET HOOK_DLLS=ddraw
@ -81,7 +81,7 @@ SET HOOK_OBJS=^
src/packet.obj^
src/SendQueue.obj
SET HOOK_LIBS=ws2_32.lib dxguid.lib ole32.lib
SET HOOK_LIBS=ws2_32.lib dxguid.lib ole32.lib iphlpapi.lib
SET CFLAGS=^
/Zi^

View File

@ -1567,7 +1567,64 @@ HRESULT DirectPlay8Peer::GetPeerAddress(CONST DPNID dpnid, IDirectPlay8Address**
HRESULT DirectPlay8Peer::GetLocalHostAddresses(IDirectPlay8Address** CONST prgpAddress, DWORD* CONST pcAddress, CONST DWORD dwFlags)
{
UNIMPLEMENTED("DirectPlay8Peer::GetLocalHostAddresses");
std::unique_lock<std::mutex> l(lock);
switch(state)
{
case STATE_NEW: return DPNERR_UNINITIALIZED;
case STATE_INITIALISED: return DPNERR_NOCONNECTION;
case STATE_HOSTING: break;
case STATE_CONNECTING_TO_HOST: return DPNERR_NOCONNECTION;
case STATE_CONNECTING_TO_PEERS: return DPNERR_NOCONNECTION;
case STATE_CONNECT_FAILED: return DPNERR_NOCONNECTION;
case STATE_CONNECTED: return DPNERR_NOTHOST;
case STATE_CLOSING: return DPNERR_NOCONNECTION;
case STATE_TERMINATED: return DPNERR_NOCONNECTION;
}
if(dwFlags & DPNGETLOCALHOSTADDRESSES_COMBINED)
{
/* TODO: Implement DPNGETLOCALHOSTADDRESSES_COMBINED */
return E_NOTIMPL;
}
/* We don't support binding to specific interfaces yet, so we just return all the IPv4
* addresses assigned to the system.
*/
std::list<SystemNetworkInterface> interfaces = get_network_interfaces();
std::list<struct sockaddr_in> local_addrs;
for(auto i = interfaces.begin(); i != interfaces.end(); ++i)
{
for(auto a = i->unicast_addrs.begin(); a != i->unicast_addrs.end(); ++a)
{
if(a->ss_family == AF_INET)
{
struct sockaddr_in sa_v4 = *(struct sockaddr_in*)(&(*a));
sa_v4.sin_port = htons(local_port);
local_addrs.push_back(sa_v4);
}
}
}
if(*pcAddress < local_addrs.size())
{
*pcAddress = local_addrs.size();
return DPNERR_BUFFERTOOSMALL;
}
IDirectPlay8Address **dest = prgpAddress;
for(auto a = local_addrs.begin(); a != local_addrs.end(); ++a)
{
*dest = DirectPlay8Address::create_host_address(global_refcount, service_provider, (struct sockaddr*)(&(*a)));
++dest;
}
*pcAddress = local_addrs.size();
return S_OK;
}
HRESULT DirectPlay8Peer::Close(CONST DWORD dwFlags)

View File

@ -1,10 +1,13 @@
#include <winsock2.h>
#include <iphlpapi.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdint.h>
#include <stdio.h>
#include <vector>
#include "network.hpp"
#include "log.hpp"
int create_udp_socket(uint32_t ipaddr, uint16_t port)
{
@ -173,3 +176,66 @@ int create_discovery_socket()
return sock;
}
std::list<SystemNetworkInterface> get_network_interfaces()
{
std::vector<unsigned char> buf;
while(1)
{
ULONG size = buf.size();
ULONG err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, (IP_ADAPTER_ADDRESSES*)(buf.data()), &size);
if(err == ERROR_SUCCESS)
{
break;
}
else if(err == ERROR_NO_DATA)
{
return std::list<SystemNetworkInterface>();
}
else if(err == ERROR_BUFFER_OVERFLOW)
{
buf.resize(size);
}
else{
log_printf("GetAdaptersAddresses: %s", win_strerror(err).c_str());
return std::list<SystemNetworkInterface>();
}
}
std::list<SystemNetworkInterface> interfaces;
for(IP_ADAPTER_ADDRESSES *ipaa = (IP_ADAPTER_ADDRESSES*)(buf.data()); ipaa != NULL; ipaa = ipaa->Next)
{
if(ipaa->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
{
continue;
}
SystemNetworkInterface iface;
iface.friendly_name = ipaa->FriendlyName;
for(IP_ADAPTER_UNICAST_ADDRESS_LH *uc = ipaa->FirstUnicastAddress; uc != NULL; uc = uc->Next)
{
if(uc->Address.iSockaddrLength > sizeof(struct sockaddr_storage))
{
log_printf("Ignoring oversize address (family = %u, size = %u)",
(unsigned)(uc->Address.lpSockaddr->sa_family),
(unsigned)(uc->Address.iSockaddrLength));
continue;
}
struct sockaddr_storage ss;
memset(&ss, 0, sizeof(ss));
memcpy(&ss, uc->Address.lpSockaddr, uc->Address.iSockaddrLength);
iface.unicast_addrs.push_back(ss);
}
interfaces.push_back(iface);
}
return interfaces;
}

View File

@ -1,16 +1,26 @@
#ifndef DPLITE_NETWORK_HPP
#define DPLITE_NETWORK_HPP
#include <winsock2.h>
#include <list>
#include <stdint.h>
#include <string>
#define DISCOVERY_PORT 6073
#define DEFAULT_HOST_PORT 6072
#define LISTEN_QUEUE_SIZE 16
#define MAX_PACKET_SIZE (60 * 1024)
struct SystemNetworkInterface {
std::wstring friendly_name;
std::list<struct sockaddr_storage> unicast_addrs;
};
int create_udp_socket(uint32_t ipaddr, uint16_t port);
int create_listener_socket(uint32_t ipaddr, uint16_t port);
int create_client_socket(uint32_t local_ipaddr, uint16_t local_port);
int create_discovery_socket();
std::list<SystemNetworkInterface> get_network_interfaces();
#endif /* !DPLITE_NETWORK_HPP */