Removed all code from header files (Utilities project)

This commit is contained in:
Souryo 2015-07-11 10:01:06 -04:00
parent e7e77ccfa7
commit bb52c3f69c
21 changed files with 536 additions and 469 deletions

View File

@ -28,7 +28,7 @@ GameServer::~GameServer()
void GameServer::AcceptConnections()
{
while(true) {
shared_ptr<Socket> socket = _listener->Accept(NULL, NULL);
shared_ptr<Socket> socket = _listener->Accept();
if(!socket->ConnectionError()) {
_openConnections.push_back(shared_ptr<GameServerConnection>(new GameServerConnection(socket, 1, this)));
std::cout << "Client connected." << std::endl;

View File

@ -27,7 +27,7 @@ ButtonState StandardController::GetButtonState()
{
ButtonState state;
for(int i = 0, len = _keyMappings.size(); i < len; i++) {
for(size_t i = 0, len = _keyMappings.size(); i < len; i++) {
KeyMapping keyMapping = _keyMappings[i];
state.A |= ControlManager::IsKeyPressed(keyMapping.A);

View File

@ -7,11 +7,6 @@
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <tchar.h>
#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64

40
Utilities/CRC32.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "stdafx.h"
#include "CRC32.h"
void CRC32::AddData(const uint8_t* pData, const std::streamoff length)
{
uint8_t* pCur = (uint8_t*)pData;
for(std::streamoff remaining = length; remaining--; ++pCur) {
_crc = (_crc >> 8) ^ kCrc32Table[(_crc ^ *pCur) & 0xff];
}
}
uint32_t CRC32::GetCRC(uint8_t *buffer, std::streamoff length)
{
CRC32 crc;
crc.AddData(buffer, length);
return crc._crc;
}
uint32_t CRC32::GetCRC(string filename)
{
uint32_t crc = 0;
ifstream file(filename, std::ios::in | std::ios::binary);
if(file) {
file.seekg(0, std::ios::end);
std::streamoff fileSize = file.tellg();
file.seekg(0, std::ios::beg);
uint8_t* buffer = new uint8_t[(uint32_t)fileSize];
file.read((char*)buffer, fileSize);
file.close();
crc = GetCRC(buffer, fileSize);
delete[] buffer;
}
return crc;
}

View File

@ -75,41 +75,9 @@ class CRC32
private:
uint32_t _crc = 0xFFFFFFFF;
void AddData(const uint8_t* pData, const std::streamoff length)
{
uint8_t* pCur = (uint8_t*)pData;
for(std::streamoff remaining = length; remaining--; ++pCur) {
_crc = (_crc >> 8) ^ kCrc32Table[(_crc ^ *pCur) & 0xff];
}
}
void AddData(const uint8_t* pData, const std::streamoff length);
public:
static uint32_t GetCRC(uint8_t *buffer, std::streamoff length)
{
CRC32 crc;
crc.AddData(buffer, length);
return crc._crc;
}
static uint32_t GetCRC(string filename)
{
uint32_t crc = 0;
ifstream file(filename, ios::in | ios::binary);
if(file) {
file.seekg(0, ios::end);
std::streamoff fileSize = file.tellg();
file.seekg(0, ios::beg);
uint8_t* buffer = new uint8_t[(uint32_t)fileSize];
file.read((char*)buffer, fileSize);
file.close();
crc = GetCRC(buffer, fileSize);
delete[] buffer;
}
return crc;
}
static uint32_t GetCRC(uint8_t *buffer, std::streamoff length);
static uint32_t GetCRC(string filename);
};

View File

@ -1,5 +1,4 @@
#include "stdafx.h"
#include <commdlg.h>
#include <shlobj.h>
#include "FolderUtilities.h"
#include "UTF8Util.h"

20
Utilities/PNGWriter.cpp Normal file
View File

@ -0,0 +1,20 @@
#include "stdafx.h"
#include "PNGWriter.h"
#include "miniz.h"
bool PNGWriter::WritePNG(string filename, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel)
{
size_t pngSize = 0;
void *pngData = tdefl_write_image_to_png_file_in_memory_ex(buffer, xSize, ySize, bitsPerPixel/8, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE);
if(!pngData) {
std::cout << "tdefl_write_image_to_png_file_in_memory_ex() failed!" << std::endl;
return false;
} else {
ofstream file(filename, std::ios::out | std::ios::binary);
file.write((char*)pngData, pngSize);
file.close();
mz_free(pngData);
return true;
}
}

View File

@ -1,24 +1,8 @@
#pragma once
#include "stdafx.h"
#include "miniz.h"
class PNGWriter
{
public:
static bool WritePNG(string filename, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32)
{
size_t pngSize = 0;
void *pngData = tdefl_write_image_to_png_file_in_memory_ex(buffer, xSize, ySize, bitsPerPixel/8, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE);
if(!pngData) {
std::cout << "tdefl_write_image_to_png_file_in_memory_ex() failed!" << std::endl;
return false;
} else {
ofstream file(filename, ios::out | ios::binary);
file.write((char*)pngData, pngSize);
file.close();
mz_free(pngData);
return true;
}
}
static bool WritePNG(string filename, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32);
};

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "SimpleLock.h"
#include <Windows.h>
SimpleLock::SimpleLock()
{

View File

@ -4,7 +4,7 @@
class SimpleLock
{
private:
DWORD _holderThreadID;
uint32_t _holderThreadID;
uint32_t _lockCount;
atomic_flag _lock;

223
Utilities/Socket.cpp Normal file
View File

@ -0,0 +1,223 @@
#include "stdafx.h"
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Windows.h>
#include "UPnPPortMapper.h"
#include "Socket.h"
Socket::Socket()
{
WSADATA wsaDat;
if(WSAStartup(MAKEWORD(2, 2), &wsaDat) != 0) {
std::cout << "WSAStartup failed." << std::endl;
SetConnectionErrorFlag();
} else {
_cleanupWSA = true;
_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(_socket == INVALID_SOCKET) {
std::cout << "Socket creation failed." << std::endl;
SetConnectionErrorFlag();
} else {
SetSocketOptions();
}
}
_sendBuffer = new char[200000];
_bufferPosition = 0;
}
Socket::Socket(uintptr_t socket)
{
_socket = socket;
if(socket == INVALID_SOCKET) {
SetConnectionErrorFlag();
} else {
SetSocketOptions();
}
_sendBuffer = new char[200000];
_bufferPosition = 0;
}
Socket::~Socket()
{
if(_UPnPPort != -1) {
UPnPPortMapper::RemoveNATPortMapping(_UPnPPort, IPProtocol::TCP);
}
if(_socket != INVALID_SOCKET) {
Close();
}
if(_cleanupWSA) {
WSACleanup();
}
delete[] _sendBuffer;
}
void Socket::SetSocketOptions()
{
//Non-blocking mode
u_long iMode = 1;
ioctlsocket(_socket, FIONBIO, &iMode);
//Set send/recv buffers to 256k
int bufferSize = 0x40000;
setsockopt(_socket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(int));
setsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (char*)&bufferSize, sizeof(int));
//Disable nagle's algorithm to improve latency
u_long value = 1;
setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&value, sizeof(value));
}
void Socket::SetConnectionErrorFlag()
{
_connectionError = true;
}
void Socket::Close()
{
std::cout << "Socket closed." << std::endl;
shutdown(_socket, SD_SEND);
closesocket(_socket);
SetConnectionErrorFlag();
}
bool Socket::ConnectionError()
{
return _connectionError;
}
void Socket::Bind(uint16_t port)
{
SOCKADDR_IN serverInf;
serverInf.sin_family = AF_INET;
serverInf.sin_addr.s_addr = INADDR_ANY;
serverInf.sin_port = htons(port);
if(UPnPPortMapper::AddNATPortMapping(port, port, IPProtocol::TCP)) {
_UPnPPort = port;
}
if(bind(_socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR) {
std::cout << "Unable to bind socket." << std::endl;
SetConnectionErrorFlag();
}
}
bool Socket::Connect(const char* hostname, uint16_t port)
{
// Resolve IP address for hostname
struct hostent *host;
if((host = gethostbyname(hostname)) == NULL) {
std::cout << "Failed to resolve hostname." << std::endl;
SetConnectionErrorFlag();
} else {
// Setup our socket address structure
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(port);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
u_long iMode = 0;
ioctlsocket(_socket, FIONBIO, &iMode);
// Attempt to connect to server
if(connect(_socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR) {
std::cout << "Failed to establish connection with server." << std::endl;
SetConnectionErrorFlag();
} else {
iMode = 1;
ioctlsocket(_socket, FIONBIO, &iMode);
return true;
}
}
return false;
}
void Socket::Listen(int backlog)
{
if(listen(_socket, backlog) == SOCKET_ERROR) {
std::cout << "listen failed." << std::endl;
SetConnectionErrorFlag();
}
}
shared_ptr<Socket> Socket::Accept()
{
SOCKET socket = accept(_socket, nullptr, nullptr);
return shared_ptr<Socket>(new Socket(socket));
}
int Socket::Send(char *buf, int len, int flags)
{
int retryCount = 15;
int nError = 0;
int returnVal;
do {
//Loop until everything has been sent (shouldn't loop at all in the vast majority of cases)
if(nError == WSAEWOULDBLOCK) {
retryCount--;
if(retryCount == 0) {
//Connection seems dead, close it.
std::cout << "Unable to send data, closing socket." << std::endl;
Close();
return 0;
}
}
returnVal = send(_socket, buf, len, flags);
nError = WSAGetLastError();
if(nError != 0) {
if(nError != WSAEWOULDBLOCK) {
SetConnectionErrorFlag();
} else {
if(returnVal > 0) {
//Sent partial data, adjust pointer & length
buf += returnVal;
len -= returnVal;
}
}
}
} while(nError == WSAEWOULDBLOCK);
return returnVal;
}
void Socket::BufferedSend(char *buf, int len)
{
memcpy(_sendBuffer+_bufferPosition, buf, len);
_bufferPosition += len;
}
void Socket::SendBuffer()
{
Send(_sendBuffer, _bufferPosition, 0);
_bufferPosition = 0;
}
int Socket::Recv(char *buf, int len, int flags)
{
int returnVal = recv(_socket, buf, len, flags);
int nError = WSAGetLastError();
if(nError != WSAEWOULDBLOCK && nError != 0) {
SetConnectionErrorFlag();
}
if(returnVal == 0) {
//Socket closed
std::cout << "Socket closed by peer." << std::endl;
Close();
}
return returnVal;
}

View File

@ -1,13 +1,11 @@
#pragma once
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#include "stdafx.h"
#include "UPnPPortMapper.h"
#include <winsock2.h>
class Socket
{
private:
SOCKET _socket = INVALID_SOCKET;
uintptr_t _socket = ~0;
bool _connectionError = false;
bool _cleanupWSA = false;
char* _sendBuffer;
@ -15,218 +13,23 @@ private:
int32_t _UPnPPort = -1;
public:
Socket()
{
WSADATA wsaDat;
if(WSAStartup(MAKEWORD(2, 2), &wsaDat) != 0) {
std::cout << "WSAStartup failed." << std::endl;
SetConnectionErrorFlag();
} else {
_cleanupWSA = true;
Socket();
Socket(uintptr_t socket);
~Socket();
_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(_socket == INVALID_SOCKET) {
std::cout << "Socket creation failed." << std::endl;
SetConnectionErrorFlag();
} else {
SetSocketOptions();
}
}
void SetSocketOptions();
void SetConnectionErrorFlag();
_sendBuffer = new char[200000];
_bufferPosition = 0;
}
void Close();
bool ConnectionError();
Socket(SOCKET socket)
{
_socket = socket;
void Bind(uint16_t port);
bool Connect(const char* hostname, uint16_t port);
void Listen(int backlog);
shared_ptr<Socket> Accept();
if(socket == INVALID_SOCKET) {
SetConnectionErrorFlag();
} else {
SetSocketOptions();
}
_sendBuffer = new char[200000];
_bufferPosition = 0;
}
~Socket()
{
if(_UPnPPort != -1) {
UPnPPortMapper::RemoveNATPortMapping(_UPnPPort, IPProtocol::TCP);
}
if(_socket != INVALID_SOCKET) {
Close();
}
if(_cleanupWSA) {
WSACleanup();
}
delete[] _sendBuffer;
}
void SetSocketOptions()
{
//Non-blocking mode
u_long iMode = 1;
ioctlsocket(_socket, FIONBIO, &iMode);
//Set send/recv buffers to 256k
int bufferSize = 0x40000;
setsockopt(_socket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(int));
setsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (char*)&bufferSize, sizeof(int));
//Disable nagle's algorithm to improve latency
u_long value = 1;
setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&value, sizeof(value));
}
void SetConnectionErrorFlag()
{
_connectionError = true;
}
void Close()
{
std::cout << "Socket closed." << std::endl;
shutdown(_socket, SD_SEND);
closesocket(_socket);
SetConnectionErrorFlag();
}
bool ConnectionError()
{
return _connectionError;
}
void Bind(u_short port)
{
SOCKADDR_IN serverInf;
serverInf.sin_family = AF_INET;
serverInf.sin_addr.s_addr = INADDR_ANY;
serverInf.sin_port = htons(port);
if(UPnPPortMapper::AddNATPortMapping(port, port, IPProtocol::TCP)) {
_UPnPPort = port;
}
if(bind(_socket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR) {
std::cout << "Unable to bind socket." << std::endl;
SetConnectionErrorFlag();
}
}
bool Connect(const char* hostname, u_short port)
{
// Resolve IP address for hostname
struct hostent *host;
if((host = gethostbyname(hostname)) == NULL) {
std::cout << "Failed to resolve hostname." << std::endl;
SetConnectionErrorFlag();
} else {
// Setup our socket address structure
SOCKADDR_IN SockAddr;
SockAddr.sin_port = htons(port);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
u_long iMode = 0;
ioctlsocket(_socket, FIONBIO, &iMode);
// Attempt to connect to server
if(connect(_socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR) {
std::cout << "Failed to establish connection with server." << std::endl;
SetConnectionErrorFlag();
} else {
iMode = 1;
ioctlsocket(_socket, FIONBIO, &iMode);
return true;
}
}
return false;
}
void Listen(int backlog)
{
if(listen(_socket, backlog) == SOCKET_ERROR) {
std::cout << "listen failed." << std::endl;
SetConnectionErrorFlag();
}
}
shared_ptr<Socket> Accept(sockaddr* addr, int *addrlen)
{
SOCKET socket = accept(_socket, addr, addrlen);
return shared_ptr<Socket>(new Socket(socket));
}
int Send(char *buf, int len, int flags)
{
int retryCount = 15;
int nError = 0;
int returnVal;
do {
//Loop until everything has been sent (shouldn't loop at all in the vast majority of cases)
if(nError == WSAEWOULDBLOCK) {
retryCount--;
if(retryCount == 0) {
//Connection seems dead, close it.
std::cout << "Unable to send data, closing socket." << std::endl;
Close();
return 0;
}
}
returnVal = send(_socket, buf, len, flags);
nError = WSAGetLastError();
if(nError != 0) {
if(nError != WSAEWOULDBLOCK) {
SetConnectionErrorFlag();
} else {
if(returnVal > 0) {
//Sent partial data, adjust pointer & length
buf += returnVal;
len -= returnVal;
}
}
}
} while(nError == WSAEWOULDBLOCK);
return returnVal;
}
void BufferedSend(char *buf, int len)
{
memcpy(_sendBuffer+_bufferPosition, buf, len);
_bufferPosition += len;
}
void SendBuffer()
{
Send(_sendBuffer, _bufferPosition, 0);
_bufferPosition = 0;
}
int Recv(char *buf, int len, int flags)
{
int returnVal = recv(_socket, buf, len, flags);
int nError = WSAGetLastError();
if(nError != WSAEWOULDBLOCK && nError != 0) {
SetConnectionErrorFlag();
}
if(returnVal == 0) {
//Socket closed
std::cout << "Socket closed by peer." << std::endl;
Close();
}
return returnVal;
}
int Send(char *buf, int len, int flags);
void BufferedSend(char *buf, int len);
void SendBuffer();
int Recv(char *buf, int len, int flags);
};

31
Utilities/Timer.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "stdafx.h"
#include <Windows.h>
#include "Timer.h"
Timer::Timer()
{
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li)) {
throw;
}
_frequency = double(li.QuadPart) / 1000.0;
QueryPerformanceCounter(&li);
_start = li.QuadPart;
}
void Timer::Reset()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
_start = li.QuadPart;
}
double Timer::GetElapsedMS()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart - _start) / _frequency;
}

View File

@ -4,32 +4,10 @@ class Timer
{
private:
double _frequency = 0.0;
LARGE_INTEGER _start;
uint64_t _start;
public:
Timer() {
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li)) {
throw;
}
_frequency = double(li.QuadPart) / 1000.0;
QueryPerformanceCounter(&li);
_start = li;
}
void Reset()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
_start = li;
}
double GetElapsedMS()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart - _start.QuadPart) / _frequency;
}
Timer();
void Reset();
double GetElapsedMS();
};

