mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-20 20:23:57 +00:00
Implement UDP recvfrom support
This commit is contained in:
@@ -40,6 +40,12 @@ public:
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T read_memory(const void* address)
|
||||
{
|
||||
return this->read_memory<T>(reinterpret_cast<uint64_t>(address));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_memory(const uint64_t address, const T& value)
|
||||
{
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace
|
||||
void create(const io_device_creation_data& data) override
|
||||
{
|
||||
const auto creation_data = get_creation_data(data);
|
||||
// TODO: values map to windows values; might not be the case for other platforms
|
||||
const auto sock = socket(creation_data.address_family, creation_data.type, creation_data.protocol);
|
||||
if (sock == INVALID_SOCKET)
|
||||
{
|
||||
@@ -91,6 +92,8 @@ namespace
|
||||
return this->ioctl_bind(c);
|
||||
case AFD_SEND_DATAGRAM:
|
||||
return this->ioctl_send_datagram(c);
|
||||
case AFD_RECEIVE_DATAGRAM:
|
||||
return this->ioctl_receive_datagram(c);
|
||||
case AFD_SET_CONTEXT:
|
||||
return STATUS_SUCCESS;
|
||||
case AFD_GET_INFORMATION:
|
||||
@@ -127,6 +130,63 @@ namespace
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS ioctl_receive_datagram(const io_device_context& c) const
|
||||
{
|
||||
if (c.input_buffer_length < sizeof(AFD_RECV_DATAGRAM_INFO))
|
||||
{
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
const auto receive_info = emulator_object<AFD_RECV_DATAGRAM_INFO>{c.emu, c.input_buffer}.read();
|
||||
const auto buffer = emulator_object<WSABUF>{c.emu, receive_info.BufferArray}.read(0);
|
||||
|
||||
std::vector<std::byte> address{};
|
||||
|
||||
ULONG address_length = 0x1000;
|
||||
if (receive_info.AddressLength)
|
||||
{
|
||||
address_length = c.emu.read_memory<ULONG>(receive_info.AddressLength);
|
||||
}
|
||||
|
||||
address.resize(std::clamp(address_length, 1UL, 0x1000UL));
|
||||
|
||||
if (!buffer.len || buffer.len > 0x10000 || !buffer.buf)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
int fromlength = static_cast<int>(address.size());
|
||||
|
||||
std::vector<char> data{};
|
||||
data.resize(buffer.len);
|
||||
|
||||
const auto recevied_data = recvfrom(*this->s, data.data(), static_cast<int>(data.size()), 0,
|
||||
reinterpret_cast<sockaddr*>(address.data()), &fromlength);
|
||||
|
||||
if (recevied_data < 0)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
c.emu.write_memory(reinterpret_cast<uint64_t>(buffer.buf), data.data(),
|
||||
std::min(data.size(), static_cast<size_t>(recevied_data)));
|
||||
|
||||
if (receive_info.Address && address_length)
|
||||
{
|
||||
c.emu.write_memory(reinterpret_cast<uint64_t>(receive_info.Address), address.data(),
|
||||
std::min(address.size(), static_cast<size_t>(address_length)));
|
||||
}
|
||||
|
||||
if (c.io_status_block)
|
||||
{
|
||||
IO_STATUS_BLOCK block{};
|
||||
block.Information = static_cast<uint32_t>(recevied_data);
|
||||
c.io_status_block.write(block);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS ioctl_send_datagram(const io_device_context& c) const
|
||||
{
|
||||
if (c.input_buffer_length < sizeof(AFD_SEND_DATAGRAM_INFO))
|
||||
|
||||
@@ -35,6 +35,14 @@ typedef struct _TDI_REQUEST_SEND_DATAGRAM
|
||||
PTDI_CONNECTION_INFORMATION SendDatagramInformation;
|
||||
} TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM;
|
||||
|
||||
typedef struct _AFD_SEND_INFO
|
||||
{
|
||||
LPWSABUF BufferArray;
|
||||
ULONG BufferCount;
|
||||
ULONG AfdFlags;
|
||||
ULONG TdiFlags;
|
||||
} AFD_SEND_INFO, *PAFD_SEND_INFO;
|
||||
|
||||
typedef struct _AFD_SEND_DATAGRAM_INFO
|
||||
{
|
||||
LPWSABUF BufferArray;
|
||||
@@ -44,6 +52,24 @@ typedef struct _AFD_SEND_DATAGRAM_INFO
|
||||
TDI_CONNECTION_INFORMATION TdiConnInfo;
|
||||
} AFD_SEND_DATAGRAM_INFO, *PAFD_SEND_DATAGRAM_INFO;
|
||||
|
||||
typedef struct _AFD_RECV_INFO
|
||||
{
|
||||
LPWSABUF BufferArray;
|
||||
ULONG BufferCount;
|
||||
ULONG AfdFlags;
|
||||
ULONG TdiFlags;
|
||||
} AFD_RECV_INFO, *PAFD_RECV_INFO;
|
||||
|
||||
typedef struct _AFD_RECV_DATAGRAM_INFO
|
||||
{
|
||||
LPWSABUF BufferArray;
|
||||
ULONG BufferCount;
|
||||
ULONG AfdFlags;
|
||||
ULONG TdiFlags;
|
||||
PVOID Address;
|
||||
PULONG AddressLength;
|
||||
} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO;
|
||||
|
||||
#define _AFD_REQUEST(ioctl) \
|
||||
((((ULONG)(ioctl)) >> 2) & 0x03FF)
|
||||
#define _AFD_BASE(ioctl) \
|
||||
|
||||
Reference in New Issue
Block a user