mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 05:45:38 +00:00
Add basic networking files to supermodel. Currently these are win32 specific but can port to SDL or whatever later.
This commit is contained in:
parent
080acd08c2
commit
78ae00faf1
82
Src/Network/UDPPacket.h
Normal file
82
Src/Network/UDPPacket.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
#ifndef _UDP_H_
|
||||
#define _UDP_H_
|
||||
|
||||
namespace SMUDP
|
||||
{
|
||||
struct Packet
|
||||
{
|
||||
|
||||
static const UINT32 BUFFER_SIZE = 1460;
|
||||
|
||||
UINT32 crc;
|
||||
UINT16 currentID;
|
||||
UINT16 totalIDs;
|
||||
UINT16 flags;
|
||||
UINT16 length;
|
||||
UCHAR data[1460];
|
||||
|
||||
Packet() {
|
||||
Init();
|
||||
}
|
||||
|
||||
enum class PacketFlags {
|
||||
newConnection = (1 << 0),
|
||||
resend = (1 << 1),
|
||||
ping = (1 << 2)
|
||||
};
|
||||
|
||||
void Init() {
|
||||
crc = 0;
|
||||
currentID = 0;
|
||||
totalIDs = 0;
|
||||
flags = 0;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
UINT32 CalcCRC() {
|
||||
crc = CalcCRCVal();
|
||||
}
|
||||
|
||||
UINT32 CalcCRCVal() {
|
||||
|
||||
UINT32 val = 0;
|
||||
|
||||
for (int i = 0; i < _countof(data); i++) {
|
||||
val += data[i]; // crude but will catch the odd off by one error
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool ValidateCRC() {
|
||||
return CalcCRCVal() == crc;
|
||||
}
|
||||
|
||||
void CreatePacket(PacketFlags p) {
|
||||
flags |= (UINT16)p;
|
||||
}
|
||||
|
||||
void CalcTotalIDs(int bytes) {
|
||||
totalIDs = bytes / sizeof(data);
|
||||
|
||||
if (bytes % sizeof(data)) {
|
||||
totalIDs++;
|
||||
}
|
||||
}
|
||||
|
||||
int HeaderSize() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
int Size() {
|
||||
return HeaderSize() + length;
|
||||
}
|
||||
|
||||
operator char*() { return (char*)this; }
|
||||
operator const char*() { return (char*)this; }
|
||||
};
|
||||
|
||||
typedef char PacketReply;
|
||||
}
|
||||
|
||||
#endif
|
89
Src/Network/UDPReceive.cpp
Normal file
89
Src/Network/UDPReceive.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "UDPReceive.h"
|
||||
#include "UDPPacket.h"
|
||||
|
||||
namespace SMUDP
|
||||
{
|
||||
|
||||
UDPReceive::UDPReceive()
|
||||
{
|
||||
m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create the socket
|
||||
m_readEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
WSAEventSelect(m_socket, m_readEvent, FD_READ);
|
||||
}
|
||||
|
||||
UDPReceive::~UDPReceive()
|
||||
{
|
||||
closesocket(m_socket);
|
||||
CloseHandle(m_readEvent);
|
||||
}
|
||||
|
||||
bool UDPReceive::Bind(UINT16 port)
|
||||
{
|
||||
//===========================
|
||||
int err;
|
||||
SOCKADDR_IN serverInfo = {};
|
||||
//===========================
|
||||
|
||||
serverInfo.sin_family = AF_INET; // address family Internet
|
||||
serverInfo.sin_port = htons(port); // set server’s port number
|
||||
serverInfo.sin_addr.s_addr = INADDR_ANY; // set server’s IP
|
||||
|
||||
err = bind(m_socket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));
|
||||
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
std::vector<UINT8>& UDPReceive::ReadData(int timeout)
|
||||
{
|
||||
m_data.clear();
|
||||
|
||||
while (true) {
|
||||
|
||||
//========
|
||||
DWORD res;
|
||||
//========
|
||||
|
||||
res = WaitForSingleObject(m_readEvent, timeout);
|
||||
|
||||
if (res == WAIT_OBJECT_0) {
|
||||
|
||||
//=========================
|
||||
int result;
|
||||
int slen;
|
||||
sockaddr_in si_other;
|
||||
Packet packet;
|
||||
//=========================
|
||||
|
||||
slen = sizeof(sockaddr_in);
|
||||
|
||||
result = recvfrom(m_socket, packet, sizeof(packet), 0, (struct sockaddr *) &si_other, &slen);
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
auto error = WSAGetLastError(); // clear error code
|
||||
m_data.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
// copy data to array
|
||||
m_data.insert(m_data.end(), packet.data, packet.data + packet.length);
|
||||
|
||||
PacketReply r = 1;
|
||||
result = sendto(m_socket, &r, sizeof(r), 0, (struct sockaddr *)&si_other, sizeof(SOCKADDR_IN));
|
||||
|
||||
if (packet.currentID + 1 == packet.totalIDs) {
|
||||
break; // reached the end
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_data.clear(); // reset any memory because we have failed
|
||||
break; // timeout
|
||||
}
|
||||
}
|
||||
|
||||
return m_data;
|
||||
}
|
||||
|
||||
}
|
30
Src/Network/UDPReceive.h
Normal file
30
Src/Network/UDPReceive.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef _UDP_RECEIVE_H_
|
||||
#define _UDP_RECEIVE_H_
|
||||
|
||||
#include "UDPPacket.h"
|
||||
#include "WinSockWrap.h"
|
||||
#include <vector>
|
||||
|
||||
namespace SMUDP
|
||||
{
|
||||
class UDPReceive
|
||||
{
|
||||
public:
|
||||
UDPReceive();
|
||||
~UDPReceive();
|
||||
|
||||
bool Bind(UINT16 port);
|
||||
|
||||
std::vector<UINT8>& ReadData(int timeout);
|
||||
|
||||
private:
|
||||
|
||||
std::vector<UINT8> m_data;
|
||||
SOCKET m_socket;
|
||||
HANDLE m_readEvent;
|
||||
HANDLE m_exitEvent;
|
||||
WinSockWrap m_winSockWrap;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
133
Src/Network/UDPSend.cpp
Normal file
133
Src/Network/UDPSend.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "UDPSend.h"
|
||||
#include <WS2tcpip.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace SMUDP
|
||||
{
|
||||
|
||||
UDPSend::UDPSend()
|
||||
{
|
||||
m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // create the socket
|
||||
m_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
WSAEventSelect(m_socket, m_event, FD_READ | FD_WRITE);
|
||||
}
|
||||
|
||||
UDPSend::~UDPSend()
|
||||
{
|
||||
closesocket(m_socket);
|
||||
CloseHandle(m_event);
|
||||
}
|
||||
|
||||
bool UDPSend::Send(const char* ip, int port, int length, const void *data, int timeout)
|
||||
{
|
||||
UINT8* pData = (UINT8*)data;
|
||||
|
||||
Packet packet;
|
||||
packet.CalcTotalIDs(length);
|
||||
|
||||
SOCKADDR_IN address = {};
|
||||
address.sin_family = AF_INET; // address family Internet
|
||||
address.sin_port = htons(port); // set server’s port number
|
||||
inet_pton(AF_INET, ip, &address.sin_addr);
|
||||
|
||||
while (length > 0) {
|
||||
|
||||
packet.flags = 0; // reset the flags (not used currently)
|
||||
|
||||
if (length > packet.BUFFER_SIZE) {
|
||||
packet.length = packet.BUFFER_SIZE;
|
||||
}
|
||||
else {
|
||||
packet.length = length;
|
||||
}
|
||||
|
||||
memcpy(packet.data, pData, packet.length);
|
||||
|
||||
int sent = SendDataPacket(packet, m_socket, address, m_event);
|
||||
|
||||
if (sent == SOCKET_ERROR) {
|
||||
return false; // send failure
|
||||
}
|
||||
|
||||
if (!ProcessReply(m_socket, m_event, timeout)) {
|
||||
return false; // reply failure
|
||||
}
|
||||
|
||||
length -= packet.length;
|
||||
pData += packet.length;
|
||||
|
||||
packet.currentID++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UDPSend::WaitForEvent(SOCKET s, HANDLE hEvent, long nEvents, int timeout)
|
||||
{
|
||||
//========
|
||||
DWORD res;
|
||||
//========
|
||||
|
||||
res = WaitForSingleObject(hEvent, timeout);
|
||||
|
||||
if (res == WAIT_OBJECT_0) {
|
||||
|
||||
WSANETWORKEVENTS events = {};
|
||||
WSAEnumNetworkEvents(s, hEvent, &events);
|
||||
|
||||
if (events.lNetworkEvents & nEvents) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int UDPSend::SendDataPacket(Packet &p, SOCKET s, SOCKADDR_IN& address, HANDLE events)
|
||||
{
|
||||
while (true) {
|
||||
|
||||
int sent = sendto(s, p, p.Size(), 0, (struct sockaddr *)&address, sizeof(SOCKADDR_IN));
|
||||
|
||||
if (sent == SOCKET_ERROR) {
|
||||
|
||||
int error = WSAGetLastError(); // clear error code
|
||||
|
||||
if (error == WSAEWOULDBLOCK) {
|
||||
WaitForEvent(s, events, FD_WRITE, INFINITE); // wait until write event is triggered
|
||||
continue;
|
||||
}
|
||||
|
||||
return sent; // send failure
|
||||
}
|
||||
|
||||
return p.Size();
|
||||
}
|
||||
}
|
||||
|
||||
bool UDPSend::ProcessReply(SOCKET s, HANDLE event, int timeout)
|
||||
{
|
||||
//=================
|
||||
int result;
|
||||
PacketReply rp;
|
||||
//=================
|
||||
|
||||
if (WaitForEvent(s, event, FD_READ, timeout)) {
|
||||
|
||||
result = recv(s, &rp, sizeof(rp), 0);
|
||||
|
||||
if (result == SOCKET_ERROR) {
|
||||
auto error = WSAGetLastError(); // clear error code
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
29
Src/Network/UDPSend.h
Normal file
29
Src/Network/UDPSend.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef _UDPSEND_H_
|
||||
#define _UDPSEND_H_
|
||||
|
||||
#include "UDPPacket.h"
|
||||
#include "WinSockWrap.h"
|
||||
|
||||
namespace SMUDP
|
||||
{
|
||||
class UDPSend
|
||||
{
|
||||
public:
|
||||
UDPSend();
|
||||
~UDPSend();
|
||||
|
||||
bool Send(const char* address, int port, int length, const void *data, int timeout);
|
||||
|
||||
private:
|
||||
|
||||
bool WaitForEvent(SOCKET s, HANDLE hEvent, long nEvents, int timeout);
|
||||
bool ProcessReply(SOCKET s, HANDLE event, int timeout);
|
||||
int SendDataPacket(Packet& p, SOCKET s, SOCKADDR_IN& address, HANDLE events);
|
||||
|
||||
SOCKET m_socket;
|
||||
HANDLE m_event;
|
||||
WinSockWrap m_winsockWrap;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
28
Src/Network/WinSockWrap.cpp
Normal file
28
Src/Network/WinSockWrap.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "WinSockWrap.h"
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
WinSockWrap::WinSockWrap()
|
||||
{
|
||||
//==============
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
//==============
|
||||
|
||||
m_count = 0;
|
||||
|
||||
err = WSAStartup(MAKEWORD(2, 2), &wsaData); // don't really need to care for checking supported version, we should be good from win95 onwards
|
||||
|
||||
if (err == 0) {
|
||||
m_count++;
|
||||
}
|
||||
}
|
||||
|
||||
WinSockWrap::~WinSockWrap()
|
||||
{
|
||||
if (m_count) {
|
||||
WSACleanup();
|
||||
}
|
||||
}
|
14
Src/Network/WinSockWrap.h
Normal file
14
Src/Network/WinSockWrap.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef _WINSOCKWRAP_H_
|
||||
#define _WINSOCKWRAP_H_
|
||||
|
||||
class WinSockWrap
|
||||
{
|
||||
public:
|
||||
WinSockWrap();
|
||||
~WinSockWrap();
|
||||
|
||||
private:
|
||||
int m_count;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -345,6 +345,9 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi
|
|||
<ClCompile Include="..\Src\Model3\RTC72421.cpp" />
|
||||
<ClCompile Include="..\Src\Model3\SoundBoard.cpp" />
|
||||
<ClCompile Include="..\Src\Model3\TileGen.cpp" />
|
||||
<ClCompile Include="..\Src\Network\UDPReceive.cpp" />
|
||||
<ClCompile Include="..\Src\Network\UDPSend.cpp" />
|
||||
<ClCompile Include="..\Src\Network\WinSockWrap.cpp" />
|
||||
<ClCompile Include="..\Src\OSD\Logger.cpp" />
|
||||
<ClCompile Include="..\Src\OSD\Outputs.cpp" />
|
||||
<ClCompile Include="..\Src\OSD\SDL\Audio.cpp" />
|
||||
|
@ -569,6 +572,10 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi
|
|||
<ClInclude Include="..\Src\Model3\RTC72421.h" />
|
||||
<ClInclude Include="..\Src\Model3\SoundBoard.h" />
|
||||
<ClInclude Include="..\Src\Model3\TileGen.h" />
|
||||
<ClInclude Include="..\Src\Network\UDPPacket.h" />
|
||||
<ClInclude Include="..\Src\Network\UDPReceive.h" />
|
||||
<ClInclude Include="..\Src\Network\UDPSend.h" />
|
||||
<ClInclude Include="..\Src\Network\WinSockWrap.h" />
|
||||
<ClInclude Include="..\Src\OSD\Audio.h" />
|
||||
<ClInclude Include="..\Src\OSD\Logger.h" />
|
||||
<ClInclude Include="..\Src\OSD\Outputs.h" />
|
||||
|
|
|
@ -132,6 +132,12 @@
|
|||
<Filter Include="Source Files\Util">
|
||||
<UniqueIdentifier>{ea54ba9d-b27d-48e1-b576-fd245fd4d6c3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Network">
|
||||
<UniqueIdentifier>{5a9e8f32-b937-4026-86c3-485581ae15c1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Network">
|
||||
<UniqueIdentifier>{284c6ebd-9a90-4283-9ee6-ea097974c8f4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\Src\BlockFile.cpp">
|
||||
|
@ -446,6 +452,15 @@
|
|||
<ClCompile Include="..\Src\Sound\MPEG\amp_audio.cpp">
|
||||
<Filter>Source Files\Sound\MPEG</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Src\Network\UDPReceive.cpp">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Src\Network\UDPSend.cpp">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Src\Network\WinSockWrap.cpp">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="..\Src\CPU\68K\Turbo68K\Turbo68K.asm">
|
||||
|
@ -829,6 +844,18 @@
|
|||
<ClInclude Include="..\Src\Sound\MPEG\amp_audio.h">
|
||||
<Filter>Header Files\Sound\MPEG</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\UDPPacket.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\UDPReceive.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\UDPSend.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Src\Network\WinSockWrap.h">
|
||||
<Filter>Header Files\Network</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\Src\Debugger\ReadMe.txt">
|
||||
|
|
Loading…
Reference in a new issue