View File

@ -0,0 +1,126 @@
#include "stdafx.h"
#include <winsock2.h>
#include <natupnp.h>
#include <ws2tcpip.h>
#include "UPnPPortMapper.h"
bool UPnPPortMapper::AddNATPortMapping(uint16_t internalPort, uint16_t externalPort, IPProtocol protocol)
{
bool result = false;
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
IUPnPNAT *nat = nullptr;
HRESULT hResult = CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat);
BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP");
if(SUCCEEDED(hResult) && nat) {
IStaticPortMappingCollection *spmc = nullptr;
hResult = nat->get_StaticPortMappingCollection(&spmc);
if(SUCCEEDED(hResult) && spmc) {
IStaticPortMapping *spm = nullptr;
hResult = spmc->get_Item(externalPort, proto, &spm);
if(spm != nullptr) {
//An identical mapping already exists, remove it
if(RemoveNATPortMapping(externalPort, protocol)) {
std::cout << "Removed existing UPnP mapping." << std::endl;
spm->Release();
spm = nullptr;
}
}
if(!SUCCEEDED(hResult) || spm == nullptr) {
std::cout << "Attempting to automatically forward port via UPnP..." << std::endl;
wstring localIP = GetLocalIP();
BSTR desc = SysAllocString(L"NESEmu for NetPlay");
BSTR clientStr = SysAllocString(localIP.c_str());
hResult = spmc->Add(externalPort, proto, internalPort, clientStr, true, desc, &spm);
SysFreeString(clientStr);
SysFreeString(desc);
if(SUCCEEDED(hResult) && spm) {
//Successfully added a new port mapping
std::cout << std::dec << "Forwarded port " << externalPort << " to IP ";
std::wcout << localIP.c_str() << std::endl;
spm->Release();
result = true;
} else {
std::cout << "Unable to add UPnP port mapping. ";
std::cout << "IP: ";
std::wcout << localIP.c_str();
std::cout << " HRESULT: 0x" << std::hex << hResult << std::endl;
}
} else {
std::cout << "Unable to add UPnP port mapping." << std::endl;
}
spmc->Release();
}
nat->Release();
}
SysFreeString(proto);
CoUninitialize();
return result;
}
bool UPnPPortMapper::RemoveNATPortMapping(uint16_t externalPort, IPProtocol protocol)
{
IUPnPNAT *nat = nullptr;
IStaticPortMappingCollection *spmc;
bool result = false;
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
HRESULT hResult = ::CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat);
BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP");
if(SUCCEEDED(hResult) && nat) {
hResult = nat->get_StaticPortMappingCollection(&spmc);
if(SUCCEEDED(hResult) && spmc) {
spmc->Remove(externalPort, proto);
spmc->Release();
result = true;
}
nat->Release();
}
SysFreeString(proto);
CoUninitialize();
return result;
}
wstring UPnPPortMapper::GetLocalIP()
{
wstring localIP;
ADDRINFOW *result = nullptr;
ADDRINFOW hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
wchar_t hostName[255];
DWORD hostSize = 255;
GetComputerName(hostName, &hostSize);
if(GetAddrInfoW(hostName, nullptr, &hints, &result) == 0) {
wchar_t ipAddr[255];
DWORD ipSize = 255;
if(WSAAddressToString(result->ai_addr, (DWORD)result->ai_addrlen, nullptr, ipAddr, &ipSize) == 0) {
localIP = ipAddr;
}
FreeAddrInfoW(result);
}
return localIP;
}

