network library rewrite, added network test

This commit is contained in:
turanszkij
2019-10-08 18:57:45 +01:00
parent 4dfc021599
commit b15f3cef27
22 changed files with 426 additions and 844 deletions
+3 -13
View File
@@ -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.
+4 -2
View File
@@ -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.
+82
View File
@@ -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);
}
+1
View File
@@ -16,5 +16,6 @@ public:
void RunJobSystemTest();
void RunFontTest();
void RunSpriteTest();
void RunNetworkTest();
};
+1
View File
@@ -62,6 +62,7 @@
#include "wiGPUBVH.h"
#include "wiGPUSortLib.h"
#include "wiJobSystem.h"
#include "wiNetwork.h"
#ifdef _WIN32
+3 -6
View File
@@ -316,7 +316,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiBackLog.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiBackLog_BindLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)WickedEngine.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiClient.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiColor.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiCube.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiDirectInput.h" />
@@ -339,13 +338,13 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiInputManager_BindLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiIntersect_BindLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiJobSystem.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiPhysicsEngine.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiSceneSystem_BindLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiLua_Globals.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiLuna.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiMath.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork_BindLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiOcean.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiProfiler.h" />
@@ -358,7 +357,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiResourceManager_BindLua.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiSceneSystem.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiSceneSystem_Decl.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiServer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiSpinLock.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiSprite.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiSprite_BindLua.h" />
@@ -651,7 +649,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)Vector_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiBackLog.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiBackLog_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiClient.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiCube.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiDirectInput.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiEmittedParticle.cpp" />
@@ -671,11 +668,12 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiIntersect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiIntersect_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiJobSystem.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork_UWP.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork_Windows.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiPhysicsEngine_Bullet.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiSceneSystem_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiMath.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiOcean.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiProfiler.cpp" />
@@ -688,7 +686,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiResourceManager_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiSceneSystem.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiSceneSystem_Serializers.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiServer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiSprite.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiSprite_BindLua.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiStartupArguments.cpp" />
@@ -891,12 +891,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiHelper.h">
<Filter>ENGINE\Helpers</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiClient.h">
<Filter>ENGINE\Network</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiServer.h">
<Filter>ENGINE\Network</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiCube.h">
<Filter>ENGINE\Graphics</Filter>
</ClInclude>
@@ -909,9 +903,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiLua.h">
<Filter>ENGINE\Scripting</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork.h">
<Filter>ENGINE\Network</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiResourceManager.h">
<Filter>ENGINE\Helpers</Filter>
</ClInclude>
@@ -1134,6 +1125,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiAudio_BindLua.h">
<Filter>ENGINE\Scripting\LuaBindings</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiNetwork.h">
<Filter>ENGINE\Network</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)LUA\lapi.c">
@@ -1742,21 +1736,12 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiHelper.cpp">
<Filter>ENGINE\Helpers</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiClient.cpp">
<Filter>ENGINE\Network</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiServer.cpp">
<Filter>ENGINE\Network</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiCube.cpp">
<Filter>ENGINE\Graphics</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiLua.cpp">
<Filter>ENGINE\Scripting</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork.cpp">
<Filter>ENGINE\Network</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiResourceManager.cpp">
<Filter>ENGINE\Helpers</Filter>
</ClCompile>
@@ -1907,6 +1892,12 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiAudio_BindLua.cpp">
<Filter>ENGINE\Scripting\LuaBindings</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork_Windows.cpp">
<Filter>ENGINE\Network</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork_UWP.cpp">
<Filter>ENGINE\Network</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="$(MSBuildThisFileDirectory)fonts\default_font.dds">
+7 -7
View File
@@ -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;
}
+12 -10
View File
@@ -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);
-52
View File
@@ -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: "<<welcomeMsg<<" ,IP: "<<ipaddress<<" [port: "<<port<<"]";
wiBackLog::post(ss.str().c_str());
changeName(newName);
serverName=welcomeMsg;
}
}
else{
success=false;
stringstream ss("");
ss<<"Connecting to server on address: "<<ipaddress<< " [port "<<port<<"] FAILED with: "<<WSAGetLastError();
wiBackLog::post(ss.str().c_str());
}
}
wiClient::~wiClient(void)
{
wiNetwork::~wiNetwork();
}
bool wiClient::sendText(const std::string& text){
return wiNetwork::sendText(text,s);
}
bool wiClient::receiveText(string& text){
return wiNetwork::receiveText(text,s);
}
bool wiClient::changeName(const std::string& newName){
wiNetwork::changeName(newName);
wiNetwork::sendData(wiNetwork::PACKET_TYPE_CHANGENAME,s);
return wiNetwork::sendText(newName,s);
}
bool wiClient::sendMessage(const std::string& text){
wiNetwork::sendData(wiNetwork::PACKET_TYPE_TEXTMESSAGE,s);
return wiNetwork::sendText(text,s);
}
#endif
-153
View File
@@ -1,153 +0,0 @@
#ifndef CLIENT_H
#define CLIENT_H
#include "wiNetwork.h"
class wiClient : public wiNetwork
{
#ifndef WINSTORE_SUPPORT
public:
wiClient(const std::string& newName = "CLIENT", const std::string& ipaddress = "127.0.0.1", int port = PORT);
~wiClient(void);
std::string serverName;
bool sendText(const std::string& text);
bool receiveText(std::string& newName);
template <typename T>
bool sendData(const T& value){
Network::sendData(PACKET_TYPE_OTHER,s);
return Network::sendData(value,s);
}
template <typename T>
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<typename T>
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: "<<text;
wiBackLog::post(ss.str().c_str());
serverName=text;
}
break;
}
case PACKET_TYPE_TEXTMESSAGE:
{
string text;
if(receiveText(text)){
stringstream ss("");
ss<<serverName<<": "<<text;
wiBackLog::post(ss.str().c_str());
}
break;
}
case PACKET_TYPE_OTHER:
{
wiNetwork::receiveData(data,s);
break;
}
default:
break;
}
}
}
}
#else
public:
wiClient(const std::string& newName = "CLIENT", const std::string& ipaddress = "127.0.0.1", int port = PORT) {}
template<typename T>
void Poll(T& data) {}
#endif // WINSTORE_SUPPORT
};
#endif
+1
View File
@@ -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(); });
+1 -2
View File
@@ -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();
}
-60
View File
@@ -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 '"<<text<<"' failed with error: " << WSAGetLastError();
wiBackLog::post("[Error][sendText] Sending text failed!");
return false;
}
return true;
}
wiBackLog::post("[Error][sendText] Sending text length failed!");
return false;
}
bool wiNetwork::receiveText(std::string& text, SOCKET socket){
int textlen;
if(receiveData(textlen,socket)){
char* puffer=new char[textlen];
memset(puffer, '\0', textlen);
int received = recv(socket, puffer, textlen, 0);
if(received<=0){
//cout<< "[Error][receiveText] The recv call failed with error!\n";
wiBackLog::post("[Error][receiveText] The recv call failed with error!");
}
else if (received <= textlen) {
puffer[received]='\0';
text = puffer;
return true;
}
else{
//cout<< "[Error][receiveText] Too long request!\n";
wiBackLog::post("[Error][receiveText] Too long request!");
}
return false;
}
wiBackLog::post("[Error][receiveText] Didn't receive text length!");
return false;
}
#endif
+55 -81
View File
@@ -1,95 +1,69 @@
#ifndef NETWORK_H
#define NETWORK_H
#pragma once
#include "CommonInclude.h"
#include "wiBackLog.h"
#include <Windows.h>
#include <winsock.h>
#include <string>
#include <sstream>
#include <array>
#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 <typename T>
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 <typename T>
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<uint8_t, 4> 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);
}
+8 -100
View File
@@ -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<wiClient_BindLua>::FunctionType wiClient_BindLua::methods[] = {
lunamethod(wiClient_BindLua,Poll),
Luna<wiNetwork_BindLua>::FunctionType wiNetwork_BindLua::methods[] = {
{ NULL, NULL }
};
Luna<wiClient_BindLua>::PropertyType wiClient_BindLua::properties[] = {
Luna<wiNetwork_BindLua>::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<wiClient_BindLua>::Register(wiLua::GetGlobal()->GetLuaState());
Luna<wiNetwork_BindLua>::Register(wiLua::GetGlobal()->GetLuaState());
wiLua::GetGlobal()->RunText("network = Network()");
}
}
const char wiServer_BindLua::className[] = "Server";
Luna<wiServer_BindLua>::FunctionType wiServer_BindLua::methods[] = {
lunamethod(wiServer_BindLua,Poll),
{ NULL, NULL }
};
Luna<wiServer_BindLua>::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<wiServer_BindLua>::Register(wiLua::GetGlobal()->GetLuaState());
}
}
+5 -31
View File
@@ -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<wiClient_BindLua>::FunctionType methods[];
static Luna<wiClient_BindLua>::PropertyType properties[];
static Luna<wiNetwork_BindLua>::FunctionType methods[];
static Luna<wiNetwork_BindLua>::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<wiServer_BindLua>::FunctionType methods[];
static Luna<wiServer_BindLua>::PropertyType properties[];
wiServer_BindLua(lua_State* L);
~wiServer_BindLua();
int Poll(lua_State* L);
static void Bind();
};
+50
View File
@@ -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
+182
View File
@@ -0,0 +1,182 @@
#ifndef WINSTORE_SUPPORT
#include "wiNetwork.h"
#include "wiBackLog.h"
#include <sstream>
#include <winsock.h>
#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
-142
View File
@@ -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 "<<name<<" ,IP: "<<ipaddress<<" [port: "<<port<<"]";
wiBackLog::post(ss.str().c_str());
success=true;
}
else{
stringstream ss("");
ss<<"Creating server on address: "<<ipaddress<< " [port "<<port<<"] FAILED with: "<<WSAGetLastError();
wiBackLog::post(ss.str().c_str());
success=false;
}
}
wiServer::~wiServer(void)
{
for (std::map<SOCKET,string>::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<string> wiServer::listClients()
{
std::vector<string> ret(0);
for (std::map<SOCKET,string>::iterator it = clients.begin(); it != clients.end(); ++it) {
stringstream ss("");
ss<<it->second<<":"<<it->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<SOCKET,string>::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<SOCKET,string>::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
-165
View File
@@ -1,165 +0,0 @@
#ifndef SERVER_H
#define SERVER_H
#include "wiNetwork.h"
#include <ctime>
#include <map>
class wiServer : public wiNetwork
{
#ifndef WINSTORE_SUPPORT
private:
std::map<SOCKET, std::string> 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 <typename T>
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 <typename T>
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<typename T>
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<SOCKET,string>::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<<"] connected";
wiBackLog::post(ss.str().c_str());
ss.str("");
ss<<"Unnamed_client_"<<new_socket;
clients.insert(pair<SOCKET,string>(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<SOCKET,string>::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 "<<it->second<<" now registered as "<<text;
wiBackLog::post(ss.str().c_str());
it->second=text;
}
break;
}
case PACKET_TYPE_TEXTMESSAGE:
{
string text;
if(receiveText(text,it->first)){
stringstream ss("");
ss<<it->second<<": "<<text;
wiBackLog::post(ss.str().c_str());
}
break;
}
case PACKET_TYPE_OTHER:
{
wiNetwork::receiveData(data,it->first);
break;
}
default:
break;
}
}
}
++it;
}
}
std::vector<std::string> listClients();
#else
public:
wiServer(const std::string& newName = "SERVER", const std::string& ipaddress = "0.0.0.0", int port = PORT) {}
template<typename T>
void Poll(T& data) {}
#endif // WINSTORE_SUPPORT
};
#endif
+2 -2
View File
@@ -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()