From b15f3cef27eff472131e056aa554775a1315723c Mon Sep 17 00:00:00 2001 From: turanszkij Date: Tue, 8 Oct 2019 18:57:45 +0100 Subject: [PATCH] network library rewrite, added network test --- Documentation/ScriptingAPI-Documentation.md | 16 +- Documentation/WickedEngine-Documentation.md | 6 +- Tests/Tests.cpp | 82 ++++++++ Tests/Tests.h | 1 + WickedEngine/WickedEngine.h | 1 + WickedEngine/WickedEngine_SHARED.vcxitems | 9 +- .../WickedEngine_SHARED.vcxitems.filters | 27 +-- WickedEngine/wiArchive.cpp | 14 +- WickedEngine/wiArchive.h | 22 ++- WickedEngine/wiClient.cpp | 52 ----- WickedEngine/wiClient.h | 153 --------------- WickedEngine/wiInitializer.cpp | 1 + WickedEngine/wiLua.cpp | 3 +- WickedEngine/wiNetwork.cpp | 60 ------ WickedEngine/wiNetwork.h | 136 ++++++------- WickedEngine/wiNetwork_BindLua.cpp | 108 +---------- WickedEngine/wiNetwork_BindLua.h | 36 +--- WickedEngine/wiNetwork_UWP.cpp | 50 +++++ WickedEngine/wiNetwork_Windows.cpp | 182 ++++++++++++++++++ WickedEngine/wiServer.cpp | 142 -------------- WickedEngine/wiServer.h | 165 ---------------- WickedEngine/wiVersion.cpp | 4 +- 22 files changed, 426 insertions(+), 844 deletions(-) delete mode 100644 WickedEngine/wiClient.cpp delete mode 100644 WickedEngine/wiClient.h delete mode 100644 WickedEngine/wiNetwork.cpp create mode 100644 WickedEngine/wiNetwork_UWP.cpp create mode 100644 WickedEngine/wiNetwork_Windows.cpp delete mode 100644 WickedEngine/wiServer.cpp delete mode 100644 WickedEngine/wiServer.h diff --git a/Documentation/ScriptingAPI-Documentation.md b/Documentation/ScriptingAPI-Documentation.md index 476130976..0185b07a8 100644 --- a/Documentation/ScriptingAPI-Documentation.md +++ b/Documentation/ScriptingAPI-Documentation.md @@ -42,8 +42,6 @@ The documentation completion is still pending.... 2. RenderPath3D_Deferred 3. LoadingScreen 9. Network - 1. Server - 2. Client 10. Input Handling 11. ResourceManager @@ -283,7 +281,7 @@ Just holds texture information in VRAM. ### Audio Loads and plays an audio files. -- [outer]audio -- the audio device +- [outer]audio : Audio -- the audio device - CreateSound(string filename, Sound sound) : bool -- Creates a sound file, returns true if successful, false otherwise - CreateSoundInstance(Sound sound, SoundInstance soundinstance) : bool -- Creates a sound instance that can be replayed, returns true if successful, false otherwise - Destroy(Sound sound) @@ -679,16 +677,8 @@ Sphere defined by center Vector and radius. Can be intersected with other primit - GetRadius() : float result ### Network -Here are the network communication features. -- TODO - -#### Server -A TCP host to which clients can connect and communicate with each other or the server. -- TODO - -#### Client -A TCP client which provides features to communicate with other clients over the internet or local area network connection. -- TODO +Handles the network communication features. +- [outer]network : Network ### Input Handling These provide functions to check the state of the input devices. diff --git a/Documentation/WickedEngine-Documentation.md b/Documentation/WickedEngine-Documentation.md index 1b3e6454a..e4c32289c 100644 --- a/Documentation/WickedEngine-Documentation.md +++ b/Documentation/WickedEngine-Documentation.md @@ -99,13 +99,15 @@ The following quick reference shows an overview of common resource formats and s ![InformationSheet](information_sheet.png) ## Audio -The audio system handles audio playback and spatial audio. +Handles audio playback and spatial audio. - wiAudio - The namespace that is a collection of audio related functionality - Sound - Represents a sound file in memory. Load a sound file via wiAudio interface. - SoundInstance - An instance of a sound file that can be played and controlled in various ways through the wiAudio interface. +- SoundInstance3D + - This structure describes a relation between listener and sound emitter in 3D space. Used together with a SoundInstance in wiAudio::Update3D() function ## Helpers A collection of engine-level helper classes @@ -130,7 +132,7 @@ The input interface can be found here - There are several functions, such as down(), press(), etc. to check button states. ## Network -TODO: Rewrite the networking systems +Handles network communication features. ## Scripting This is the place for the Lua scipt interface. The systems that are bound to Lua have the name of the system prefixed by _BindLua. diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index 92bf32667..6d3e0ca7d 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -109,6 +109,7 @@ TestsRenderer::TestsRenderer() testSelector->AddItem("Volumetric Test"); testSelector->AddItem("Sprite Test"); testSelector->AddItem("Lightmap Bake Test"); + testSelector->AddItem("Network Test"); testSelector->SetMaxVisibleItemCount(100); testSelector->OnSelect([=](wiEventArgs args) { @@ -199,6 +200,9 @@ TestsRenderer::TestsRenderer() wiRenderer::SetTemporalAAEnabled(true); wiSceneSystem::LoadModel("../models/lightmap_bake_test.wiscene", XMMatrixTranslation(0, 0, 4)); break; + case 15: + RunNetworkTest(); + break; default: assert(0); break; @@ -663,3 +667,81 @@ void TestsRenderer::RunSpriteTest() } } +void TestsRenderer::RunNetworkTest() +{ + static wiFont font; + + wiNetwork::Connection connection; + connection.ipaddress = { 127,0,0,1 }; // localhost + connection.port = 12345; // just any random port really + + std::thread sender([&] { + // Create sender socket: + wiNetwork::Socket sock; + wiNetwork::CreateSocket(&sock); + + // Create a text message: + const char message[] = "Hi, this is a text message sent over the network!\nYou can find out more in Tests.cpp, RunNetworkTest() function."; + const size_t message_size = sizeof(message); + + // First, send the text message size: + wiNetwork::Send(&sock, &connection, &message_size, sizeof(message_size)); + + // Then send the actual text message: + wiNetwork::Send(&sock, &connection, message, message_size); + + }); + + std::thread receiver([&] { + // Create receiver socket: + wiNetwork::Socket sock; + wiNetwork::CreateSocket(&sock); + + // Listen on the port which the sender uses: + wiNetwork::ListenPort(&sock, connection.port); + + // We can check for incoming messages with CanReceive(). A timeout value can be specified in microseconds + // to let the function block for some time, otherwise it returns imediately + // It is not necessary to use this, but the wiNetwork::Receive() will block until there is a message + if (wiNetwork::CanReceive(&sock, 1000000)) + { + // We know that we want a text message in this simple example, but we don't know the size. + // We also know that the sender sends the text size before the actual text, so first we will receive the text size: + size_t message_size; + wiNetwork::Connection sender_connection; // this will be filled out with the sender's address + wiNetwork::Receive(&sock, &sender_connection, &message_size, sizeof(message_size)); + + if (wiNetwork::CanReceive(&sock, 1000000)) + { + // Once we know the text message length, we can receive the message itself: + char* message = new char[message_size]; // allocate text buffer + wiNetwork::Receive(&sock, &sender_connection, message, message_size); + + // Write the message to the screen: + font.SetText(message); + + // delete the message: + delete[] message; + } + else + { + font.SetText("Failed to receive the message in time"); + } + } + else + { + font.SetText("Failed to receive the message length in time"); + } + + }); + + sender.join(); + receiver.join(); + + font.params.posX = wiRenderer::GetDevice()->GetScreenWidth() / 2; + font.params.posY = wiRenderer::GetDevice()->GetScreenHeight() / 2; + font.params.h_align = WIFALIGN_CENTER; + font.params.v_align = WIFALIGN_CENTER; + font.params.size = 24; + this->addFont(&font); +} diff --git a/Tests/Tests.h b/Tests/Tests.h index bd969ad87..498fec6ea 100644 --- a/Tests/Tests.h +++ b/Tests/Tests.h @@ -16,5 +16,6 @@ public: void RunJobSystemTest(); void RunFontTest(); void RunSpriteTest(); + void RunNetworkTest(); }; diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index 3430fc071..0110e1f0a 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -62,6 +62,7 @@ #include "wiGPUBVH.h" #include "wiGPUSortLib.h" #include "wiJobSystem.h" +#include "wiNetwork.h" #ifdef _WIN32 diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems b/WickedEngine/WickedEngine_SHARED.vcxitems index 0b4a21f71..6b2a88607 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems +++ b/WickedEngine/WickedEngine_SHARED.vcxitems @@ -316,7 +316,6 @@ - @@ -339,13 +338,13 @@ + - @@ -358,7 +357,6 @@ - @@ -651,7 +649,6 @@ - @@ -671,11 +668,12 @@ + + - @@ -688,7 +686,6 @@ - diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems.filters b/WickedEngine/WickedEngine_SHARED.vcxitems.filters index 1f00dbde2..db01fdcf0 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems.filters +++ b/WickedEngine/WickedEngine_SHARED.vcxitems.filters @@ -891,12 +891,6 @@ ENGINE\Helpers - - ENGINE\Network - - - ENGINE\Network - ENGINE\Graphics @@ -909,9 +903,6 @@ ENGINE\Scripting - - ENGINE\Network - ENGINE\Helpers @@ -1134,6 +1125,9 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Network + @@ -1742,21 +1736,12 @@ ENGINE\Helpers - - ENGINE\Network - - - ENGINE\Network - ENGINE\Graphics ENGINE\Scripting - - ENGINE\Network - ENGINE\Helpers @@ -1907,6 +1892,12 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Network + + + ENGINE\Network + diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 65c30c89a..cd9093539 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -17,7 +17,7 @@ wiArchive::wiArchive() { CreateEmpty(); } -wiArchive::wiArchive(const std::string& fileName, bool readMode):readMode(readMode),pos(0),DATA(nullptr),dataSize(0),fileName(fileName) +wiArchive::wiArchive(const std::string& fileName, bool readMode) : fileName(fileName), readMode(readMode) { if (!fileName.empty()) { @@ -28,8 +28,8 @@ wiArchive::wiArchive(const std::string& fileName, bool readMode):readMode(readMo { dataSize = (size_t)file.tellg(); file.seekg(0, file.beg); - DATA = new char[(size_t)dataSize]; - file.read(DATA, dataSize); + DATA = new uint8_t[(size_t)dataSize]; + file.read((char*)DATA, dataSize); file.close(); (*this) >> version; if (version < __archiveVersionBarrier) @@ -69,7 +69,7 @@ void wiArchive::CreateEmpty() version = __archiveVersion; dataSize = 128; // this will grow if necessary anyway... - DATA = new char[dataSize]; + DATA = new uint8_t[dataSize]; (*this) << version; } @@ -113,7 +113,7 @@ bool wiArchive::SaveFile(const std::string& fileName) ofstream file(fileName, ios::binary | ios::trunc); if (file.is_open()) { - file.write(DATA, (streamsize)pos); + file.write((const char*)DATA, (streamsize)pos); file.close(); return true; } @@ -121,12 +121,12 @@ bool wiArchive::SaveFile(const std::string& fileName) return false; } -string wiArchive::GetSourceDirectory() +string wiArchive::GetSourceDirectory() const { return wiHelper::GetDirectoryFromPath(fileName); } -string wiArchive::GetSourceFileName() +string wiArchive::GetSourceFileName() const { return fileName; } diff --git a/WickedEngine/wiArchive.h b/WickedEngine/wiArchive.h index b2df11cfb..187357907 100644 --- a/WickedEngine/wiArchive.h +++ b/WickedEngine/wiArchive.h @@ -8,11 +8,11 @@ class wiArchive { private: - uint64_t version; - bool readMode; - size_t pos; - char* DATA; - size_t dataSize; + uint64_t version = 0; + bool readMode = false; + size_t pos = 0; + uint8_t* DATA = nullptr; + size_t dataSize = 0; std::string fileName; // save to this file on closing if not empty @@ -25,14 +25,16 @@ public: wiArchive(const std::string& fileName, bool readMode = true); ~wiArchive(); - uint64_t GetVersion() { return version; } - bool IsReadMode() { return readMode; } + const uint8_t* GetData() const { return DATA; } + size_t GetSize() const { return pos; } + uint64_t GetVersion() const { return version; } + bool IsReadMode() const { return readMode; } void SetReadModeAndResetPos(bool isReadMode); bool IsOpen(); void Close(); bool SaveFile(const std::string& fileName); - std::string GetSourceDirectory(); - std::string GetSourceFileName(); + std::string GetSourceDirectory() const; + std::string GetSourceFileName() const; // It could be templated but we have to be extremely careful of different datasizes on different platforms // because serialized data should be interchangeable! @@ -318,7 +320,7 @@ private: size_t _right = pos + _size; if (_right > dataSize) { - char* NEWDATA = new char[_right * 2]; + uint8_t* NEWDATA = new uint8_t[_right * 2]; memcpy(NEWDATA, DATA, dataSize); dataSize = _right * 2; SAFE_DELETE_ARRAY(DATA); diff --git a/WickedEngine/wiClient.cpp b/WickedEngine/wiClient.cpp deleted file mode 100644 index 52293f7a6..000000000 --- a/WickedEngine/wiClient.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "wiClient.h" - -using namespace std; - -#ifndef WINSTORE_SUPPORT - -wiClient::wiClient(const std::string& newName, const std::string& ipaddress, int port) -{ - if(ConnectToHost(port,ipaddress.length()<=1?"127.0.0.1":ipaddress.c_str())){ - success=true; - string welcomeMsg; - if(receiveText(welcomeMsg)){ - stringstream ss(""); - ss<<"Client connected to: "< - bool sendData(const T& value){ - Network::sendData(PACKET_TYPE_OTHER,s); - return Network::sendData(value,s); - } - template - bool receiveData(T& value){ - return wiNetwork::receiveData(value,s); - } - - bool changeName(const std::string& newName); - bool sendMessage(const std::string& text); - - bool ConnectToHost(int PortNo, const char* IPAddress) - { - WSAData wsadata; - int error = WSAStartup(SCK_VERSION2,&wsadata); - - if(error) - return false; - - if(wsadata.wVersion != SCK_VERSION2){ - WSACleanup(); - return false; - } - - SOCKADDR_IN target; - - target.sin_family = AF_INET; - target.sin_port = htons(PortNo); - target.sin_addr.S_un.S_addr = inet_addr(IPAddress); - - s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(s == INVALID_SOCKET){ - return false; - } - - int opt = TRUE; - if( setsockopt(s, SOL_SOCKET, TCP_NODELAY, (char *)&opt, sizeof(opt)) < 0 ) - return false; - - //Try connecting: - - if(connect(s, (SOCKADDR*)&target, sizeof(target)) == SOCKET_ERROR){ - return false; - } - else - return true; - - } - - template - void Poll(T& data) - { - - if(!success) - return; - - //clear the socket set - FD_ZERO(&readfds); - - //add master socket to set - FD_SET(s, &readfds); - - - //wait for an activity on one of the sockets , timeout is NULL , so wait indefinitely - timeval time=timeval(); - time.tv_sec=0; - time.tv_usec=1; - - if ((select( (int)s + 1, &readfds , NULL , NULL , &time) < 0) && (errno!=EINTR)) - { - wiBackLog::post("select error"); - } - - //If something happened on the master socket , then its an incoming connection - if (FD_ISSET(s, &readfds)) - { - int command; - bool receiveSuccess = receiveData(command); - - if(!receiveSuccess){ - wiBackLog::post("Server no longer available. Please disconnect."); - closesocket(s); - success=false; - } - else{ - switch(command){ - case PACKET_TYPE_CHANGENAME: - { - string text; - if(receiveText(text)){ - stringstream ss(""); - ss<<"New server name is: "< - void Poll(T& data) {} - -#endif // WINSTORE_SUPPORT - -}; - - -#endif \ No newline at end of file diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index 46c92c67f..0b1451da7 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -29,6 +29,7 @@ namespace wiInitializer wiJobSystem::Execute(ctx, [] { wiInputManager::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiRenderer::Initialize(); wiWidget::LoadShaders(); }); wiJobSystem::Execute(ctx, [] { wiAudio::Initialize(); }); + wiJobSystem::Execute(ctx, [] { wiNetwork::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiTextureHelper::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiSceneSystem::wiHairParticle::Initialize(); }); wiJobSystem::Execute(ctx, [] { wiSceneSystem::wiEmittedParticle::Initialize(); }); diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 89a30a215..5a7570dbb 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -75,8 +75,7 @@ wiLua* wiLua::GetGlobal() wiInputManager_BindLua::Bind(); wiFont_BindLua::Bind(); wiBackLog_BindLua::Bind(); - wiClient_BindLua::Bind(); - wiServer_BindLua::Bind(); + wiNetwork_BindLua::Bind(); wiIntersect_BindLua::Bind(); } diff --git a/WickedEngine/wiNetwork.cpp b/WickedEngine/wiNetwork.cpp deleted file mode 100644 index 0d1bbd7a7..000000000 --- a/WickedEngine/wiNetwork.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "wiNetwork.h" - - -#ifndef WINSTORE_SUPPORT - -wiNetwork::wiNetwork(void) -{ - name="UNNAMED_NETWORK"; -} - - -wiNetwork::~wiNetwork(void) -{ - CloseConnection(); -} - - -bool wiNetwork::sendText(const std::string& text, SOCKET socket){ - if(sendData((int)text.length(),socket)){ - int sent = send(socket, text.c_str(), (int)text.length(), 0); - - if(sent==SOCKET_ERROR) { - //cout << "\n[Error] Sending text '"< -#include #include -#include +#include -#ifndef WINSTORE_SUPPORT -#pragma comment(lib,"ws2_32.lib") -#endif - -class wiNetwork +namespace wiNetwork { -public: - static const int PORT = 65000; - - static const int PACKET_TYPE_CHANGENAME = 0; - static const int PACKET_TYPE_TEXTMESSAGE = 1; - static const int PACKET_TYPE_OTHER = 2; - -#ifndef WINSTORE_SUPPORT -protected: - -#define SCK_VERSION2 0x0202 - - SOCKET s; - WSADATA w; - fd_set readfds; - - std::string name; - -public: - bool success; - - wiNetwork(void); - ~wiNetwork(void); - - virtual bool changeName(const std::string& newName){ - name=newName; - return true; - } - - void CloseConnection() + struct Socket { - if(s) - closesocket(s); + wiCPUHandle handle = WI_NULL_HANDLE; - WSACleanup(); - - - //wiBackLog::post("\n\nClosed Connection"); - } - - static bool sendText(const std::string& text, SOCKET socket); - template - static bool sendData(const T& value, SOCKET socket){ - int sent = send(socket, (const char*)&value, sizeof(value), 0); - - if(sent==SOCKET_ERROR) { - //stringstream ss(""); - //ss << "\n[Error] Sending data failed with error: " << WSAGetLastError(); - //wiBackLog::post(ss.str().c_str()); - return false; + void operator=(Socket&& other) + { + handle = other.handle; + other.handle = WI_NULL_HANDLE; } - return true; - } + Socket() {} + Socket(Socket&& other) + { + handle = other.handle; - static bool receiveText(std::string& text, SOCKET socket); - template - static bool receiveData(T& value, SOCKET socket){ - char puffer[sizeof(value)]; - int received = recv(socket, puffer, sizeof(puffer), 0); - if(received<=0){ - //cout<< "[Error][receiveNumber] The recv call failed with error!\n"; - } - else if (received <= sizeof(value)) { - value = *((T*)puffer); - return true; + other.handle = WI_NULL_HANDLE; } - else{ - //cout<< "[Error][receiveNumber] Too long request!\n"; - } - return false; - } -#endif // WINSTORE_SUPPORT + ~Socket(); + }; -}; + static const uint16_t DEFAULT_PORT = 777; + struct Connection + { + std::array ipaddress = { 127,0,0,1 }; + uint16_t port = DEFAULT_PORT; + }; + void Initialize(); + void CleanUp(); -#endif + // Creates a socket that can be used to send or receive data + HRESULT CreateSocket(Socket* sock); + // Destroys socket + HRESULT Destroy(Socket* sock); + + // Sends data packet to destination connection + // sock : socket that sends the packet + // connection : connection to the receiver, it is provided by the call site + // data : buffer that contains data to send + // dataSize : size of the data to send in bytes + HRESULT Send(const Socket* sock, const Connection* connection, const void* data, size_t dataSize); + + // Enables the socket to receive data on a port + // sock : socket that receives packet + // port : port number to open + HRESULT ListenPort(const Socket* sock, uint16_t port = DEFAULT_PORT); + + // Checks whether any data can be received at the moment, returns immediately + // sock : socket that receives packet + // timeout_microseconds : timeout period in microseconds. Specify this to let the function block + // returns true if there are any messages in the queue, false otherwise + bool CanReceive(const Socket* sock, long timeout_microseconds = 1); + + // Receive data. This function will block until a packet has been received. Use CanReceive() function to check if this function will block or not. + // sock : socket that receives packet + // connection : sender's connection data will be written to it when the function returns + // data : buffer to hold received data, must be already allocated to a sufficient size + // dataSize : expected data size in bytes + HRESULT Receive(const Socket* sock, Connection* connection, void* data, size_t dataSize); +} diff --git a/WickedEngine/wiNetwork_BindLua.cpp b/WickedEngine/wiNetwork_BindLua.cpp index 71db73109..651d1d429 100644 --- a/WickedEngine/wiNetwork_BindLua.cpp +++ b/WickedEngine/wiNetwork_BindLua.cpp @@ -1,119 +1,27 @@ #include "wiNetwork_BindLua.h" -#include "wiClient.h" -#include "wiServer.h" +#include "wiNetwork.h" #include "wiHelper.h" using namespace std; -const char wiClient_BindLua::className[] = "Client"; +const char wiNetwork_BindLua::className[] = "Network"; -Luna::FunctionType wiClient_BindLua::methods[] = { - lunamethod(wiClient_BindLua,Poll), +Luna::FunctionType wiNetwork_BindLua::methods[] = { { NULL, NULL } }; -Luna::PropertyType wiClient_BindLua::properties[] = { +Luna::PropertyType wiNetwork_BindLua::properties[] = { { NULL, NULL } }; - -wiClient_BindLua::wiClient_BindLua(lua_State* L) -{ - string name = "CLIENT-", ipaddress = "127.0.0.1"; - name += wiHelper::getCurrentDateTimeAsString(); - int port = 65000; - - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - { - name = wiLua::SGetString(L, 1); - if (argc > 1) - { - ipaddress = wiLua::SGetString(L, 2); - if (argc > 2) - { - port = wiLua::SGetInt(L, 3); - } - } - } - - client = new wiClient(name, ipaddress, port); -} - - -wiClient_BindLua::~wiClient_BindLua() -{ - SAFE_DELETE(client); -} - -int wiClient_BindLua::Poll(lua_State* L) -{ - int i = 0; - client->Poll(i); - return 0; -} - -void wiClient_BindLua::Bind() +void wiNetwork_BindLua::Bind() { static bool initialized = false; if (!initialized) { initialized = true; - Luna::Register(wiLua::GetGlobal()->GetLuaState()); + Luna::Register(wiLua::GetGlobal()->GetLuaState()); + + wiLua::GetGlobal()->RunText("network = Network()"); } } - -const char wiServer_BindLua::className[] = "Server"; - -Luna::FunctionType wiServer_BindLua::methods[] = { - lunamethod(wiServer_BindLua,Poll), - { NULL, NULL } -}; -Luna::PropertyType wiServer_BindLua::properties[] = { - { NULL, NULL } -}; - -wiServer_BindLua::wiServer_BindLua(lua_State* L) -{ - string name = "SERVER-", ipaddress = "0.0.0.0"; - name+=wiHelper::getCurrentDateTimeAsString(); - int port = 65000; - - int argc = wiLua::SGetArgCount(L); - if (argc > 0) - { - name = wiLua::SGetString(L, 1); - if (argc > 1) - { - ipaddress = wiLua::SGetString(L, 2); - if (argc > 2) - { - port = wiLua::SGetInt(L, 3); - } - } - } - - server = new wiServer(name, ipaddress, port); -} - -wiServer_BindLua::~wiServer_BindLua() -{ - SAFE_DELETE(server); -} - -int wiServer_BindLua::Poll(lua_State* L) -{ - int i = 0; - server->Poll(i); - return 0; -} - -void wiServer_BindLua::Bind() -{ - static bool initialized = false; - if (!initialized) - { - initialized = true; - Luna::Register(wiLua::GetGlobal()->GetLuaState()); - } -} \ No newline at end of file diff --git a/WickedEngine/wiNetwork_BindLua.h b/WickedEngine/wiNetwork_BindLua.h index 4e1438fda..0c30d6334 100644 --- a/WickedEngine/wiNetwork_BindLua.h +++ b/WickedEngine/wiNetwork_BindLua.h @@ -2,41 +2,15 @@ #include "wiLua.h" #include "wiLuna.h" -class wiClient; -class wiServer; - -class wiClient_BindLua +class wiNetwork_BindLua { public: - wiClient* client; - static const char className[]; - static Luna::FunctionType methods[]; - static Luna::PropertyType properties[]; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; - wiClient_BindLua(lua_State* L); - ~wiClient_BindLua(); - - int Poll(lua_State* L); + wiNetwork_BindLua(lua_State* L) {} + ~wiNetwork_BindLua() {} static void Bind(); }; - -class wiServer_BindLua -{ -public: - wiServer* server; - - static const char className[]; - static Luna::FunctionType methods[]; - static Luna::PropertyType properties[]; - - wiServer_BindLua(lua_State* L); - ~wiServer_BindLua(); - - - int Poll(lua_State* L); - - static void Bind(); -}; - diff --git a/WickedEngine/wiNetwork_UWP.cpp b/WickedEngine/wiNetwork_UWP.cpp new file mode 100644 index 000000000..2298f6810 --- /dev/null +++ b/WickedEngine/wiNetwork_UWP.cpp @@ -0,0 +1,50 @@ +#ifdef WINSTORE_SUPPORT +#include "wiNetwork.h" +#include "wiBackLog.h" + +namespace wiNetwork +{ + Socket::~Socket() + { + } + + void Initialize() + { + wiBackLog::post("TODO wiNetwork_UWP"); + } + void CleanUp() + { + } + + HRESULT CreateSocket(Socket* sock) + { + return E_FAIL; + } + HRESULT Destroy(Socket* sock) + { + return E_FAIL; + } + + HRESULT Send(const Socket* sock, const Connection* connection, const void* data, size_t dataSize) + { + return E_FAIL; + } + + HRESULT ListenPort(const Socket* sock, uint16_t port) + { + return E_FAIL; + } + + bool CanReceive(const Socket* sock, long timeout_microseconds) + { + return false; + } + + HRESULT Receive(const Socket* sock, Connection* connection, void* data, size_t dataSize) + { + return E_FAIL; + } + +} + +#endif // WINSTORE_SUPPORT diff --git a/WickedEngine/wiNetwork_Windows.cpp b/WickedEngine/wiNetwork_Windows.cpp new file mode 100644 index 000000000..9e91b55c7 --- /dev/null +++ b/WickedEngine/wiNetwork_Windows.cpp @@ -0,0 +1,182 @@ +#ifndef WINSTORE_SUPPORT +#include "wiNetwork.h" +#include "wiBackLog.h" + +#include + +#include +#pragma comment(lib,"ws2_32.lib") + +namespace wiNetwork +{ + Socket::~Socket() + { + Destroy(this); + } + + void Initialize() + { + int result; + WSAData wsadata; + result = WSAStartup(MAKEWORD(2, 2), &wsadata); + if (result) + { + int error = WSAGetLastError(); + std::stringstream ss(""); + ss << "wiNetwork Initialization FAILED with error: " << error; + wiBackLog::post(ss.str().c_str()); + WSACleanup(); + assert(0); + } + + wiBackLog::post("wiNetwork Initialized"); + } + void CleanUp() + { + WSACleanup(); + } + + HRESULT CreateSocket(Socket* sock) + { + Destroy(sock); + + SOCKET handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (handle == INVALID_SOCKET) + { + int error = WSAGetLastError(); + std::stringstream ss; + ss << "wiNetwork error in CreateSocket: " << error; + wiBackLog::post(ss.str().c_str()); + return E_FAIL; + } + + sock->handle = (wiCPUHandle)handle; + + return S_OK; + } + HRESULT Destroy(Socket* sock) + { + if (socket != nullptr && sock->handle != WI_NULL_HANDLE) + { + int result = closesocket((SOCKET)sock->handle); + if (result == SOCKET_ERROR) + { + int error = WSAGetLastError(); + std::stringstream ss; + ss << "wiNetwork error in Destroy: " << error; + wiBackLog::post(ss.str().c_str()); + return E_FAIL; + } + + sock->handle = WI_NULL_HANDLE; + return S_OK; + } + return E_FAIL; + } + + HRESULT Send(const Socket* sock, const Connection* connection, const void* data, size_t dataSize) + { + if (socket != nullptr && sock->handle != WI_NULL_HANDLE) + { + sockaddr_in target; + target.sin_family = AF_INET; + target.sin_port = htons(connection->port); // reverse byte order from host to network + target.sin_addr.S_un.S_un_b.s_b1 = connection->ipaddress[0]; + target.sin_addr.S_un.S_un_b.s_b2 = connection->ipaddress[1]; + target.sin_addr.S_un.S_un_b.s_b3 = connection->ipaddress[2]; + target.sin_addr.S_un.S_un_b.s_b4 = connection->ipaddress[3]; + + int result = sendto((SOCKET)sock->handle, (const char*)data, (int)dataSize, 0, (const sockaddr*)& target, sizeof(target)); + if (result == SOCKET_ERROR) + { + int error = WSAGetLastError(); + std::stringstream ss; + ss << "wiNetwork error in Send: " << error; + wiBackLog::post(ss.str().c_str()); + return E_FAIL; + } + + return S_OK; + } + return E_FAIL; + } + + HRESULT ListenPort(const Socket* sock, uint16_t port) + { + if (socket != nullptr && sock->handle != WI_NULL_HANDLE) + { + sockaddr_in target; + target.sin_family = AF_INET; + target.sin_port = htons(port); + target.sin_addr.S_un.S_addr = htonl(INADDR_ANY); + + int result = bind((SOCKET)sock->handle, (const sockaddr*)& target, sizeof(target)); + if (result == SOCKET_ERROR) + { + int error = WSAGetLastError(); + std::stringstream ss; + ss << "wiNetwork error in ListenPort: " << error; + wiBackLog::post(ss.str().c_str()); + return E_FAIL; + } + + return S_OK; + } + return E_FAIL; + } + + bool CanReceive(const Socket* sock, long timeout_microseconds) + { + if (socket != nullptr && sock->handle != WI_NULL_HANDLE) + { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET((SOCKET)sock->handle, &readfds); + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = timeout_microseconds; + int result = select(0, &readfds, NULL, NULL, &timeout); + if (result < 0) + { + std::stringstream ss; + ss << "wiNetwork error in CanReceive: " << WSAGetLastError(); + wiBackLog::post(ss.str().c_str()); + assert(0); + return false; + } + + return FD_ISSET((SOCKET)sock->handle, &readfds); + } + return false; + } + + HRESULT Receive(const Socket* sock, Connection* connection, void* data, size_t dataSize) + { + if (socket != nullptr && sock->handle != WI_NULL_HANDLE) + { + sockaddr_in sender; + int targetsize = sizeof(sender); + int result = recvfrom((SOCKET)sock->handle, (char*)data, (int)dataSize, 0, (sockaddr*)& sender, &targetsize); + if (result == SOCKET_ERROR) + { + int error = WSAGetLastError(); + std::stringstream ss; + ss << "wiNetwork error in Receive: " << error; + wiBackLog::post(ss.str().c_str()); + return E_FAIL; + } + + connection->port = htons(sender.sin_port); // reverse byte order from network to host + connection->ipaddress[0] = sender.sin_addr.S_un.S_un_b.s_b1; + connection->ipaddress[1] = sender.sin_addr.S_un.S_un_b.s_b2; + connection->ipaddress[2] = sender.sin_addr.S_un.S_un_b.s_b3; + connection->ipaddress[3] = sender.sin_addr.S_un.S_un_b.s_b4; + + return S_OK; + } + return E_FAIL; + } + +} + +#endif // WINSTORE_SUPPORT diff --git a/WickedEngine/wiServer.cpp b/WickedEngine/wiServer.cpp deleted file mode 100644 index 57ab4d199..000000000 --- a/WickedEngine/wiServer.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "wiServer.h" - -#ifndef WINSTORE_SUPPORT - -using namespace std; - - -wiServer::wiServer(const std::string& newName, const std::string& ipaddress, int port) -{ - name=newName; - if(ListenOnPort(port,ipaddress.length()<=1?"0.0.0.0":ipaddress.c_str())){ - stringstream ss(""); - ss<<"Listening as "<::iterator it = clients.begin(); it != clients.end(); ++it) { - closesocket(it->first); - } - wiNetwork::~wiNetwork(); -} - -bool wiServer::ListenOnPort(int portno, const char* ipaddress) -{ - int error = WSAStartup(SCK_VERSION2,&w); - - if(error) - return false; - - if(w.wVersion != SCK_VERSION2){ - WSACleanup(); - return false; - } - - SOCKADDR_IN addr; - addr.sin_family = AF_INET; - addr.sin_port= htons(portno); - //addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //or inet_addr("0.0.0.0"); - addr.sin_addr.S_un.S_addr = inet_addr(ipaddress); - - s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - - - //set master socket to allow multiple connections , this is just a good habit, it will work without this - int opt = TRUE; - if( setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ) - return false; - - - if( setsockopt(s, SOL_SOCKET, TCP_NODELAY, (char *)&opt, sizeof(opt)) < 0 ) - return false; - - if(s == INVALID_SOCKET) - return false; - - if(::bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) - return false; //couldn't bind (for example if you try to bind more than once to the same socket - - //if( listen(s,SOMAXCONN) == SOCKET_ERROR ) - if( listen(s,SOMAXCONN) == SOCKET_ERROR ) - return false; - - - - return true; -} -SOCKET wiServer::CreateAccepter(){ - struct sockaddr_in caller; - int addrlen = sizeof(caller); - SOCKET newsock = accept(s,(struct sockaddr *) &caller, &addrlen); - - //inform user of socket number - used in send and receive commands - if(newsock != SOCKET_ERROR){ - //printf("\nNew connection , socket fd is %d , ip is : %s , port : %d \n" , newsock , inet_ntoa(caller.sin_addr) , ntohs(caller.sin_port)); - } - else{ - //printf("\nConnection FAILED on socket: fd is %d , ip is : %s , port : %d \n" , newsock , inet_ntoa(caller.sin_addr) , ntohs(caller.sin_port)); - } - - return newsock; -} - - - -std::vector wiServer::listClients() -{ - std::vector ret(0); - for (std::map::iterator it = clients.begin(); it != clients.end(); ++it) { - stringstream ss(""); - ss<second<<":"<first; - ret.push_back(ss.str()); - } - return ret; -} - -bool wiServer::sendText(const std::string& text, int packettype, const std::string& clientName, int clientID){ - int sentTo=0; - - if(clientName.length()<=0){ //send to everyone - for (std::map::iterator it = clients.begin(); it != clients.end(); ++it) { - sentTo += wiNetwork::sendData(packettype,it->first) && wiNetwork::sendText(text,it->first); - } - } - else if(clientID<0){ //send to all of same name - for (std::map::iterator it = clients.begin(); it != clients.end(); ++it) { - if(!clientName.compare(it->second)){ - sentTo += wiNetwork::sendData(packettype,it->first) && wiNetwork::sendText(text,it->first); - } - } - } - else{ //send to specific client - if(clients.find(clientID) != clients.end()){ - sentTo += wiNetwork::sendData(packettype,clientID) && wiNetwork::sendText(text,clientID); - } - } - - if(sentTo<=0) - wiBackLog::post("No client was found with the specified parameters"); - - return sentTo>0; -} - -bool wiServer::changeName(const std::string& newName){ - wiNetwork::changeName(newName); - return sendText(newName, wiNetwork::PACKET_TYPE_CHANGENAME); -} -bool wiServer::sendMessage(const std::string& text, const std::string& clientName, int clientID){ - return sendText(text, wiNetwork::PACKET_TYPE_TEXTMESSAGE, clientName, clientID); -} - -#endif diff --git a/WickedEngine/wiServer.h b/WickedEngine/wiServer.h deleted file mode 100644 index 5399e8568..000000000 --- a/WickedEngine/wiServer.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef SERVER_H -#define SERVER_H - - - -#include "wiNetwork.h" -#include -#include - - -class wiServer : public wiNetwork -{ -#ifndef WINSTORE_SUPPORT -private: - std::map clients; -public: - wiServer(const std::string& newName = "SERVER", const std::string& ipaddress = "0.0.0.0", int port = PORT); - ~wiServer(void); - - bool active(){return !clients.empty();} - - - bool sendText(const std::string& text, int packettype, const std::string& clientName = "", int clientID = -1); - template - bool sendData(const T& value){ - if(clients.begin()==clients.end()) - return false; - Network::sendData(PACKET_TYPE_OTHER,clients.begin()->first); - return Network::sendData(value,clients.begin()->first); - } - template - bool receiveData(T& value){ - if(clients.begin()==clients.end()) - return false; - return Network::receiveData(value,clients.begin()->first); - } - - - bool changeName(const std::string& newName); - bool sendMessage(const std::string& text, const std::string& clientName = "", int clientID = -1); - - bool ListenOnPort(int portno, const char* ipaddress); - SOCKET CreateAccepter(); - - template - void Poll(T& data) - { - - - //clear the socket set - FD_ZERO(&readfds); - - //add master socket to set - FD_SET(s, &readfds); - SOCKET max_sd = s; - - - for (std::map::iterator it = clients.begin(); it != clients.end(); ++it) { - if(it->first>0) - FD_SET( it->first, &readfds ); - if(it->first>max_sd) - max_sd=it->first; - } - - - timeval time=timeval(); - time.tv_sec=0; - time.tv_usec=1; - - if ((select( (int)max_sd + 1, &readfds , NULL , NULL , &time) < 0) && (errno!=EINTR)) - { - wiBackLog::post("select error"); - } - - //If something happened on the master socket , then its an incoming connection - if (FD_ISSET(s, &readfds)) - { - SOCKET new_socket = CreateAccepter(); - - if(new_socket != SOCKET_ERROR){ - if(wiNetwork::sendText(name,new_socket)){ - stringstream ss(""); - ss<<"Name sent, client ["<(new_socket,ss.str())); - - } - else - wiBackLog::post("Welcome message could NOT be sent, client ignored"); - - } - } - - //else its some IO operation on some other socket :) - for (std::map::iterator it = clients.begin(); it != clients.end(); ) { - - if (FD_ISSET( it->first , &readfds)) - { - int command; - bool receiveSuccess = wiNetwork::receiveData(command,it->first); - - if(!receiveSuccess){ - wiBackLog::post("Client disconnected."); - closesocket(it->first); - clients.erase(it++); - continue; - } - else{ - - switch(command){ - case PACKET_TYPE_CHANGENAME: - { - string text; - if(receiveText(text,it->first)){ - stringstream ss(""); - ss<<"Client "<second<<" now registered as "<second=text; - } - break; - } - case PACKET_TYPE_TEXTMESSAGE: - { - string text; - if(receiveText(text,it->first)){ - stringstream ss(""); - ss<second<<": "<first); - break; - } - default: - break; - } - } - - } - ++it; - } - - } - - - std::vector listClients(); - -#else -public: - wiServer(const std::string& newName = "SERVER", const std::string& ipaddress = "0.0.0.0", int port = PORT) {} - template - void Poll(T& data) {} - -#endif // WINSTORE_SUPPORT - -}; - - -#endif \ No newline at end of file diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 50fab5aac..d7247b9d0 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,9 +7,9 @@ namespace wiVersion // main engine core const int major = 0; // minor features, major updates - const int minor = 29; + const int minor = 30; // minor bug fixes, alterations, refactors, updates - const int revision = 2; + const int revision = 0; long GetVersion()