View File

@ -2,9 +2,6 @@
#include "stdafx.h"
#include <natupnp.h>
#include <ws2tcpip.h>
using std::wstring;
enum class IPProtocol
@ -15,125 +12,10 @@ enum class IPProtocol
class UPnPPortMapper
{
private:
static wstring GetLocalIP();
public:
static bool AddNATPortMapping(WORD internalPort, WORD externalPort, IPProtocol protocol)
{
bool result = false;
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
IUPnPNAT *nat = nullptr;
HRESULT hResult = CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat);
BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP");
if(SUCCEEDED(hResult) && nat) {
IStaticPortMappingCollection *spmc = nullptr;
hResult = nat->get_StaticPortMappingCollection(&spmc);
if(SUCCEEDED(hResult) && spmc) {
IStaticPortMapping *spm = nullptr;
hResult = spmc->get_Item(externalPort, proto, &spm);
if(spm != nullptr) {
//An identical mapping already exists, remove it
if(RemoveNATPortMapping(externalPort, protocol)) {
std::cout << "Removed existing UPnP mapping." << std::endl;
spm->Release();
spm = nullptr;
}
}
if(!SUCCEEDED(hResult) || spm == nullptr) {
std::cout << "Attempting to automatically forward port via UPnP..." << std::endl;
wstring localIP = GetLocalIP();
BSTR desc = SysAllocString(L"NESEmu for NetPlay");
BSTR clientStr = SysAllocString(localIP.c_str());
hResult = spmc->Add(externalPort, proto, internalPort, clientStr, true, desc, &spm);
SysFreeString(clientStr);
SysFreeString(desc);
if(SUCCEEDED(hResult) && spm) {
//Successfully added a new port mapping
std::cout << std::dec << "Forwarded port " << externalPort << " to IP ";
std::wcout << localIP.c_str() << std::endl;
spm->Release();
result = true;
} else {
std::cout << "Unable to add UPnP port mapping. ";
std::cout << "IP: ";
std::wcout << localIP.c_str();
std::cout << " HRESULT: 0x" << std::hex << hResult << std::endl;
}
} else {
std::cout << "Unable to add UPnP port mapping." << std::endl;
}
spmc->Release();
}
nat->Release();
}
SysFreeString(proto);
CoUninitialize();
return result;
}
static bool RemoveNATPortMapping(WORD externalPort, IPProtocol protocol)
{
IUPnPNAT *nat = nullptr;
IStaticPortMappingCollection *spmc;
bool result = false;
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
HRESULT hResult = ::CoCreateInstance(__uuidof(UPnPNAT), nullptr, CLSCTX_ALL, __uuidof(IUPnPNAT), (void**)&nat);
BSTR proto = SysAllocString((protocol == IPProtocol::TCP) ? L"TCP" : L"UDP");
if(SUCCEEDED(hResult) && nat) {
hResult = nat->get_StaticPortMappingCollection(&spmc);
if(SUCCEEDED(hResult) && spmc) {
spmc->Remove(externalPort, proto);
spmc->Release();
result = true;
}
nat->Release();
}
SysFreeString(proto);
CoUninitialize();
return result;
}
static wstring GetLocalIP()
{
wstring localIP;
ADDRINFOW *result = nullptr;
ADDRINFOW hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
wchar_t hostName[255];
DWORD hostSize = 255;
GetComputerName(hostName, &hostSize);
if(GetAddrInfoW(hostName, nullptr, &hints, &result) == 0) {
wchar_t ipAddr[255];
DWORD ipSize = 255;
if(WSAAddressToString(result->ai_addr, (DWORD)result->ai_addrlen, nullptr, ipAddr, &ipSize) == 0) {
localIP = ipAddr;
}
FreeAddrInfoW(result);
}
return localIP;
}
static bool AddNATPortMapping(uint16_t internalPort, uint16_t externalPort, IPProtocol protocol);
static bool RemoveNATPortMapping(uint16_t externalPort, IPProtocol protocol);
};

28
Utilities/UTF8Util.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "stdafx.h"
#include "UTF8Util.h"
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#define _WINSOCKAPI_
#include <Windows.h>
namespace utf8 {
std::wstring utf8::decode(const std::string &str)
{
if(str.empty()) return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
std::string utf8::encode(const std::wstring &wstr)
{
if(wstr.empty()) return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
}
#endif

View File

@ -1,67 +1,30 @@
#pragma once
#include <fstream>
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif
namespace utf8 {
#ifdef _WIN32
class utf8
{
public:
static std::wstring decode(const std::string &str)
{
if(str.empty()) return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
static std::string encode(const std::wstring &wstr)
{
if(wstr.empty()) return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
static std::wstring decode(const std::string &str);
static std::string encode(const std::wstring &wstr);
};
class ifstream : public std::ifstream
{
public:
ifstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) : std::ifstream(utf8::decode(_Str), _Mode, _Prot)
{
}
ifstream() : std::ifstream()
{
}
void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot)
{
std::ifstream::open(utf8::decode(_Str), _Mode, _Prot);
}
ifstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) : std::ifstream(utf8::decode(_Str), _Mode, _Prot) { }
ifstream() : std::ifstream() { }
void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) { std::ifstream::open(utf8::decode(_Str), _Mode, _Prot); }
};
class ofstream : public std::ofstream
{
public:
ofstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) : std::ofstream(utf8::decode(_Str), _Mode, _Prot)
{
}
ofstream() : std::ofstream()
{
}
void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot)
{
std::ofstream::open(utf8::decode(_Str), _Mode, _Prot);
}
ofstream(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) : std::ofstream(utf8::decode(_Str), _Mode, _Prot) { }
ofstream() : std::ofstream() { }
void open(const std::string& _Str, ios_base::openmode _Mode = ios_base::in, int _Prot = (int)ios_base::_Openprot) { std::ofstream::open(utf8::decode(_Str), _Mode, _Prot); }
};
#else
using std::ifstream;

View File

@ -128,6 +128,7 @@
<CallingConvention>Cdecl</CallingConvention>
<AdditionalIncludeDirectories>
</AdditionalIncludeDirectories>
<ShowIncludes>true</ShowIncludes>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -241,9 +242,12 @@
<ClInclude Include="ZIPReader.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CRC32.cpp" />
<ClCompile Include="FolderUtilities.cpp" />
<ClCompile Include="miniz.cpp" />
<ClCompile Include="PNGWriter.cpp" />
<ClCompile Include="SimpleLock.cpp" />
<ClCompile Include="Socket.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@ -252,6 +256,9 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release x64|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release x64|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UPnPPortMapper.cpp" />
<ClCompile Include="UTF8Util.cpp" />
<ClCompile Include="ZIPReader.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -64,5 +64,23 @@
<ClCompile Include="SimpleLock.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Socket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UPnPPortMapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UTF8Util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Timer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PNGWriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CRC32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -12,6 +12,7 @@
using std::shared_ptr;
using utf8::ifstream;
using utf8::ofstream;
using std::string;
using std::vector;
using std::atomic;