New version
This commit is contained in:
@ -101,10 +101,12 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>D:\VoidNet\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>D:\VoidNet\VoidNetVS\x64\Debug\VoidNetVS.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -18,44 +18,47 @@
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\Config.hpp" />
|
||||
<ClInclude Include="..\..\include\Defs.hpp" />
|
||||
<ClInclude Include="..\..\include\Handshake.hpp" />
|
||||
<ClInclude Include="..\..\include\Init.hpp" />
|
||||
<ClInclude Include="..\..\include\NetworkBuffer.hpp" />
|
||||
<ClInclude Include="..\..\include\NetworkMessage.hpp" />
|
||||
<ClInclude Include="..\..\include\PluginManager.hpp" />
|
||||
<ClInclude Include="..\..\include\Serializer.hpp" />
|
||||
<ClInclude Include="..\..\include\TcpClient.hpp" />
|
||||
<ClInclude Include="..\..\include\TcpServer.hpp" />
|
||||
<ClInclude Include="..\..\include\UdpClient.hpp" />
|
||||
<ClInclude Include="..\..\include\UdpServer.hpp" />
|
||||
<ClInclude Include="..\..\include\Utility.hpp" />
|
||||
<ClInclude Include="..\..\include\VoidNetClient.hpp" />
|
||||
<ClInclude Include="..\..\include\VoidNetServer.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\Config.cpp" />
|
||||
<ClCompile Include="..\..\src\Handshake.cpp" />
|
||||
<ClCompile Include="..\..\src\Init.cpp" />
|
||||
<ClCompile Include="..\..\src\InitWindows.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\NetworkBuffer.cpp" />
|
||||
<ClCompile Include="..\..\src\NetworkMessage.cpp" />
|
||||
<ClCompile Include="..\..\src\Serializer.cpp" />
|
||||
<ClCompile Include="..\..\src\TcpClient.cpp" />
|
||||
<ClCompile Include="..\..\src\TcpServer.cpp" />
|
||||
<ClCompile Include="..\..\src\UdpClient.cpp" />
|
||||
<ClCompile Include="..\..\src\UdpServer.cpp" />
|
||||
<ClCompile Include="..\..\src\Utility.cpp" />
|
||||
<ClCompile Include="..\..\src\VoidNetClient.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\DEV_INFO" />
|
||||
<Text Include="..\..\TODO" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\Cookies.hpp" />
|
||||
<ClInclude Include="..\..\include\Enums.hpp" />
|
||||
<ClInclude Include="..\..\include\Headers.hpp" />
|
||||
<ClInclude Include="..\..\include\Http.hpp" />
|
||||
<ClInclude Include="..\..\include\Init.hpp" />
|
||||
<ClInclude Include="..\..\include\IPAddress.hpp" />
|
||||
<ClInclude Include="..\..\include\ISocket.hpp" />
|
||||
<ClInclude Include="..\..\include\Net.hpp" />
|
||||
<ClInclude Include="..\..\include\Parse.hpp" />
|
||||
<ClInclude Include="..\..\include\Request.hpp" />
|
||||
<ClInclude Include="..\..\include\Response.hpp" />
|
||||
<ClInclude Include="..\..\include\SecureSocket.hpp" />
|
||||
<ClInclude Include="..\..\include\Socket.hpp" />
|
||||
<ClInclude Include="..\..\include\TcpClient.hpp" />
|
||||
<ClInclude Include="..\..\include\TcpListener.hpp" />
|
||||
<ClInclude Include="..\..\include\TcpSocketBuilder.hpp" />
|
||||
<ClInclude Include="..\..\include\UdpSocket.hpp" />
|
||||
<ClInclude Include="..\..\include\UdpSocketBuilder.hpp" />
|
||||
<ClInclude Include="..\..\include\Uri.hpp" />
|
||||
<ClInclude Include="..\..\include\Util.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\Cookies.cpp" />
|
||||
<ClCompile Include="..\..\src\Headers.cpp" />
|
||||
<ClCompile Include="..\..\src\Http.cpp" />
|
||||
<ClCompile Include="..\..\src\IPAddress.cpp" />
|
||||
<ClCompile Include="..\..\src\Request.cpp" />
|
||||
<ClCompile Include="..\..\src\Response.cpp" />
|
||||
<ClCompile Include="..\..\src\SecureSocket.cpp" />
|
||||
<ClCompile Include="..\..\src\Socket.cpp" />
|
||||
<ClCompile Include="..\..\src\TcpClient.cpp" />
|
||||
<ClCompile Include="..\..\src\TcpListener.cpp" />
|
||||
<ClCompile Include="..\..\src\TcpSocketBuilder.cpp" />
|
||||
<ClCompile Include="..\..\src\UdpSocket.cpp" />
|
||||
<ClCompile Include="..\..\src\Uri.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{5172321E-CCB0-4A77-9F3D-FAAF0084F434}</ProjectGuid>
|
||||
<RootNamespace>VoidNetVS</RootNamespace>
|
||||
@ -76,7 +79,7 @@
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
@ -120,7 +123,9 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>../include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<PreprocessorDefinitions>_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
|
||||
@ -7,97 +7,118 @@
|
||||
<Filter Include="src">
|
||||
<UniqueIdentifier>{4c99f44e-3ff9-4d5c-a3a1-27d1f02b0b7f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\Init.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Defs.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\TcpClient.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Utility.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Config.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\NetworkMessage.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\VoidNetClient.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\VoidNetServer.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\NetworkBuffer.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Serializer.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\TcpServer.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Handshake.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\UdpClient.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\UdpServer.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\PluginManager.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\Init.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Utility.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Config.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\NetworkBuffer.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Serializer.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\NetworkMessage.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\VoidNetClient.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpServer.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\InitWindows.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Handshake.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpClient.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\UdpClient.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\UdpServer.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<Filter Include="include\Http">
|
||||
<UniqueIdentifier>{b40bea23-e721-4605-9fb2-1a893c226525}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\Http">
|
||||
<UniqueIdentifier>{d78dfc6c-3983-4cd8-9cb1-d101a0162e77}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\TODO" />
|
||||
<Text Include="..\..\DEV_INFO" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\Enums.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Init.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\IPAddress.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\ISocket.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Net.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\SecureSocket.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Socket.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\TcpClient.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\TcpListener.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\TcpSocketBuilder.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\UdpSocket.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\UdpSocketBuilder.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Util.hpp">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Cookies.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Headers.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Http.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Request.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Response.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Parse.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\Uri.hpp">
|
||||
<Filter>include\Http</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\IPAddress.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\SecureSocket.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Socket.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpClient.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpListener.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\TcpSocketBuilder.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\UdpSocket.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Cookies.cpp">
|
||||
<Filter>src\Http</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Headers.cpp">
|
||||
<Filter>src\Http</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Http.cpp">
|
||||
<Filter>src\Http</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Request.cpp">
|
||||
<Filter>src\Http</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Response.cpp">
|
||||
<Filter>src\Http</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\Uri.cpp">
|
||||
<Filter>src\Http</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -1,27 +0,0 @@
|
||||
#ifndef CONFIG_HPP
|
||||
#define CONFIG_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Utility.hpp"
|
||||
|
||||
struct Config
|
||||
{
|
||||
static void Initialize();
|
||||
|
||||
static void SetUsingConsole(bool value);
|
||||
static bool GetUsingConsole();
|
||||
|
||||
static void SetLogToFile(bool value);
|
||||
static bool GetLogToFile();
|
||||
|
||||
static Utility::ConfigReader Configuration;
|
||||
|
||||
private:
|
||||
static bool using_console;
|
||||
static bool log_to_file;
|
||||
};
|
||||
|
||||
#endif
|
||||
100
include/Cookies.hpp
Normal file
100
include/Cookies.hpp
Normal file
@ -0,0 +1,100 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Cookie
|
||||
{
|
||||
public:
|
||||
Cookie(const std::string& text);
|
||||
|
||||
Cookie() : m_httpOnly(false), m_secure(false)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string& GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const std::string& GetPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
bool IsHttpOnly() const
|
||||
{
|
||||
return m_httpOnly;
|
||||
}
|
||||
|
||||
bool IsSecure() const
|
||||
{
|
||||
return m_secure;
|
||||
}
|
||||
|
||||
void SetName(const std::string& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void SetValue(const std::string& value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
void SetPath(const std::string& path)
|
||||
{
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
void SetHttpOnly(bool httpOnly)
|
||||
{
|
||||
m_httpOnly = httpOnly;
|
||||
}
|
||||
|
||||
void SetSecure(bool secure)
|
||||
{
|
||||
m_secure = secure;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_value;
|
||||
std::string m_path;
|
||||
bool m_httpOnly;
|
||||
bool m_secure;
|
||||
};
|
||||
|
||||
class Cookies
|
||||
{
|
||||
public:
|
||||
const Cookie operator[](const std::string &name) const;
|
||||
|
||||
std::map<std::string, Cookie>::const_iterator begin() const
|
||||
{
|
||||
return m_cookie.begin();
|
||||
}
|
||||
|
||||
std::map<std::string, Cookie>::const_iterator end() const
|
||||
{
|
||||
return m_cookie.end();
|
||||
}
|
||||
|
||||
void SetCookie(Cookie const& cookie);
|
||||
|
||||
static const std::string HOST;
|
||||
static const std::string CONTENT_LENGTH;
|
||||
static const std::string ACCEPT_ENCODING;
|
||||
static const std::string CONNECTION;
|
||||
private:
|
||||
std::map<std::string, Cookie> m_cookie;
|
||||
};
|
||||
}
|
||||
256
include/Defs.hpp
256
include/Defs.hpp
@ -1,256 +0,0 @@
|
||||
#ifndef DEFS_HPP
|
||||
#define DEFS_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WINSOCKAPI_
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
|
||||
#undef GetBinaryType
|
||||
#undef GetShortPathName
|
||||
#undef GetLongPathName
|
||||
#undef GetEnvironmentStrings
|
||||
#undef SetEnvironmentStrings
|
||||
#undef FreeEnvironmentStrings
|
||||
#undef FormatMessage
|
||||
#undef EncryptFile
|
||||
#undef DecryptFile
|
||||
#undef CreateMutex
|
||||
#undef OpenMutex
|
||||
#undef CreateEvent
|
||||
#undef OpenEvent
|
||||
#undef CreateSemaphore
|
||||
#undef OpenSemaphore
|
||||
#undef LoadLibrary
|
||||
#undef GetModuleFileName
|
||||
#undef CreateProcess
|
||||
#undef GetCommandLine
|
||||
#undef GetEnvironmentVariable
|
||||
#undef SetEnvironmentVariable
|
||||
#undef ExpandEnvironmentStrings
|
||||
#undef OutputDebugString
|
||||
#undef FindResource
|
||||
#undef UpdateResource
|
||||
#undef FindAtom
|
||||
#undef AddAtom
|
||||
#undef GetSystemDirectory
|
||||
#undef GetTempPath
|
||||
#undef GetTempFileName
|
||||
#undef SetCurrentDirectory
|
||||
#undef GetCurrentDirectory
|
||||
#undef CreateDirectory
|
||||
#undef RemoveDirectory
|
||||
#undef CreateFile
|
||||
#undef DeleteFile
|
||||
#undef SearchPath
|
||||
#undef CopyFile
|
||||
#undef MoveFile
|
||||
#undef ReplaceFile
|
||||
#undef GetComputerName
|
||||
#undef SetComputerName
|
||||
#undef GetUserName
|
||||
#undef LogonUser
|
||||
#undef GetVersion
|
||||
#undef GetObject
|
||||
#undef SendMessage
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef signed __int64 int_ptr;
|
||||
typedef unsigned __int64 uint_ptr;
|
||||
#else
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
#endif // win64
|
||||
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef signed long long int_ptr, int64;
|
||||
typedef unsigned long long uint_ptr, uint64;
|
||||
#else
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
|
||||
#ifdef __LP64__
|
||||
typedef signed long int64;
|
||||
typedef unsigned long uint64;
|
||||
#else
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif // __LP64__
|
||||
|
||||
#endif // win64
|
||||
|
||||
#elif defined(__DECCXX)
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
|
||||
#ifdef __VMS
|
||||
#ifdef __32BITS
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
#else
|
||||
typedef signed __int64 int_ptr;
|
||||
typedef unsigned __int64 uint_ptr;
|
||||
#endif // __32BITS
|
||||
#else
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr
|
||||
#endif // __VMS
|
||||
|
||||
#elif defined(__HP_aCC)
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
|
||||
#ifdef __LP64__
|
||||
typedef signed long int64;
|
||||
typedef unsigned long uint64;
|
||||
#else
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif // __LP64__
|
||||
|
||||
#elif defined(__SUNPRO_CC)
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_otr
|
||||
|
||||
#ifdef __sparcv9
|
||||
typedef signed long int64;
|
||||
typedef unsigned long uint64;
|
||||
#else
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif // __sparcv9
|
||||
|
||||
#elif defined(__IBMCPP__)
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
|
||||
#ifdef __64BIT__
|
||||
typedef signed long int64;
|
||||
typedef unsigned long uint64;
|
||||
#else
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif // __64BIT__
|
||||
|
||||
#elif defined(__sgi)
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
|
||||
#if _MIPS_SZLONG == 64
|
||||
typedef signed long int64;
|
||||
typedef unsigned long uint64;
|
||||
#else
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif // _MIPS_SZLONG
|
||||
|
||||
#elif defined(_DIAB_TOOL)
|
||||
|
||||
typedef signed char int8, sbyte;
|
||||
typedef unsigned char uint8, byte;
|
||||
typedef signed short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed int in32;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed long int_ptr;
|
||||
typedef unsigned long uint_ptr;
|
||||
typedef signed long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
#endif // compiler data type defenitions
|
||||
|
||||
typedef long long longlong;
|
||||
|
||||
const uint16 default_client_port = 60250;
|
||||
const uint16 default_server_port = 61250;
|
||||
|
||||
enum DistributionType
|
||||
{
|
||||
All = 1, // Others and Server
|
||||
AllAndMe, // Other, Server and the user sending the message
|
||||
Server,
|
||||
Others,
|
||||
ID,
|
||||
};
|
||||
|
||||
enum ConnectionCode
|
||||
{
|
||||
Accept,
|
||||
Reject,
|
||||
Close
|
||||
};
|
||||
|
||||
enum InternalTags
|
||||
{
|
||||
ConnectTag = 254,
|
||||
DisconnectTag = 255,
|
||||
};
|
||||
|
||||
#define IS_HANDSHAKE(name) name.subject == 1 || (name.tag == DisconnectTag || name.tag == ConnectTag || name.tag == Accept || name.tag == Close || name.tag == Reject)
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
void closesocket(int socket) { close(socket); }
|
||||
#endif
|
||||
|
||||
#endif // DEFS_HPP
|
||||
171
include/Enums.hpp
Normal file
171
include/Enums.hpp
Normal file
@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
|
||||
#undef DELETE
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
enum class SocketParam
|
||||
{
|
||||
CanRead,
|
||||
CanWrite,
|
||||
HasError,
|
||||
};
|
||||
|
||||
enum class SocketReturn
|
||||
{
|
||||
Yes,
|
||||
No,
|
||||
EncounteredError,
|
||||
};
|
||||
|
||||
enum class SocketErrors
|
||||
{
|
||||
SE_SOCKET_ERROR = -1,
|
||||
SE_NO_ERROR,
|
||||
SE_EINTR,
|
||||
SE_EBADF,
|
||||
SE_EACCES,
|
||||
SE_EFAULT,
|
||||
SE_EINVAL,
|
||||
SE_EMFILE,
|
||||
SE_EWOULDBLOCK,
|
||||
SE_EINPROGRESS,
|
||||
SE_EALREADY,
|
||||
SE_ENOTSOCK,
|
||||
SE_EDESTADDRREQ,
|
||||
SE_EMSGSIZE,
|
||||
SE_EPROTOTYPE,
|
||||
SE_ENOPROTOOPT,
|
||||
SE_EPROTONOSUPPORT,
|
||||
SE_ESOCKTNOSUPPORT,
|
||||
SE_EOPNOTSUPP,
|
||||
SE_EPFNOSUPPORT,
|
||||
SE_EAFNOSUPPORT,
|
||||
SE_EADDRINUSE,
|
||||
SE_EADDRNOTAVAIL,
|
||||
SE_ENETDOWN,
|
||||
SE_ENETUNREACH,
|
||||
SE_ENETRESET,
|
||||
SE_ECONNABORTED,
|
||||
SE_ECONNRESET,
|
||||
SE_ENOBUFS,
|
||||
SE_EISCONN,
|
||||
SE_ENOTCONN,
|
||||
SE_ESHUTDOWN,
|
||||
SE_ETOOMANYREFS,
|
||||
SE_ETIMEDOUT,
|
||||
SE_ECONNREFUSED,
|
||||
SE_ELOOP,
|
||||
SE_ENAMETOOLONG,
|
||||
SE_EHOSTDOWN,
|
||||
SE_EHOSTUNREACH,
|
||||
SE_ENOTEMPTY,
|
||||
SE_EPROCLIM,
|
||||
SE_EUSERS,
|
||||
SE_EDQUOT,
|
||||
SE_ESTALE,
|
||||
SE_EREMOTE,
|
||||
SE_EDISCON,
|
||||
SE_SYSNOTREADY,
|
||||
SE_VERNOTSUPPORTED,
|
||||
SE_NOTINITIALISED,
|
||||
SE_HOST_NOT_FOUND,
|
||||
SE_TRY_AGAIN,
|
||||
SE_NO_RECOVERY,
|
||||
SE_NO_DATA,
|
||||
SE_UDP_ERR_PORT_UNREACH,
|
||||
SE_ADDRFAMILY,
|
||||
SE_SYSTEM,
|
||||
SE_NODEV,
|
||||
SE_GET_LAST_ERROR_CODE,
|
||||
};
|
||||
|
||||
enum class SocketType
|
||||
{
|
||||
Unknown = -1,
|
||||
Datagram = 2,
|
||||
Streaming = 1,
|
||||
};
|
||||
|
||||
enum class SocketProtocol
|
||||
{
|
||||
IPv4 = 2, // AF_INET
|
||||
IPv6 = 23 // AF_INET6
|
||||
};
|
||||
|
||||
enum class SocketReceiveFlags
|
||||
{
|
||||
None = 0,
|
||||
Peek = 2,
|
||||
WaitAll = 0x100,
|
||||
};
|
||||
|
||||
enum class SocketWaitConditions
|
||||
{
|
||||
WaitForRead,
|
||||
WaitForWrite,
|
||||
WaitForReadOrWrite,
|
||||
};
|
||||
|
||||
enum class SocketConnectionState
|
||||
{
|
||||
NotConnected,
|
||||
Connected,
|
||||
ConnectionError,
|
||||
};
|
||||
|
||||
enum class HttpStatus
|
||||
{
|
||||
INVALID_CODE = 0,
|
||||
CONTINUE = 100,
|
||||
SWITCHING_PROTOCOLS = 101,
|
||||
OK = 200,
|
||||
CREATED = 201,
|
||||
ACCEPTED = 202,
|
||||
NON_AUTHORITATIVE_INFO = 203,
|
||||
NO_CONTENT = 204,
|
||||
RESET_CONTENT = 205,
|
||||
PARTIAL_CONTENT = 206,
|
||||
MULTIPLE_CHOICES = 300,
|
||||
MOVED_PERMANENTLY = 301,
|
||||
FOUND = 302,
|
||||
SEE_OTHER = 303,
|
||||
NOT_MODIFIED = 304,
|
||||
USE_PROXY = 305,
|
||||
TEMPORARY_REDIRECT = 307,
|
||||
BAD_REQUEST = 400,
|
||||
UNAUTHORIZED = 401,
|
||||
PAYMENT_REQUIRED = 402,
|
||||
FORBIDDEN = 403,
|
||||
NOT_FOUND = 404,
|
||||
METHOD_NOT_ALLOWED = 405,
|
||||
NOT_ACCEPTABLE = 406,
|
||||
PROXY_AUTHENTICATION_REQUIRED = 407,
|
||||
REQUEST_TIMEOUT = 408,
|
||||
CONFLICT = 409,
|
||||
GONE = 410,
|
||||
LENGTH_REQUIRED = 411,
|
||||
PRECONDITION_FAILED = 412,
|
||||
REQUEST_ENTITY_TOO_LARGE = 413,
|
||||
UNSUPPORTED_MEDIA_TYPE = 415,
|
||||
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
|
||||
EXPECTATION_FAILED = 417,
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
NOT_IMPLEMENTED = 501,
|
||||
BAD_GATEWAY = 502,
|
||||
SERVICE_UNAVAILABLE = 503,
|
||||
GATEWAY_TIMEOUT = 504,
|
||||
VERSION_NOT_SUPPORTED = 505,
|
||||
};
|
||||
|
||||
enum class Method
|
||||
{
|
||||
GET,
|
||||
HEAD,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
TRACE,
|
||||
CONNECT,
|
||||
};
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
#ifndef HANDSHAKE_HPP
|
||||
#define HANDSHAKE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "NetworkMessage.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct Handshake
|
||||
{
|
||||
Handshake();
|
||||
Handshake(uint16 id, byte con_code, byte distribution_mode);
|
||||
~Handshake();
|
||||
|
||||
static const std::vector<byte> &EncodeHandshake(const Handshake &handshake);
|
||||
static Handshake &DecodeHandshake(const std::vector<byte> &bytes);
|
||||
static const NetworkMessage &HandshakeToNetworkMessage(const Handshake &handshake);
|
||||
static const Handshake &NetworkMessageToHandshake(const NetworkMessage &message);
|
||||
|
||||
uint16 id;
|
||||
byte con_code;
|
||||
byte distribution_mode;
|
||||
};
|
||||
|
||||
#endif
|
||||
33
include/Headers.hpp
Normal file
33
include/Headers.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Headers
|
||||
{
|
||||
public:
|
||||
const std::string operator[](const std::string &name) const;
|
||||
|
||||
std::multimap<std::string, std::string>::const_iterator begin() const
|
||||
{
|
||||
return m_header.begin();
|
||||
}
|
||||
|
||||
std::multimap<std::string, std::string>::const_iterator end() const
|
||||
{
|
||||
return m_header.end();
|
||||
}
|
||||
|
||||
void AddHeader(std::string const& name, std::string const& value);
|
||||
|
||||
static std::string const HOST;
|
||||
static std::string const CONTENT_LENGTH;
|
||||
static std::string const ACCEPT_ENCODING;
|
||||
static std::string const CONNECTION;
|
||||
private:
|
||||
std::multimap<std::string, std::string> m_header;
|
||||
};
|
||||
}
|
||||
20
include/Http.hpp
Normal file
20
include/Http.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Response.hpp"
|
||||
#include "Request.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Http
|
||||
{
|
||||
public:
|
||||
static Response Get(std::string const& path, std::string const& data = "");
|
||||
static Response Post(std::string const& path, std::string const& data = "");
|
||||
|
||||
private:
|
||||
static Response Send(Request const& request);
|
||||
static std::string Str(Request const& request);
|
||||
};
|
||||
}
|
||||
108
include/IPAddress.hpp
Normal file
108
include/IPAddress.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "Net.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class IPAddress
|
||||
{
|
||||
public:
|
||||
inline IPAddress(const IPAddress &addr, uint16_t port)
|
||||
: m_address(addr.ToInteger())
|
||||
, m_valid(true)
|
||||
, m_port(port)
|
||||
{
|
||||
}
|
||||
|
||||
inline IPAddress()
|
||||
: m_address(0)
|
||||
, m_valid(false)
|
||||
, m_port(DEFAULT_SERVER_PORT)
|
||||
{
|
||||
}
|
||||
|
||||
inline IPAddress(const std::string& address, uint16_t port = DEFAULT_SERVER_PORT)
|
||||
: m_address(0)
|
||||
, m_valid(false)
|
||||
, m_port(port)
|
||||
{
|
||||
Resolve(address);
|
||||
}
|
||||
|
||||
inline IPAddress(const char* address, uint16_t port = DEFAULT_SERVER_PORT)
|
||||
: m_address(0)
|
||||
, m_valid(false)
|
||||
, m_port(port)
|
||||
{
|
||||
Resolve(address);
|
||||
}
|
||||
|
||||
inline IPAddress(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t port = DEFAULT_SERVER_PORT)
|
||||
: m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
|
||||
, m_valid(true)
|
||||
, m_port(port)
|
||||
{
|
||||
}
|
||||
|
||||
inline explicit IPAddress(uint32_t address, uint16_t port = DEFAULT_SERVER_PORT)
|
||||
: m_address(htonl(address))
|
||||
, m_valid(true)
|
||||
, m_port(port)
|
||||
{
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
inline uint32_t ToInteger() const { return ntohl(m_address); }
|
||||
inline uint16_t GetPort() const { return m_port; }
|
||||
|
||||
static const IPAddress None;
|
||||
static const IPAddress Any;
|
||||
static const IPAddress LocalHost;
|
||||
static const IPAddress Broadcast;
|
||||
|
||||
inline sockaddr_in ToCAddr() const
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(ToInteger());
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(GetPort());
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend bool operator <(const IPAddress& left, const IPAddress& right);
|
||||
|
||||
void Resolve(const std::string& address);
|
||||
|
||||
private:
|
||||
uint32_t m_address;
|
||||
bool m_valid;
|
||||
uint16_t m_port;
|
||||
};
|
||||
|
||||
inline bool operator ==(const IPAddress& left, const IPAddress& right) { return !(left < right) && !(right < left); }
|
||||
inline bool operator !=(const IPAddress& left, const IPAddress& right) { return !(left == right); }
|
||||
inline bool operator <(const IPAddress& left, const IPAddress& right) { return std::make_pair(left.m_valid, left.m_address) < std::make_pair(right.m_valid, right.m_address); }
|
||||
inline bool operator >(const IPAddress& left, const IPAddress& right) { return right < left; }
|
||||
inline bool operator <=(const IPAddress& left, const IPAddress& right) { return !(right < left); }
|
||||
inline bool operator >=(const IPAddress& left, const IPAddress& right) { return !(left < right); }
|
||||
|
||||
inline std::istream& operator >>(std::istream& stream, IPAddress& address)
|
||||
{
|
||||
std::string str;
|
||||
stream >> str;
|
||||
address = IPAddress(str);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& stream, const IPAddress& address) { return stream << address.ToString(); }
|
||||
}
|
||||
74
include/ISocket.hpp
Normal file
74
include/ISocket.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "Net.hpp"
|
||||
#include "IPAddress.hpp"
|
||||
#include "Enums.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Socket;
|
||||
|
||||
class ISocket
|
||||
{
|
||||
public:
|
||||
inline ISocket()
|
||||
: m_socketType(SocketType::Unknown)
|
||||
, m_protocol(SocketProtocol::IPv4)
|
||||
{
|
||||
}
|
||||
|
||||
inline ISocket(SocketType InSocketType, SocketProtocol protocol = SocketProtocol::IPv4)
|
||||
: m_socketType(InSocketType)
|
||||
, m_protocol(protocol)
|
||||
{
|
||||
}
|
||||
|
||||
inline virtual ~ISocket()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Close() = 0;
|
||||
virtual bool Bind(const IPAddress &addr) = 0;
|
||||
virtual bool Connect(const IPAddress& addr) = 0;
|
||||
virtual bool Listen() = 0;
|
||||
virtual bool WaitForPendingConnection(bool& hasPendingConnection, std::chrono::milliseconds t) = 0;
|
||||
virtual bool HasPendingData(uint32_t& pendingDataSize) = 0;
|
||||
virtual std::unique_ptr<Socket> Accept() = 0;
|
||||
virtual bool SendTo(const uint8_t* data, int32_t count, int32_t& sent, const IPAddress& addrDest) = 0;
|
||||
virtual bool Send(const uint8_t* data, int32_t count, int32_t& sent) = 0;
|
||||
virtual bool RecvFrom(uint8_t* data, int32_t size, int32_t& read, IPAddress& srcAddr, SocketReceiveFlags flags = SocketReceiveFlags::None) = 0;
|
||||
virtual bool Recv(uint8_t* data, int32_t size, int32_t& read, SocketReceiveFlags flags = SocketReceiveFlags::None) = 0;
|
||||
virtual bool Wait(SocketWaitConditions cond, std::chrono::milliseconds t) = 0;
|
||||
virtual SocketConnectionState GetConnectionState() = 0;
|
||||
virtual void GetAddress(IPAddress& outAddr) = 0;
|
||||
virtual bool GetPeerAddress(IPAddress& outAddr) = 0;
|
||||
virtual bool SetNonBlocking(bool isNonBlocking = true) = 0;
|
||||
virtual bool JoinMulticastGroup(const IPAddress& addrStr) = 0;
|
||||
virtual bool LeaveMulticastGroup(const IPAddress& addrStr) = 0;
|
||||
virtual bool SetMulticastLoopback(bool loopback) = 0;
|
||||
virtual bool SetMulticastTtl(uint8_t timeToLive) = 0;
|
||||
virtual bool SetReuseAddr(bool allowReuse = true) = 0;
|
||||
virtual bool SetLinger(bool shouldLinger = true, int32_t t = 0) = 0;
|
||||
virtual bool SetSendBufferSize(int32_t size, int32_t& newSize) = 0;
|
||||
virtual bool SetReceiveBufferSize(int32_t size, int32_t& newSize) = 0;
|
||||
virtual uint32_t GetPort() = 0;
|
||||
|
||||
inline SocketType GetSocketType() const
|
||||
{
|
||||
return m_socketType;
|
||||
}
|
||||
|
||||
inline SocketProtocol GetSocketProtocol() const
|
||||
{
|
||||
return m_protocol;
|
||||
}
|
||||
|
||||
private:
|
||||
const SocketType m_socketType;
|
||||
const SocketProtocol m_protocol;
|
||||
};
|
||||
}
|
||||
@ -1,25 +1,40 @@
|
||||
#ifndef INIT_HPP
|
||||
#define INIT_HPP
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
static WSADATA WsaData;
|
||||
static bool Initialized;
|
||||
}
|
||||
|
||||
struct Initialization
|
||||
{
|
||||
static bool Initialize();
|
||||
inline static bool Initialize()
|
||||
{
|
||||
if (priv::Initialized) return true;
|
||||
return (priv::Initialized = WSAStartup(MAKEWORD(2, 2), &priv::WsaData)) == 0;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
const WSADATA &GetData();
|
||||
#endif
|
||||
inline static void Cleanup()
|
||||
{
|
||||
if (priv::Initialized)
|
||||
{
|
||||
WSACleanup();
|
||||
priv::Initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef _MSC_VER
|
||||
static WSADATA wsa_data;
|
||||
#endif
|
||||
};
|
||||
#else
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
inline static bool Initialize() { return true; }
|
||||
inline static void Cleanup() { }
|
||||
}
|
||||
|
||||
#endif
|
||||
40
include/Net.hpp
Normal file
40
include/Net.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#undef SendMessage
|
||||
#undef SetPort
|
||||
|
||||
#define poll WSAPoll
|
||||
#define ioctl ioctlsocket
|
||||
|
||||
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define SOCKET_ERROR -1
|
||||
#define NO_ERROR 0
|
||||
#define INVALID_SOCKET NO_ERROR
|
||||
|
||||
#define SOCKET int
|
||||
#define closesocket close
|
||||
#define ioctlsocket ioctl
|
||||
|
||||
int closesocket(SOCKET soc)
|
||||
{
|
||||
return close(soc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SERVER_PORT 61250
|
||||
@ -1,24 +0,0 @@
|
||||
#ifndef NETWORK_BUFFER_HPP
|
||||
#define NETWORK_BUFFER_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "Utility.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct NetworkBuffer
|
||||
{
|
||||
NetworkBuffer();
|
||||
~NetworkBuffer();
|
||||
|
||||
std::vector<byte> header; // size must always be sizeof(int32)
|
||||
std::vector<byte> body;
|
||||
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,32 +0,0 @@
|
||||
#ifndef NETWORK_MESSAGE_HPP
|
||||
#define NETWORK_MESSAGE_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "NetworkBuffer.hpp"
|
||||
|
||||
struct NetworkMessage
|
||||
{
|
||||
NetworkMessage();
|
||||
NetworkMessage(const NetworkBuffer &buffer);
|
||||
NetworkMessage(uint16 sender, byte distribution_mode, uint16 destination_id, byte tag, byte subject);
|
||||
~NetworkMessage();
|
||||
|
||||
static const NetworkBuffer &EncodeMessage(const NetworkMessage &message);
|
||||
|
||||
static const NetworkMessage &DecodeMessage(const NetworkBuffer &buffer);
|
||||
|
||||
uint16 sender = -2;
|
||||
byte distribution_mode;
|
||||
uint16 destination_id;
|
||||
byte tag;
|
||||
byte subject;
|
||||
void *data;
|
||||
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
67
include/Parse.hpp
Normal file
67
include/Parse.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
template <typename T>
|
||||
class ParseResult
|
||||
{
|
||||
public:
|
||||
T value;
|
||||
char const* ch;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
static ParseResult<std::string> ParseUntil(char const* str, F func)
|
||||
{
|
||||
ParseResult<std::string> result{};
|
||||
char const* ch = str;
|
||||
for (; *ch && !func(*ch); ++ch)
|
||||
{
|
||||
}
|
||||
|
||||
result.value = std::string(str, ch - str);
|
||||
result.ch = ch;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
static inline ParseResult<std::string> ParseWhile(char const* str, F func)
|
||||
{
|
||||
ParseResult<std::string> result{};
|
||||
char const* ch = str;
|
||||
for (; *ch && func(*ch); ++ch)
|
||||
{
|
||||
}
|
||||
|
||||
result.value = std::string(str, ch - str);
|
||||
result.ch = ch;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline ParseResult<std::string> ParseToken(char const* str)
|
||||
{
|
||||
auto token = ParseUntil(str, isspace);
|
||||
token.ch = ParseWhile(token.ch, isspace).ch;
|
||||
return token;
|
||||
}
|
||||
|
||||
static inline ParseResult<std::string> parseCrLf(char const* str)
|
||||
{
|
||||
auto cr = ParseUntil(str, [](char ch) { return ch == '\r'; });
|
||||
if (*cr.ch == '\r')
|
||||
cr.ch++;
|
||||
return ParseWhile(cr.ch, [](char ch)
|
||||
{
|
||||
return isspace(ch) && ch != '\r';
|
||||
});
|
||||
}
|
||||
|
||||
static inline ParseResult<std::string> ParseWhitespace(char const* str)
|
||||
{
|
||||
return ParseWhile(str, isspace);
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
#ifndef PLUGIN_MANAGER_HPP
|
||||
#define PLUGIN_MANAGER_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
struct PluginManager
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
52
include/Request.hpp
Normal file
52
include/Request.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Uri.hpp"
|
||||
#include "Headers.hpp"
|
||||
#include "Enums.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Request
|
||||
{
|
||||
public:
|
||||
Method GetMethod() const
|
||||
{
|
||||
return m_method;
|
||||
}
|
||||
|
||||
const Uri& GetUri() const
|
||||
{
|
||||
return m_uri;
|
||||
}
|
||||
|
||||
const std::string& GetPath() const
|
||||
{
|
||||
return m_uri.GetPath();
|
||||
}
|
||||
|
||||
const std::string& GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const std::string GetHeaderElement(const std::string& name) const;
|
||||
|
||||
const Headers& GetHeaders() const
|
||||
{
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
void SetMethod(Method method);
|
||||
void SetUri(const Uri& path);
|
||||
void SetData(const std::string& data);
|
||||
void AddHeader(const std::string& name, const std::string& value);
|
||||
|
||||
private:
|
||||
Method m_method = Method::GET;
|
||||
Uri m_uri;
|
||||
std::string m_data;
|
||||
Headers m_headers;
|
||||
};
|
||||
}
|
||||
43
include/Response.hpp
Normal file
43
include/Response.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Headers.hpp"
|
||||
#include "Cookies.hpp"
|
||||
#include "Enums.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Response
|
||||
{
|
||||
public:
|
||||
Response(const std::string& text);
|
||||
Response() {};
|
||||
|
||||
HttpStatus GetStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
const std::string& daGetDatata() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const std::string GetHeader(const std::string& name) const;
|
||||
const Cookie GetCookie(const std::string& name) const;
|
||||
|
||||
void SetStatus(HttpStatus status);
|
||||
void SetData(const std::string& data);
|
||||
void SetHeader(const std::string& name, const std::string& value);
|
||||
void SetCookie(const Cookie& cookie);
|
||||
|
||||
private:
|
||||
HttpStatus m_status = HttpStatus::INVALID_CODE;
|
||||
std::string m_data;
|
||||
Headers m_headers;
|
||||
Cookies m_cookies;
|
||||
};
|
||||
}
|
||||
43
include/SecureSocket.hpp
Normal file
43
include/SecureSocket.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "Socket.hpp"
|
||||
|
||||
//#include <openssl/rand.h>
|
||||
//#include <openssl/ssl.h>
|
||||
//#include <openssl/err.h>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class SecureSocket
|
||||
{
|
||||
public:
|
||||
SecureSocket();
|
||||
|
||||
bool Connect(const IPAddress& addr);
|
||||
bool Close() const;
|
||||
bool HasPendingData(uint32_t& pendingDataSize) const;
|
||||
bool Send(uint8_t* data, int32_t count, int32_t &sent, int flags = 0); // Execute 1 write() syscall
|
||||
bool Recv(uint8_t* data, int32_t count, int32_t &read, int flags = 0); // Execte 1 read() syscall
|
||||
bool Wait(SocketWaitConditions cond, std::chrono::milliseconds t) const;
|
||||
SocketConnectionState GetConnectionState() const;
|
||||
void GetAddress(IPAddress& outAddr) const;
|
||||
int32_t GetPort() const;
|
||||
|
||||
void UseCertificateFile(std::string const& path);
|
||||
void UsePrivateKeyFile(std::string const& path);
|
||||
|
||||
private:
|
||||
bool SendRaw(uint8_t* buf, size_t len, int flags = 0);
|
||||
bool SendFromBio(int flags = 0);
|
||||
bool RecvToBio(int flags = 0);
|
||||
void HandleReturn(size_t ret);
|
||||
|
||||
std::unique_ptr<Socket> m_socket;
|
||||
|
||||
//SSL_CTX* m_context;
|
||||
//SSL* m_conn;
|
||||
//BIO* m_in;
|
||||
//BIO* m_out;
|
||||
bool m_eof;
|
||||
};
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
#ifndef SERIALIZER_HPP
|
||||
#define SERIALIZER_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include <vector>
|
||||
|
||||
struct Serializer
|
||||
{
|
||||
template<typename T> static const std::vector<byte> &to_bytes(const T &object);
|
||||
template<typename T> static const T& from_bytes(const std::vector<byte> &bytes, T& object);
|
||||
};
|
||||
|
||||
#endif
|
||||
84
include/Socket.hpp
Normal file
84
include/Socket.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include "ISocket.hpp"
|
||||
#include "Enums.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Socket : public ISocket
|
||||
{
|
||||
public:
|
||||
inline Socket(SocketType socketType, SocketProtocol protocol = SocketProtocol::IPv4)
|
||||
: ISocket(socketType, protocol)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
inline Socket(SOCKET newSocket, SocketType socketType, SocketProtocol protocol = SocketProtocol::IPv4)
|
||||
: ISocket(socketType, protocol)
|
||||
, m_socket(newSocket)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
virtual ~Socket() { Close(); }
|
||||
|
||||
public:
|
||||
|
||||
// ISocket overrides
|
||||
|
||||
virtual bool Close() override;
|
||||
virtual bool Bind(const IPAddress &addr) override;
|
||||
virtual bool Connect(const IPAddress& addr) override;
|
||||
inline virtual bool Listen() override { return listen(m_socket, SOMAXCONN) == 0; }
|
||||
virtual bool WaitForPendingConnection(bool& hasPendingConnection, std::chrono::milliseconds t) override;
|
||||
virtual bool HasPendingData(uint32_t& pendingDataSize) override;
|
||||
virtual std::unique_ptr<Socket> Accept() override;
|
||||
virtual bool SendTo(const uint8_t* data, int32_t count, int32_t& sent, const IPAddress& addrDest) override;
|
||||
virtual bool Send(const uint8_t* data, int32_t count, int32_t& sent) override;
|
||||
virtual bool RecvFrom(uint8_t* data, int32_t size, int32_t& read, IPAddress& srcAddr, SocketReceiveFlags flags = SocketReceiveFlags::None) override;
|
||||
virtual bool Recv(uint8_t* data, int32_t size, int32_t& read, SocketReceiveFlags flags = SocketReceiveFlags::None) override;
|
||||
virtual bool Wait(SocketWaitConditions cond, std::chrono::milliseconds t) override;
|
||||
virtual SocketConnectionState GetConnectionState() override;
|
||||
virtual void GetAddress(IPAddress& outAddr) override;
|
||||
virtual bool GetPeerAddress(IPAddress& outAddr) override;
|
||||
virtual bool SetNonBlocking(bool isNonBlocking = true) override;
|
||||
|
||||
virtual bool JoinMulticastGroup(const IPAddress& addrStr) override;
|
||||
virtual bool LeaveMulticastGroup(const IPAddress& addrStr) override;
|
||||
inline virtual bool SetMulticastLoopback(bool loopback) override { return (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&loopback, sizeof(loopback)) == 0); }
|
||||
inline virtual bool SetMulticastTtl(uint8_t timeToLive) override { return (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&timeToLive, sizeof(timeToLive)) == 0); }
|
||||
inline virtual bool SetReuseAddr(bool allowReuse = true) override
|
||||
{
|
||||
int param = allowReuse ? 1 : 0;
|
||||
return setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)¶m, sizeof(param)) == 0;
|
||||
}
|
||||
|
||||
virtual bool SetLinger(bool shouldLinger = true, int32_t t = 0) override;
|
||||
virtual bool SetSendBufferSize(int32_t size, int32_t& newSize) override;
|
||||
virtual bool SetReceiveBufferSize(int32_t size, int32_t& newSize) override;
|
||||
virtual uint32_t GetPort() override;
|
||||
|
||||
SOCKET GetNativeSocket()
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
virtual SocketReturn HasState(SocketParam state, std::chrono::milliseconds t = std::chrono::milliseconds(0));
|
||||
virtual SocketErrors TranslateErrorCode(int32_t code);
|
||||
virtual int TranslateFlags(SocketReceiveFlags flags);
|
||||
|
||||
inline void UpdateActivity()
|
||||
{
|
||||
m_lastActivityTime = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
}
|
||||
|
||||
private:
|
||||
SOCKET m_socket = INVALID_SOCKET;
|
||||
|
||||
long long m_lastActivityTime = 0;
|
||||
};
|
||||
}
|
||||
@ -1,79 +1,33 @@
|
||||
#ifndef TCP_CLIENT_HPP
|
||||
#define TCP_CLIENT_HPP
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "NetworkMessage.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
struct TcpClient
|
||||
#include "Socket.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
TcpClient(const SOCKET &socket);
|
||||
TcpClient(const std::string &ip);
|
||||
TcpClient(const std::string &ip, uint16 port = default_client_port);
|
||||
~TcpClient();
|
||||
class TcpConnectionHandler;
|
||||
}
|
||||
|
||||
void Shutdown();
|
||||
namespace std::net
|
||||
{
|
||||
class TcpClient
|
||||
{
|
||||
friend class std::net::TcpConnectionHandler;
|
||||
|
||||
const std::string &GetIP();
|
||||
void SetIP(const std::string &ip);
|
||||
public:
|
||||
TcpClient(Socket *soc);
|
||||
TcpClient(SocketProtocol protocol = SocketProtocol::IPv4);
|
||||
|
||||
uint16 GetPort();
|
||||
void SetPort(uint16 port);
|
||||
bool Connect(const IPAddress& addrStr);
|
||||
bool Close() const;
|
||||
bool HasPendingData(uint32_t& pendingDataSize) const;
|
||||
bool Send(const uint8_t* data, int32_t count, int32_t& sent) const;
|
||||
bool Recv(uint8_t* data, int32_t size, int32_t& read, SocketReceiveFlags flags = SocketReceiveFlags::None) const;
|
||||
bool Wait(SocketWaitConditions cond, std::chrono::milliseconds t) const;
|
||||
SocketConnectionState GetConnectionState() const;
|
||||
void GetAddress(IPAddress& outAddr) const;
|
||||
int32_t GetPort() const;
|
||||
|
||||
uint16 GetID();
|
||||
void SetID(uint16 id);
|
||||
|
||||
bool Connect();
|
||||
|
||||
bool DataAvailable(int32 &size);
|
||||
|
||||
//this method will receive the messages automaticaly and use the callback methods
|
||||
void ReceiveMessages();
|
||||
|
||||
//this is a more manual method with no callbacks
|
||||
const NetworkMessage &ReceiveMessage();
|
||||
|
||||
std::future<bool> SendMessage(const NetworkMessage &message);
|
||||
bool SendBytes(const std::vector<byte> &bytes);
|
||||
bool SendBytes(byte *bytes, uint32 lenght);
|
||||
|
||||
void SetOnDisconnectCallback(std::function<void(uint16)> func);
|
||||
void SetOnConnectCallback(std::function<void(uint16)> func);
|
||||
void SetOnMessageCallback(std::function<void(uint16, byte, byte, void*)> func);
|
||||
|
||||
static const TcpClient &DefaultTcpClient();
|
||||
|
||||
private:
|
||||
TcpClient();
|
||||
|
||||
const NetworkBuffer &receive_data_array();
|
||||
static void receive_data(TcpClient *client);
|
||||
static bool send_network_message(const NetworkMessage &message, TcpClient *client);
|
||||
static void close_connection(TcpClient *client);
|
||||
|
||||
bool initialize(const std::string &ip, uint16 port = default_client_port);
|
||||
|
||||
uint16 id = -2;
|
||||
std::string ip;
|
||||
uint16 port = 0;
|
||||
bool initialized = false;
|
||||
bool receive = false;
|
||||
|
||||
std::function<void(uint16)> OnDisconnect;
|
||||
std::function<void(uint16)> OnConnect;
|
||||
std::function<void(uint16, byte, byte, void*)> OnMessage;
|
||||
|
||||
SOCKET tcp_socket = INVALID_SOCKET;
|
||||
struct addrinfo *result = nullptr;
|
||||
struct addrinfo hints;
|
||||
};
|
||||
|
||||
#endif
|
||||
private:
|
||||
std::unique_ptr<Socket> m_socket;
|
||||
};
|
||||
}
|
||||
32
include/TcpListener.hpp
Normal file
32
include/TcpListener.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include <queue>
|
||||
|
||||
#include "Socket.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class TcpConnectionHandler;
|
||||
}
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class TcpClient;
|
||||
|
||||
class TcpListener
|
||||
{
|
||||
friend class std::net::TcpConnectionHandler;
|
||||
|
||||
public:
|
||||
TcpListener(uint16_t port, std::chrono::milliseconds inSleepTime = std::chrono::milliseconds(1));
|
||||
TcpListener(Socket *InSocket, std::chrono::milliseconds inSleepTime = std::chrono::milliseconds(1));
|
||||
|
||||
TcpClient *AcceptClient();
|
||||
|
||||
private:
|
||||
std::chrono::milliseconds m_sleepTime;
|
||||
std::unique_ptr<Socket> m_socket;
|
||||
uint16_t m_port = 0;
|
||||
};
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
#ifndef TCP_SERVER_HPP
|
||||
#define TCP_SERVER_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "TcpClient.hpp"
|
||||
#include "Handshake.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct TcpServer
|
||||
{
|
||||
TcpServer();
|
||||
TcpServer(uint16 port = default_server_port);
|
||||
~TcpServer();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
bool StartServer(bool accept_connections); // if accept_connections is false the user must call the funcion AcceptConnections()
|
||||
void AcceptConnections();
|
||||
|
||||
bool SendMessage(const NetworkMessage &message);
|
||||
|
||||
void RejectConnection(TcpClient &client);
|
||||
void AcceptConnection(uint16 client);
|
||||
|
||||
void CloseSocket(TcpClient &client);
|
||||
void CloseSocket(uint16 id);
|
||||
|
||||
uint16 GetMaxConnections();
|
||||
void SetMaxConnections(uint16 value);
|
||||
|
||||
const TcpClient &GetClientByID(uint16 id);
|
||||
|
||||
std::vector<std::function<void(const NetworkMessage &message)>> OnMessageFunctions; // this is going to be used for plugins
|
||||
|
||||
private:
|
||||
static void process_client_messages(TcpServer *server, TcpClient &client);
|
||||
static void accept_connections(TcpServer *server);
|
||||
|
||||
void add_to_clients_list(TcpClient &client);
|
||||
|
||||
uint16 allocate_id();
|
||||
|
||||
void shutdown_internal();
|
||||
|
||||
bool initialize(uint16 port = default_server_port);
|
||||
|
||||
bool initialized = false;
|
||||
bool running = false;
|
||||
|
||||
uint16 max_connections = 0;
|
||||
|
||||
std::vector<TcpClient> clients;
|
||||
|
||||
SOCKET server_tcp_socket = INVALID_SOCKET;
|
||||
struct addrinfo *result = nullptr;
|
||||
struct addrinfo hints;
|
||||
};
|
||||
|
||||
#endif
|
||||
112
include/TcpSocketBuilder.hpp
Normal file
112
include/TcpSocketBuilder.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include "Enums.hpp"
|
||||
#include "IPAddress.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Socket;
|
||||
class TcpClient;
|
||||
class TcpListener;
|
||||
|
||||
class TcpSocketBuilder
|
||||
{
|
||||
public:
|
||||
inline TcpSocketBuilder()
|
||||
: m_blocking(false)
|
||||
, m_bound(false)
|
||||
, m_boundAddr(IPAddress::Any, 0)
|
||||
, m_linger(false)
|
||||
, m_lingerTimeout(0)
|
||||
, m_listen(false)
|
||||
, m_receiveBufferSize(0)
|
||||
, m_reusable(false)
|
||||
, m_sendBufferSize(0)
|
||||
, m_socketProtocol(SocketProtocol::IPv4)
|
||||
{
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder AsBlocking()
|
||||
{
|
||||
m_blocking = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder AsNonBlocking()
|
||||
{
|
||||
m_blocking = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder AsReusable()
|
||||
{
|
||||
m_reusable = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder Bind(const IPAddress &addr)
|
||||
{
|
||||
m_boundAddr = addr;
|
||||
m_bound = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder Lingering(int32_t Timeout)
|
||||
{
|
||||
m_linger = true;
|
||||
m_lingerTimeout = Timeout;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder Listening()
|
||||
{
|
||||
m_listen = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder WithReceiveBufferSize(int32_t SizeInBytes)
|
||||
{
|
||||
m_receiveBufferSize = SizeInBytes;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder WithSendBufferSize(int32_t SizeInBytes)
|
||||
{
|
||||
m_sendBufferSize = SizeInBytes;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline TcpSocketBuilder Protocol(SocketProtocol prot)
|
||||
{
|
||||
m_socketProtocol = prot;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Socket> Build() const;
|
||||
std::unique_ptr<TcpClient> BuildClient() const;
|
||||
std::unique_ptr<TcpListener> BuildListener() const;
|
||||
|
||||
private:
|
||||
bool m_blocking;
|
||||
bool m_bound;
|
||||
IPAddress m_boundAddr;
|
||||
bool m_linger;
|
||||
int32_t m_lingerTimeout;
|
||||
bool m_listen;
|
||||
int32_t m_receiveBufferSize;
|
||||
bool m_reusable;
|
||||
int32_t m_sendBufferSize;
|
||||
|
||||
SocketProtocol m_socketProtocol;
|
||||
};
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
#ifndef UDP_CLIENT_HPP
|
||||
#define UDP_CLIENT_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "NetworkMessage.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
|
||||
struct UdpClient
|
||||
{
|
||||
UdpClient(const SOCKET &socket);
|
||||
UdpClient(const std::string &ip);
|
||||
UdpClient(const std::string &ip, uint16 = default_client_port);
|
||||
~UdpClient();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
const std::string &GetIP();
|
||||
void SetIP(const std::string &ip);
|
||||
|
||||
uint16 GetPort();
|
||||
void SetPort(uint16 port);
|
||||
|
||||
uint16 GetID();
|
||||
void SetID(uint16 id);
|
||||
|
||||
void ReceiveMessages();
|
||||
|
||||
const NetworkMessage &ReceiveMessage();
|
||||
|
||||
std::future<bool> SendMessage(const NetworkMessage &message);
|
||||
bool SendBytes(const std::vector<byte> &bytes);
|
||||
bool SendBytes(byte *bytes, uint32 lenght);
|
||||
|
||||
private:
|
||||
const NetworkBuffer &receive_data_array();
|
||||
static void receive_data(UdpClient *client);
|
||||
bool initialize(const std::string &ip, uint16 port = default_client_port);
|
||||
|
||||
static bool send_network_message(const NetworkMessage &message, UdpClient *client);
|
||||
|
||||
uint16 id = -2;
|
||||
|
||||
std::string ip;
|
||||
uint16 port = 0;
|
||||
bool initialized = false;
|
||||
bool receive = false;
|
||||
|
||||
std::function<void(uint16)> OnDisconnect;
|
||||
std::function<void(uint16)> OnConnect;
|
||||
std::function<void(uint16, byte, byte, void*)> OnMessage;
|
||||
|
||||
SOCKET udp_socket = INVALID_SOCKET;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,34 +0,0 @@
|
||||
#ifndef UDP_SERVER_HPP
|
||||
#define UDP_SERVER_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "UdpClient.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct UdpServer
|
||||
{
|
||||
private:
|
||||
bool initialize(uint16 port = default_server_port);
|
||||
|
||||
uint16 allocate_id();
|
||||
|
||||
void shutdown_internal();
|
||||
|
||||
bool initialized = false;
|
||||
bool running = false;
|
||||
|
||||
uint16 max_connections = 0;
|
||||
|
||||
std::vector<UdpClient> clients;
|
||||
|
||||
SOCKET server_udp_socket = INVALID_SOCKET;
|
||||
struct sockaddr_in server;
|
||||
};
|
||||
|
||||
#endif
|
||||
29
include/UdpSocket.hpp
Normal file
29
include/UdpSocket.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "Socket.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class UdpSocket
|
||||
{
|
||||
public:
|
||||
UdpSocket(Socket *soc);
|
||||
UdpSocket(SocketProtocol protocol = SocketProtocol::IPv4);
|
||||
|
||||
bool Bind(const IPAddress &addr);
|
||||
bool SendTo(const uint8_t* data, int32_t count, int32_t& sent, const IPAddress& addrDest);
|
||||
bool RecvFrom(uint8_t* data, int32_t size, int32_t& read, IPAddress& srcAddr, SocketReceiveFlags flags = SocketReceiveFlags::None);
|
||||
bool GetPeerAddress(IPAddress& outAddr);
|
||||
bool JoinMulticastGroup(const IPAddress& addrStr);
|
||||
bool LeaveMulticastGroup(const IPAddress& addrStr);
|
||||
bool SetMulticastLoopback(bool loopback);
|
||||
bool SetMulticastTtl(uint8_t timeToLive);
|
||||
uint32_t GetPort();
|
||||
bool SetReuseAddr(bool allowReuse = true);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Socket> m_socket;
|
||||
};
|
||||
}
|
||||
152
include/UdpSocketBuilder.hpp
Normal file
152
include/UdpSocketBuilder.hpp
Normal file
@ -0,0 +1,152 @@
|
||||
#pragma once
|
||||
|
||||
#include "UdpSocket.hpp"
|
||||
#include "IPAddress.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class UdpSocketBuilder
|
||||
{
|
||||
public:
|
||||
UdpSocketBuilder()
|
||||
: m_blocking(false)
|
||||
, m_bound(false)
|
||||
, m_boundEndpoint(IPAddress::Any, 0)
|
||||
, m_multicastLoopback(false)
|
||||
, m_multicastTtl(1)
|
||||
, m_receiveBufferSize(0)
|
||||
, m_reusable(false)
|
||||
, m_sendBufferSize(0)
|
||||
{ }
|
||||
|
||||
public:
|
||||
UdpSocketBuilder AsBlocking()
|
||||
{
|
||||
m_blocking = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder AsNonBlocking()
|
||||
{
|
||||
m_blocking = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder AsReusable()
|
||||
{
|
||||
m_reusable = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder BoundToAddress(const IPAddress& addr)
|
||||
{
|
||||
m_boundEndpoint = IPAddress(addr);
|
||||
m_bound = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder BoundToPort(uint16_t port)
|
||||
{
|
||||
m_boundEndpoint = IPAddress(m_boundEndpoint.ToInteger(), port);
|
||||
m_bound = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder JoinedToGroup(const IPAddress& group_addr)
|
||||
{
|
||||
m_joinedGroups.emplace_back(group_addr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder WithMulticastLoopback()
|
||||
{
|
||||
m_multicastLoopback = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder WithMulticastTtl(uint8_t time_to_live)
|
||||
{
|
||||
m_multicastTtl = time_to_live;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder WithReceiveBufferSize(uint32_t size)
|
||||
{
|
||||
m_receiveBufferSize = size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
UdpSocketBuilder WithSendBufferSize(uint32_t size)
|
||||
{
|
||||
m_sendBufferSize = size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<UdpSocket> Build() const
|
||||
{
|
||||
std::unique_ptr<Socket> soc = std::make_unique<Socket>(SocketType::Datagram);
|
||||
|
||||
if (soc)
|
||||
{
|
||||
bool Error =
|
||||
!soc->SetNonBlocking(!m_blocking) ||
|
||||
!soc->SetReuseAddr(m_reusable);
|
||||
|
||||
if (!Error)
|
||||
Error = m_bound && !soc->Bind(m_boundEndpoint);
|
||||
if (!Error)
|
||||
Error = !soc->SetMulticastLoopback(m_multicastLoopback) || !soc->SetMulticastTtl(m_multicastTtl);
|
||||
|
||||
if (!Error)
|
||||
{
|
||||
for (const auto& Group : m_joinedGroups)
|
||||
{
|
||||
if (!soc->JoinMulticastGroup(IPAddress(Group, 0)))
|
||||
{
|
||||
Error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Error)
|
||||
{
|
||||
int32_t out_new_size;
|
||||
if (m_receiveBufferSize > 0)
|
||||
soc->SetReceiveBufferSize(m_receiveBufferSize, out_new_size);
|
||||
if (m_sendBufferSize > 0)
|
||||
soc->SetSendBufferSize(m_sendBufferSize, out_new_size);
|
||||
}
|
||||
|
||||
if (Error)
|
||||
throw inl::RuntimeException("Couldnt create socket"); // make parameter a string depending on the error
|
||||
return std::make_unique<UdpSocket>();
|
||||
}
|
||||
return std::unique_ptr<UdpSocket>(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_blocking;
|
||||
bool m_bound;
|
||||
IPAddress m_boundEndpoint;
|
||||
std::vector<IPAddress> m_joinedGroups;
|
||||
bool m_multicastLoopback;
|
||||
uint8_t m_multicastTtl;
|
||||
uint32_t m_receiveBufferSize;
|
||||
bool m_reusable;
|
||||
uint32_t m_sendBufferSize;
|
||||
};
|
||||
}
|
||||
78
include/Uri.hpp
Normal file
78
include/Uri.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
class Authority
|
||||
{
|
||||
public:
|
||||
Authority(const std::string& user, const std::string& host, uint16_t port);
|
||||
Authority();
|
||||
|
||||
const std::string& GetUser() const
|
||||
{
|
||||
return m_user;
|
||||
}
|
||||
|
||||
const std::string& GetHost() const
|
||||
{
|
||||
return m_host;
|
||||
}
|
||||
|
||||
uint16_t GetPort() const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
void SetUser(const std::string& user);
|
||||
void SetHost(const std::string& host);
|
||||
void SetPort(uint16_t port);
|
||||
private:
|
||||
std::string m_user;
|
||||
std::string m_host;
|
||||
uint16_t m_port;
|
||||
};
|
||||
|
||||
class Uri {
|
||||
public:
|
||||
Uri(const char* value);
|
||||
Uri(const std::string& value);
|
||||
Uri();
|
||||
|
||||
const std::string& GetScheme() const
|
||||
{
|
||||
return m_scheme;
|
||||
}
|
||||
|
||||
const Authority& GetAuthority() const
|
||||
{
|
||||
return m_authority;
|
||||
}
|
||||
|
||||
const std::string& GetPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
const std::string& GetHost() const
|
||||
{
|
||||
return m_authority.GetHost();
|
||||
}
|
||||
|
||||
uint16_t GetPort() const
|
||||
{
|
||||
return m_authority.GetPort();
|
||||
}
|
||||
|
||||
void SetScheme(const std::string& scheme);
|
||||
void SetAuthority(const Authority& authority);
|
||||
void SetPath(const std::string& path);
|
||||
private:
|
||||
std::string m_scheme;
|
||||
Authority m_authority;
|
||||
std::string m_path;
|
||||
};
|
||||
}
|
||||
37
include/Util.hpp
Normal file
37
include/Util.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include "Net.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
inline static std::vector<std::string> Split(const std::string &str, const std::string &delimiter)
|
||||
{
|
||||
std::vector<std::string> splited;
|
||||
if (str.empty() && delimiter.empty())
|
||||
return std::vector<std::string>();
|
||||
std::string::size_type lastPos = str.find_first_not_of(delimiter, 0);
|
||||
std::string::size_type pos = str.find_first_of(delimiter, lastPos);
|
||||
|
||||
while (std::string::npos != pos || std::string::npos != lastPos)
|
||||
{
|
||||
splited.push_back(str.substr(lastPos, pos - lastPos));
|
||||
lastPos = str.find_first_not_of(delimiter, pos);
|
||||
pos = str.find_first_of(delimiter, lastPos);
|
||||
}
|
||||
return splited;
|
||||
}
|
||||
|
||||
sockaddr_in CreateAddress(uint32_t address, uint16_t port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_addr.s_addr = htonl(address);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
#ifndef UTILITY_HPP
|
||||
#define UTILITY_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
struct Utility
|
||||
{
|
||||
static void Delete(void *pointer);
|
||||
static void DeleteArray(void *pointer);
|
||||
|
||||
struct BitConverter
|
||||
{
|
||||
static const std::vector<byte> &ToBytes(uint8 number);
|
||||
static uint8 ToUint8(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(uint16 number);
|
||||
static uint16 ToUint16(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(uint32 number);
|
||||
static uint32 ToUint32(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(uint64 number);
|
||||
static uint64 ToUint64(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(int8 number);
|
||||
static int8 ToInt8(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(int16 number);
|
||||
static int16 ToInt16(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(int32 number);
|
||||
static int32 ToInt32(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
|
||||
static const std::vector<byte> &ToBytes(int64 number);
|
||||
static int64 ToInt64(const std::vector<byte> &bytes, uint16 start_index = 0);
|
||||
};
|
||||
|
||||
struct StringConverter
|
||||
{
|
||||
static const std::string &ToString(bool value);
|
||||
static const std::string &ToString(uint8 value);
|
||||
static const std::string &ToString(uint16 value);
|
||||
static const std::string &ToString(uint32 value);
|
||||
static const std::string &ToString(uint64 value);
|
||||
static const std::string &ToString(int8 value);
|
||||
static const std::string &ToString(int16 value);
|
||||
static const std::string &ToString(int32 value);
|
||||
static const std::string &ToString(int64 value);
|
||||
static const std::string &ToString(const std::vector<byte> &bytes);
|
||||
|
||||
static uint8 ToUint8(const std::string &str);
|
||||
static uint16 ToUint16(const std::string &str);
|
||||
static uint32 ToUint32(const std::string &str);
|
||||
static uint64 ToUint64(const std::string &str);
|
||||
static int8 ToInt8(const std::string &str);
|
||||
static int16 ToInt16(const std::string &str);
|
||||
static int32 ToInt32(const std::string &str);
|
||||
static int64 ToInt64(const std::string &str);
|
||||
|
||||
static const std::vector<byte> &ToBytes(const std::string &str);
|
||||
|
||||
static const std::string &ToString(const std::vector<byte> &bytes, uint16 start_index = 0, uint16 lenght = 0);
|
||||
|
||||
static const std::string &Trim(std::string &str, char ch);
|
||||
static std::vector<std::string> Split(const std::string &str, const std::string &delimiter);
|
||||
};
|
||||
|
||||
struct IPUtil
|
||||
{
|
||||
static bool ValidIPV4(const std::string &ip);
|
||||
};
|
||||
|
||||
struct ConfigReader
|
||||
{
|
||||
void ReadConfig(const std::string &file_name);
|
||||
void ReadNodes();
|
||||
|
||||
const std::string &operator[](const std::string &key);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> nodes;
|
||||
std::string file_content;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,39 +0,0 @@
|
||||
#ifndef VOID_NET_HPP
|
||||
#define VOID_NET_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "Defs.hpp"
|
||||
#include "Init.hpp"
|
||||
#include "TcpClient.hpp"
|
||||
#include "NetworkBuffer.hpp"
|
||||
#include "NetworkMessage.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
struct VoidNetClientAPI
|
||||
{
|
||||
static bool Connect(const std::string &ip, uint16 port = default_client_port);
|
||||
static void Disconnect();
|
||||
|
||||
static void SendMessageToServer(byte tag, byte subject, void *data);
|
||||
static void SendMessageToID(uint16 id, byte tag, byte subject, void *data);
|
||||
static void SendMessageToOthers(byte tag, byte subject, void *data);
|
||||
static void SendMessageToAll(byte tag, byte subject, void *data);
|
||||
static void SendMessageToAllAndMe(byte tag, byte subject, void *data);
|
||||
|
||||
static void SendMessage(byte distribution_mode, uint16 destination_id, byte tag, byte subject, void *data);
|
||||
|
||||
static void Receive();
|
||||
|
||||
private:
|
||||
static void receive_data();
|
||||
|
||||
static TcpClient tcp_client;
|
||||
static uint16 id;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,18 +0,0 @@
|
||||
#ifndef VOID_NET_SERVER_HPP
|
||||
#define VOID_NET_SERVER_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "TcpServer.hpp"
|
||||
|
||||
struct VoidNetServer
|
||||
{
|
||||
void StartServer(uint16 port);
|
||||
void StopServer();
|
||||
private:
|
||||
TcpServer server;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,29 +0,0 @@
|
||||
#include "Config.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
void Config::Initialize()
|
||||
{
|
||||
Configuration.ReadConfig("config.dat");
|
||||
Configuration.ReadNodes();
|
||||
}
|
||||
|
||||
inline void Config::SetUsingConsole(bool value)
|
||||
{
|
||||
using_console = value;
|
||||
}
|
||||
|
||||
inline bool Config::GetUsingConsole()
|
||||
{
|
||||
return using_console;
|
||||
}
|
||||
|
||||
inline void Config::SetLogToFile(bool value)
|
||||
{
|
||||
log_to_file = value;
|
||||
}
|
||||
|
||||
inline bool Config::GetLogToFile()
|
||||
{
|
||||
return log_to_file;
|
||||
}
|
||||
84
src/Cookies.cpp
Normal file
84
src/Cookies.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#include "Cookies.hpp"
|
||||
#include "Parse.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
ParseResult<std::string> ParseName(const char* str)
|
||||
{
|
||||
return ParseUntil(str, [](char ch)
|
||||
{
|
||||
return isspace(ch) || ch == '=';
|
||||
});
|
||||
}
|
||||
|
||||
ParseResult<std::string> ParseValue(const char* str)
|
||||
{
|
||||
return ParseUntil(str, [](char ch)
|
||||
{
|
||||
return ch == ';' || ch == '=';
|
||||
});
|
||||
}
|
||||
|
||||
ParseResult<std::string> ParseSeparator(const char* str)
|
||||
{
|
||||
if (*str)
|
||||
{
|
||||
assert(*str == ';' || *str == '=');
|
||||
return ParseWhitespace(str + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = ParseResult<std::string>{};
|
||||
result.ch = str;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Cookie ParseCookie(const char* str)
|
||||
{
|
||||
auto name = ParseName(str);
|
||||
auto ch = ParseSeparator(name.ch).ch;
|
||||
auto value = ParseValue(ch);
|
||||
ch = ParseSeparator(value.ch).ch;
|
||||
|
||||
auto cookie = Cookie();
|
||||
cookie.SetName(name.value);
|
||||
cookie.SetValue(value.value);
|
||||
while (*ch)
|
||||
{
|
||||
auto flag = ParseValue(ch);
|
||||
if (flag.value == "Path")
|
||||
{
|
||||
ch = ParseSeparator(flag.ch).ch;
|
||||
flag = ParseValue(ch);
|
||||
cookie.SetPath(flag.value);
|
||||
}
|
||||
else if (flag.value == "HttpOnly")
|
||||
cookie.SetHttpOnly(true);
|
||||
else if (flag.value == "Secure")
|
||||
cookie.SetSecure(true);
|
||||
ch = ParseSeparator(flag.ch).ch;
|
||||
}
|
||||
return cookie;
|
||||
}
|
||||
|
||||
Cookie::Cookie(const std::string& text)
|
||||
{
|
||||
*this = ParseCookie(text.c_str());
|
||||
}
|
||||
|
||||
const Cookie Cookies::operator[](const std::string & name) const
|
||||
{
|
||||
auto i = m_cookie.find(name);
|
||||
return (i == m_cookie.end()) ? Cookie() : i->second;
|
||||
}
|
||||
|
||||
void Cookies::SetCookie(const Cookie& cookie)
|
||||
{
|
||||
m_cookie[cookie.GetName()] = cookie;
|
||||
}
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
#include "Handshake.hpp"
|
||||
#include "Utility.hpp"
|
||||
|
||||
Handshake::Handshake()
|
||||
{
|
||||
id = -2;
|
||||
}
|
||||
|
||||
Handshake::Handshake(uint16 id, byte con_code, byte distribution_mode)
|
||||
{
|
||||
this->id = id;
|
||||
this->con_code = con_code;
|
||||
this->distribution_mode = distribution_mode;
|
||||
}
|
||||
|
||||
Handshake::~Handshake()
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<byte>& Handshake::EncodeHandshake(const Handshake & handshake)
|
||||
{
|
||||
std::vector<byte> handshake_bytes;
|
||||
|
||||
std::vector<byte> id = Utility::BitConverter::ToBytes(handshake.id);
|
||||
std::vector<byte> con_mode = Utility::BitConverter::ToBytes(handshake.con_code);
|
||||
std::vector<byte> type = Utility::BitConverter::ToBytes(static_cast<uint8>(1));
|
||||
|
||||
handshake_bytes.insert(handshake_bytes.begin(), type.begin(), type.end());
|
||||
handshake_bytes.insert(handshake_bytes.begin(), id.begin(), id.end());
|
||||
handshake_bytes.insert(handshake_bytes.begin(), con_mode.begin(), con_mode.end());
|
||||
|
||||
return handshake_bytes;
|
||||
}
|
||||
|
||||
Handshake & Handshake::DecodeHandshake(const std::vector<byte>& bytes)
|
||||
{
|
||||
Handshake handshake;
|
||||
|
||||
handshake.id = Utility::BitConverter::ToUint16(bytes, 1);
|
||||
handshake.con_code = Utility::BitConverter::ToUint8(bytes, 3);
|
||||
|
||||
return handshake;
|
||||
}
|
||||
|
||||
const NetworkMessage & Handshake::HandshakeToNetworkMessage(const Handshake & handshake)
|
||||
{
|
||||
NetworkMessage message;
|
||||
message.sender = handshake.id;
|
||||
message.tag = handshake.con_code;
|
||||
message.subject = 1;
|
||||
return message;
|
||||
}
|
||||
|
||||
const Handshake & Handshake::NetworkMessageToHandshake(const NetworkMessage & message)
|
||||
{
|
||||
Handshake handshake;
|
||||
handshake.id = message.sender;
|
||||
handshake.con_code = message.tag;
|
||||
return handshake;
|
||||
}
|
||||
22
src/Headers.cpp
Normal file
22
src/Headers.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#include "Headers.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
std::string const Headers::HOST("Host");
|
||||
std::string const Headers::CONTENT_LENGTH("Content-Length");
|
||||
std::string const Headers::ACCEPT_ENCODING("Accept-Encoding");
|
||||
std::string const Headers::CONNECTION("Connection");
|
||||
|
||||
const std::string Headers::operator[](const std::string & name) const
|
||||
{
|
||||
auto i = m_header.find(name);
|
||||
return (i == m_header.end()) ? "" : i->second;
|
||||
}
|
||||
|
||||
void Headers::AddHeader(std::string const& name, std::string const& value)
|
||||
{
|
||||
m_header.emplace(name, value);
|
||||
}
|
||||
}
|
||||
120
src/Http.cpp
Normal file
120
src/Http.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#include "Http.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include "Socket.hpp"
|
||||
#include "SecureSocket.hpp"
|
||||
|
||||
#undef DELETE
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
Response Http::Send(Request const& request)
|
||||
{
|
||||
// Send an HTTP request. Auto-fill the content-length headers.
|
||||
std::string string = Str(request);
|
||||
|
||||
uint16_t port = 0;
|
||||
std::unique_ptr<Socket> socket;
|
||||
std::unique_ptr<SecureSocket> secure_socket;
|
||||
bool secure = false;
|
||||
if (request.GetUri().GetScheme() == "https")
|
||||
{
|
||||
secure_socket.reset(new SecureSocket());
|
||||
port = 443;
|
||||
secure = true;
|
||||
}
|
||||
else if (request.GetUri().GetScheme() == "http")
|
||||
{
|
||||
socket.reset(new Socket(SocketType::Streaming));
|
||||
port = 80;
|
||||
}
|
||||
else
|
||||
assert(!"unknown http scheme");
|
||||
|
||||
if (request.GetUri().GetPort())
|
||||
port = request.GetUri().GetPort();
|
||||
|
||||
secure ? secure_socket->Connect(IPAddress(request.GetUri().GetHost(), port)) : socket->Connect(IPAddress(request.GetUri().GetHost(), port));
|
||||
int32_t sent;
|
||||
secure ? secure_socket->Recv((uint8_t*)string.c_str(), string.size(), sent) : socket->Send((uint8_t*)string.c_str(), string.size(), sent);
|
||||
|
||||
std::vector<char> buffer(16384); // 16 KiB
|
||||
std::stringstream ss;
|
||||
|
||||
int32_t read;
|
||||
do
|
||||
{
|
||||
secure ? secure_socket->Recv((uint8_t*)&buffer[0], buffer.size(), read) : socket->Recv((uint8_t*)&buffer[0], buffer.size(), read);
|
||||
ss.write(&buffer[0], read);
|
||||
}
|
||||
while (read > 0);
|
||||
secure ? secure_socket->Close() : socket->Close();
|
||||
|
||||
return Response(ss.str());
|
||||
}
|
||||
|
||||
Response Http::Get(std::string const& path, std::string const& data)
|
||||
{
|
||||
// Shortcut for simple GET requests
|
||||
Request request;
|
||||
request.SetMethod(Method::GET);
|
||||
request.SetUri(Uri(path));
|
||||
request.SetData(data);
|
||||
return Send(request);
|
||||
}
|
||||
|
||||
Response Http::Post(std::string const& path, std::string const& data)
|
||||
{
|
||||
// Shortcut for simple POST requests
|
||||
Request request;
|
||||
request.SetMethod(Method::POST);
|
||||
request.SetUri(Uri(path));
|
||||
request.SetData(data);
|
||||
return Send(request);
|
||||
}
|
||||
|
||||
static std::string str_impl(Method method) {
|
||||
switch (method)
|
||||
{
|
||||
case Method::GET:
|
||||
return "GET";
|
||||
case Method::HEAD:
|
||||
return "HEAD";
|
||||
case Method::POST:
|
||||
return "POST";
|
||||
case Method::PUT:
|
||||
return "PUT";
|
||||
case Method::DELETE:
|
||||
return "DELETE";
|
||||
case Method::TRACE:
|
||||
return "TRACE";
|
||||
case Method::CONNECT:
|
||||
return "CONNECT";
|
||||
default:
|
||||
assert(!"unknown request method");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Http::Str(Request const& request)
|
||||
{
|
||||
// Serialize a request to a string
|
||||
std::stringstream ss;
|
||||
auto path = request.GetPath().empty() ? "/" : request.GetPath();
|
||||
ss << str_impl(request.GetMethod()) << ' ' << path << " HTTP/1.1\n";
|
||||
ss << Headers::HOST << ": " << request.GetUri().GetHost() << "\n";
|
||||
ss << Headers::CONTENT_LENGTH << ": " << request.GetData().size() << "\n";
|
||||
ss << Headers::CONNECTION << ": close\n";
|
||||
ss << Headers::ACCEPT_ENCODING << ": identity\n";
|
||||
for (auto header : request.GetHeaders())
|
||||
ss << header.first << ": " << header.second << "\n";
|
||||
ss << "\n";
|
||||
ss << request.GetData();
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
62
src/IPAddress.cpp
Normal file
62
src/IPAddress.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "IPAddress.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
const IPAddress IPAddress::None;
|
||||
const IPAddress IPAddress::Any(0, 0, 0, 0);
|
||||
const IPAddress IPAddress::LocalHost(127, 0, 0, 1);
|
||||
const IPAddress IPAddress::Broadcast(255, 255, 255, 255);
|
||||
|
||||
std::string IPAddress::ToString() const
|
||||
{
|
||||
in_addr address;
|
||||
address.s_addr = m_address;
|
||||
|
||||
return inet_ntoa(address);
|
||||
}
|
||||
|
||||
void IPAddress::Resolve(const std::string& address)
|
||||
{
|
||||
m_address = 0;
|
||||
m_valid = false;
|
||||
|
||||
if (address == "255.255.255.255")
|
||||
{
|
||||
// The broadcast address needs to be handled explicitly,
|
||||
// because it is also the value returned by inet_addr on error
|
||||
m_address = INADDR_BROADCAST;
|
||||
m_valid = true;
|
||||
}
|
||||
else if (address == "0.0.0.0")
|
||||
{
|
||||
m_address = INADDR_ANY;
|
||||
m_valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ip = inet_addr(address.c_str());
|
||||
if (ip != INADDR_NONE)
|
||||
{
|
||||
m_address = ip;
|
||||
m_valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
addrinfo hints;
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
addrinfo* result = NULL;
|
||||
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo(result);
|
||||
m_address = ip;
|
||||
m_valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/Init.cpp
23
src/Init.cpp
@ -1,23 +0,0 @@
|
||||
#include "Init.hpp"
|
||||
#include "Config.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
bool Initialization::Initialize()
|
||||
{
|
||||
uint16 code = WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
if (code != 0)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << code << std::endl; // display some more information too
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const WSADATA &Initialization::GetData()
|
||||
{
|
||||
return wsa_data;
|
||||
}
|
||||
#endif
|
||||
@ -1,9 +0,0 @@
|
||||
#include "NetworkBuffer.hpp"
|
||||
|
||||
NetworkBuffer::NetworkBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkBuffer::~NetworkBuffer()
|
||||
{
|
||||
}
|
||||
@ -1,110 +0,0 @@
|
||||
#include "NetworkMessage.hpp"
|
||||
#include "Utility.hpp"
|
||||
#include "Serializer.hpp"
|
||||
#include "Handshake.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
NetworkMessage::NetworkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkMessage::NetworkMessage(uint16 sender, byte distribution_mode, uint16 destination_id, byte tag, byte subject) :
|
||||
sender(sender), distribution_mode(distribution_mode), destination_id(destination_id), tag(tag), subject(subject)
|
||||
{
|
||||
}
|
||||
|
||||
NetworkMessage::NetworkMessage(const NetworkBuffer &buffer)
|
||||
{
|
||||
*this = DecodeMessage(buffer);
|
||||
}
|
||||
|
||||
NetworkMessage::~NetworkMessage()
|
||||
{
|
||||
}
|
||||
|
||||
const NetworkBuffer &NetworkMessage::EncodeMessage(const NetworkMessage &message)
|
||||
{
|
||||
if (message.valid)
|
||||
{
|
||||
NetworkBuffer net_buffer;
|
||||
|
||||
if (!IS_HANDSHAKE(message))
|
||||
{
|
||||
std::vector<byte> sender = Utility::BitConverter::ToBytes(message.sender);
|
||||
std::vector<byte> distribution_mode = Utility::BitConverter::ToBytes(message.distribution_mode);
|
||||
std::vector<byte> destination_id = Utility::BitConverter::ToBytes(message.destination_id);
|
||||
std::vector<byte> tag = Utility::BitConverter::ToBytes(message.tag);
|
||||
std::vector<byte> subject = Utility::BitConverter::ToBytes(message.subject);
|
||||
std::vector<byte> data;
|
||||
if (message.data != nullptr)
|
||||
data = Serializer::to_bytes(message.data);
|
||||
std::vector<byte> type = Utility::BitConverter::ToBytes(0);
|
||||
|
||||
net_buffer.body.insert(net_buffer.body.begin(), type.begin(), type.end());
|
||||
net_buffer.body.insert(net_buffer.body.begin(), sender.begin(), sender.end());
|
||||
net_buffer.body.insert(net_buffer.body.begin(), distribution_mode.begin(), distribution_mode.end());
|
||||
net_buffer.body.insert(net_buffer.body.begin(), destination_id.begin(), destination_id.end());
|
||||
net_buffer.body.insert(net_buffer.body.begin(), tag.begin(), tag.end());
|
||||
net_buffer.body.insert(net_buffer.body.begin(), subject.begin(), subject.end());
|
||||
if (message.data != nullptr && data.size() > 0)
|
||||
net_buffer.body.insert(net_buffer.body.begin(), data.begin(), data.end());
|
||||
net_buffer.header = Utility::BitConverter::ToBytes(sender.size() + distribution_mode.size() + destination_id.size() +
|
||||
tag.size() + subject.size() + data.size());
|
||||
net_buffer.valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<byte> handshake_bytes = Handshake::EncodeHandshake(Handshake::NetworkMessageToHandshake(message));
|
||||
std::vector<byte> type = Utility::BitConverter::ToBytes(static_cast<uint8>(1));
|
||||
handshake_bytes.insert(handshake_bytes.begin(), type.begin(), type.end());
|
||||
net_buffer.header = Utility::BitConverter::ToBytes(handshake_bytes.size());
|
||||
net_buffer.body = handshake_bytes;
|
||||
}
|
||||
return net_buffer;
|
||||
}
|
||||
return NetworkBuffer();
|
||||
}
|
||||
|
||||
const NetworkMessage &NetworkMessage::DecodeMessage(const NetworkBuffer &buffer)
|
||||
{
|
||||
if (buffer.valid)
|
||||
{
|
||||
byte type = buffer.body[0];
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
NetworkMessage message;
|
||||
message.sender = Utility::BitConverter::ToUint16(buffer.body, 1);
|
||||
message.distribution_mode = buffer.body[3];
|
||||
message.destination_id = Utility::BitConverter::ToUint16(buffer.body, 4);
|
||||
message.tag = buffer.body[6];
|
||||
message.subject = Utility::BitConverter::ToUint8(buffer.body, 7);
|
||||
message.valid = message.sender != -2 && message.tag != ConnectTag && message.tag != DisconnectTag;
|
||||
if (Utility::BitConverter::ToInt32(buffer.header) < 9)
|
||||
return message;
|
||||
void *object;
|
||||
object = Serializer::from_bytes(buffer.body, object);
|
||||
return message;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
NetworkMessage message;
|
||||
message.sender = Utility::BitConverter::ToUint16(buffer.body, 1);
|
||||
message.tag = Utility::BitConverter::ToUint8(buffer.body, 3);
|
||||
message.subject = 1;
|
||||
message.valid = message.sender != -2 && IS_HANDSHAKE(message);
|
||||
return message;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//type not supported
|
||||
throw std::runtime_error("NetworkMessage - Decoding version not supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return NetworkMessage();
|
||||
}
|
||||
0
src/Parse.cpp
Normal file
0
src/Parse.cpp
Normal file
31
src/Request.cpp
Normal file
31
src/Request.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#include "Request.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
const std::string Request::GetHeaderElement(const std::string& name) const
|
||||
{
|
||||
return m_headers[name];
|
||||
}
|
||||
|
||||
void Request::SetMethod(Method method)
|
||||
{
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
void Request::SetUri(const Uri& uri)
|
||||
{
|
||||
m_uri = uri;
|
||||
}
|
||||
|
||||
void Request::SetData(const std::string& data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
void Request::AddHeader(const std::string& name, const std::string& value)
|
||||
{
|
||||
m_headers.AddHeader(name, value);
|
||||
}
|
||||
}
|
||||
97
src/Response.cpp
Normal file
97
src/Response.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#include "Response.hpp"
|
||||
#include "Parse.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
static ParseResult<HttpStatus> ParseStatus(const char* str)
|
||||
{
|
||||
ParseResult<HttpStatus> result
|
||||
{
|
||||
};
|
||||
|
||||
auto code = ParseToken(str);
|
||||
|
||||
result.value = (HttpStatus)std::atoi(code.value.c_str());
|
||||
result.ch = code.ch;
|
||||
return result;
|
||||
}
|
||||
|
||||
Response ParseResponse(const char* str)
|
||||
{
|
||||
// Parse an HTTP response
|
||||
auto version = ParseToken(str);
|
||||
auto code = ParseStatus(version.ch);
|
||||
auto message = ParseUntil(code.ch, [](char ch)
|
||||
{
|
||||
return ch == '\r';
|
||||
});
|
||||
|
||||
auto response = Response();
|
||||
if (version.value != "HTTP/1.1")
|
||||
throw std::runtime_error("bad HTTP version");
|
||||
|
||||
auto ch = parseCrLf(message.ch).ch;
|
||||
while (*ch != '\0' && *ch != '\r')
|
||||
{
|
||||
auto name = ParseUntil(ch, [](char ch)
|
||||
{
|
||||
return ch == ':';
|
||||
});
|
||||
|
||||
if (*name.ch)
|
||||
name.ch++; // For ":"
|
||||
auto ws = ParseWhile(name.ch, isspace);
|
||||
auto value = ParseUntil(ws.ch, [](char ch)
|
||||
{
|
||||
return ch == '\r';
|
||||
});
|
||||
|
||||
response.SetHeader(name.value, value.value);
|
||||
if (name.value == "Set-Cookie")
|
||||
response.SetCookie(Cookie(value.value));
|
||||
ch = parseCrLf(value.ch).ch;
|
||||
}
|
||||
ch = parseCrLf(ch).ch;
|
||||
|
||||
response.SetStatus(code.value);
|
||||
response.SetData(ch);
|
||||
return response;
|
||||
}
|
||||
|
||||
Response::Response(const std::string& response)
|
||||
{
|
||||
*this = ParseResponse(response.c_str());
|
||||
}
|
||||
|
||||
const std::string Response::GetHeader(const std::string& name) const
|
||||
{
|
||||
return m_headers[name];
|
||||
}
|
||||
|
||||
const Cookie Response::GetCookie(const std::string& name) const
|
||||
{
|
||||
return m_cookies[name];
|
||||
}
|
||||
|
||||
void Response::SetStatus(HttpStatus status)
|
||||
{
|
||||
m_status = status;
|
||||
}
|
||||
|
||||
void Response::SetData(const std::string& data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
void Response::SetHeader(const std::string& name, const std::string& value)
|
||||
{
|
||||
m_headers.AddHeader(name, value);
|
||||
}
|
||||
|
||||
void Response::SetCookie(const Cookie& cookie)
|
||||
{
|
||||
m_cookies.SetCookie(cookie);
|
||||
}
|
||||
}
|
||||
163
src/SecureSocket.cpp
Normal file
163
src/SecureSocket.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
#include "SecureSocket.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace inl::net::sockets
|
||||
{
|
||||
/*SecureSocket::SecureSocket()
|
||||
: m_context(0), m_conn(0), m_eof(false)
|
||||
{
|
||||
m_socket = std::make_unique<Socket>(SocketType::Streaming);
|
||||
|
||||
// Intitialize the SSL client-side socket
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
ERR_load_BIO_strings();
|
||||
}
|
||||
|
||||
bool SecureSocket::Connect(const IPAddress & addrStr)
|
||||
{
|
||||
if (!m_context)
|
||||
{
|
||||
m_context = SSL_CTX_new(SSLv23_client_method());
|
||||
assert(m_context);
|
||||
}
|
||||
if (!m_conn)
|
||||
{
|
||||
m_conn = SSL_new(m_context);
|
||||
assert(m_conn);
|
||||
|
||||
m_in = BIO_new(BIO_s_mem());
|
||||
m_out = BIO_new(BIO_s_mem());
|
||||
SSL_set_bio(m_conn, m_in, m_out);
|
||||
SSL_set_connect_state(m_conn);
|
||||
}
|
||||
|
||||
return m_socket->Connect(addrStr);
|
||||
}
|
||||
|
||||
bool SecureSocket::Close() const
|
||||
{
|
||||
return m_socket->Close();
|
||||
}
|
||||
|
||||
bool SecureSocket::HasPendingData(uint32_t & pendingDataSize) const
|
||||
{
|
||||
return m_socket->HasPendingData(pendingDataSize);
|
||||
}
|
||||
|
||||
bool SecureSocket::Send(uint8_t* data, int32_t count, int32_t &sent, int flags)
|
||||
{
|
||||
sent = SSL_write(m_conn, data, count);
|
||||
SendFromBio(); // Write data if available
|
||||
if (sent < 0)
|
||||
{
|
||||
HandleReturn(sent);
|
||||
return true;
|
||||
}
|
||||
return sent > 0;
|
||||
}
|
||||
|
||||
bool SecureSocket::SendRaw(uint8_t * buf, size_t len, int flags)
|
||||
{
|
||||
int32_t sent;
|
||||
return m_socket->Send(buf, len, sent) && sent == len;
|
||||
|
||||
}
|
||||
|
||||
bool SecureSocket::SendFromBio(int flags)
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
size_t pending = BIO_ctrl_pending(m_out);
|
||||
if (!pending)
|
||||
return true;
|
||||
size_t bytes = BIO_read(m_out, buf, sizeof(buf));
|
||||
if (bytes > 0)
|
||||
return SendRaw(buf, bytes, flags);
|
||||
else if (bytes == -1 || bytes == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SecureSocket::RecvToBio(int flags)
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
size_t bytes = m_socket->Recv(buf, sizeof(buf), flags);
|
||||
if (bytes > 0)
|
||||
{
|
||||
size_t written = BIO_write(m_in, buf, int(bytes));
|
||||
assert(bytes == written);
|
||||
return true;
|
||||
}
|
||||
else if (bytes == 0)
|
||||
{
|
||||
// No data
|
||||
m_eof = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SecureSocket::HandleReturn(size_t ret)
|
||||
{
|
||||
int32_t err = SSL_get_error(m_conn, ret);
|
||||
if (SSL_ERROR_WANT_WRITE == err)
|
||||
SendFromBio();
|
||||
else if (SSL_ERROR_WANT_READ == err)
|
||||
RecvToBio();
|
||||
else if (SSL_ERROR_SSL == err)
|
||||
throw inl::RuntimeException();
|
||||
else
|
||||
assert(!"unexpected error");
|
||||
}
|
||||
|
||||
bool SecureSocket::Recv(uint8_t* data, int32_t count, int32_t &read, int flags)
|
||||
{
|
||||
read = SSL_read(m_conn, data, count);
|
||||
if (read < 0)
|
||||
{
|
||||
HandleReturn(read);
|
||||
if (m_eof)
|
||||
return false;
|
||||
}
|
||||
return read > 0;
|
||||
}
|
||||
|
||||
bool SecureSocket::Wait(SocketWaitConditions cond, std::chrono::milliseconds t) const
|
||||
{
|
||||
return m_socket->Wait(cond, t);
|
||||
}
|
||||
|
||||
SocketConnectionState SecureSocket::GetConnectionState() const
|
||||
{
|
||||
return m_socket->GetConnectionState();
|
||||
}
|
||||
|
||||
void SecureSocket::GetAddress(IPAddress & outAddr) const
|
||||
{
|
||||
m_socket->GetAddress(outAddr);
|
||||
}
|
||||
|
||||
int32_t SecureSocket::GetPort() const
|
||||
{
|
||||
return m_socket->GetPort();
|
||||
}
|
||||
|
||||
void SecureSocket::UseCertificateFile(std::string const & path)
|
||||
{
|
||||
if (!m_context)
|
||||
assert(!"not initialized yet");
|
||||
if (SSL_CTX_use_certificate_file(m_context, path.c_str(), SSL_FILETYPE_PEM) <= 0)
|
||||
throw inl::RuntimeException();
|
||||
}
|
||||
|
||||
void SecureSocket::UsePrivateKeyFile(std::string const & path)
|
||||
{
|
||||
if (!m_context)
|
||||
assert(!"not initialized yet");
|
||||
if (SSL_CTX_use_PrivateKey_file(m_context, path.c_str(), SSL_FILETYPE_PEM) <= 0)
|
||||
throw inl::RuntimeException();
|
||||
if (!SSL_CTX_check_private_key(m_context))
|
||||
throw inl::RuntimeException();
|
||||
}*/
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
#include "Serializer.hpp"
|
||||
|
||||
template<typename T> const std::vector<byte> &Serializer::to_bytes(const T& object)
|
||||
{
|
||||
std::vector<byte> bytes;
|
||||
|
||||
const byte *begin = reinterpret_cast<const byte*>(std::addressof(object));
|
||||
const byte *end = begin + sizeof(T);
|
||||
std::copy(begin, end, bytes.begin());
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
template<typename T> const T& Serializer::from_bytes(const std::vector<byte> &bytes, T& object)
|
||||
{
|
||||
static_assert(std::is_trivially_copyable<T>::value, "not a TriviallyCopyable type");
|
||||
std::copy(bytes.begin(), bytes.end(), reinterpret_cast<const byte*>(std::addressof(object)));
|
||||
|
||||
return object;
|
||||
}
|
||||
511
src/Socket.cpp
Normal file
511
src/Socket.cpp
Normal file
@ -0,0 +1,511 @@
|
||||
#include "Socket.hpp"
|
||||
#include "IPAddress.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
void Socket::init()
|
||||
{
|
||||
if (GetSocketType() == SocketType::Unknown)
|
||||
throw std::invalid_argument("Unknown socket type");
|
||||
|
||||
if (m_socket == INVALID_SOCKET)
|
||||
{
|
||||
m_socket = socket(AF_INET, (int)GetSocketType(), 0);
|
||||
|
||||
if (m_socket == INVALID_SOCKET)
|
||||
throw std::runtime_error("Couldnt create socket");
|
||||
}
|
||||
|
||||
if (GetSocketType() == SocketType::Streaming)
|
||||
{
|
||||
int yes = 1;
|
||||
// Disable the Nagle algorithm (i.e. removes buffering of TCP packets)
|
||||
setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes));
|
||||
|
||||
// On Mac OS X, disable the SIGPIPE signal on disconnection
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable broadcast by default for UDP sockets
|
||||
int yes = 1;
|
||||
setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes));
|
||||
}
|
||||
}
|
||||
|
||||
bool Socket::Close()
|
||||
{
|
||||
if (m_socket != INVALID_SOCKET)
|
||||
{
|
||||
int32_t error = closesocket(m_socket);
|
||||
m_socket = INVALID_SOCKET;
|
||||
return error == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Socket::Bind(const IPAddress &addr)
|
||||
{
|
||||
sockaddr_in addr_in = addr.ToCAddr();
|
||||
return bind(m_socket, (sockaddr*)&addr_in, sizeof(sockaddr_in)) == 0;
|
||||
}
|
||||
|
||||
bool Socket::Connect(const IPAddress& addr)
|
||||
{
|
||||
sockaddr_in addr_in = addr.ToCAddr();
|
||||
int32_t Return = connect(m_socket, (sockaddr*)&addr_in, sizeof(sockaddr_in));
|
||||
SocketErrors Error = TranslateErrorCode(Return);
|
||||
|
||||
// "would block" is not an error
|
||||
return ((Error == SocketErrors::SE_NO_ERROR) || (Error == SocketErrors::SE_EWOULDBLOCK));
|
||||
}
|
||||
|
||||
bool Socket::WaitForPendingConnection(bool& hasPendingConnection, std::chrono::milliseconds t)
|
||||
{
|
||||
bool hasSucceeded = false;
|
||||
hasPendingConnection = false;
|
||||
|
||||
if (HasState(SocketParam::HasError) == SocketReturn::No)
|
||||
{
|
||||
SocketReturn state = HasState(SocketParam::CanRead, t);
|
||||
|
||||
hasSucceeded = state != SocketReturn::EncounteredError;
|
||||
hasPendingConnection = state == SocketReturn::Yes;
|
||||
}
|
||||
|
||||
return hasSucceeded;
|
||||
}
|
||||
|
||||
bool Socket::HasPendingData(uint32_t& pendingDataSize)
|
||||
{
|
||||
pendingDataSize = 0;
|
||||
|
||||
if (HasState(SocketParam::CanRead) == SocketReturn::Yes)
|
||||
{
|
||||
if (ioctl(m_socket, FIONREAD,
|
||||
#if defined(_WIN32)
|
||||
(u_long*)
|
||||
#endif
|
||||
&pendingDataSize) == 0)
|
||||
return (pendingDataSize > 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<Socket> Socket::Accept()
|
||||
{
|
||||
SOCKET newSocket = accept(m_socket, nullptr, nullptr);
|
||||
|
||||
if (newSocket != INVALID_SOCKET)
|
||||
{
|
||||
return std::make_unique<Socket>(newSocket, GetSocketType());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Socket::SendTo(const uint8_t* data, int32_t count, int32_t& sent, const IPAddress& addrDest)
|
||||
{
|
||||
sockaddr_in addr = addrDest.ToCAddr();
|
||||
sent = sendto(m_socket, (const char*)data, count, 0, (sockaddr*)&addr, sizeof(sockaddr_in));
|
||||
|
||||
bool result = sent >= 0;
|
||||
if (result)
|
||||
m_lastActivityTime = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Socket::Send(const uint8_t* data, int32_t count, int32_t& sent)
|
||||
{
|
||||
sent = send(m_socket, (const char*)data, count, 0);
|
||||
|
||||
bool result = sent != SOCKET_ERROR;
|
||||
if (result)
|
||||
m_lastActivityTime = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Socket::RecvFrom(uint8_t* data, int32_t size, int32_t& read, IPAddress& srcAddr, SocketReceiveFlags flags)
|
||||
{
|
||||
socklen_t len = sizeof(sockaddr_in);
|
||||
sockaddr_in addr = srcAddr.ToCAddr();
|
||||
const int translatedFlags = TranslateFlags(flags);
|
||||
|
||||
read = recvfrom(m_socket, (char*)data, size, translatedFlags, (sockaddr*)&addr, &len);
|
||||
|
||||
if (read < 0 && TranslateErrorCode(read) == SocketErrors::SE_EWOULDBLOCK)
|
||||
read = 0;
|
||||
else if (read <= 0) // 0 means gracefully closed
|
||||
{
|
||||
read = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_lastActivityTime = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Socket::Recv(uint8_t* data, int32_t size, int32_t& read, SocketReceiveFlags flags)
|
||||
{
|
||||
const int translatedFlags = TranslateFlags(flags);
|
||||
read = recv(m_socket, (char*)data, size, translatedFlags);
|
||||
|
||||
if (read < 0 && TranslateErrorCode(read) == SocketErrors::SE_EWOULDBLOCK)
|
||||
read = 0;
|
||||
else if (read <= 0) // 0 means gracefully closed
|
||||
{
|
||||
read = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_lastActivityTime = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Socket::Wait(SocketWaitConditions cond, std::chrono::milliseconds t)
|
||||
{
|
||||
if ((cond == SocketWaitConditions::WaitForRead) || (cond == SocketWaitConditions::WaitForReadOrWrite))
|
||||
{
|
||||
if (HasState(SocketParam::CanRead, t) == SocketReturn::Yes)
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((cond == SocketWaitConditions::WaitForWrite) || (cond == SocketWaitConditions::WaitForReadOrWrite))
|
||||
{
|
||||
if (HasState(SocketParam::CanWrite, t) == SocketReturn::Yes)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SocketConnectionState Socket::GetConnectionState()
|
||||
{
|
||||
SocketConnectionState currentState = SocketConnectionState::ConnectionError;
|
||||
|
||||
if (HasState(SocketParam::HasError) == SocketReturn::No)
|
||||
{
|
||||
if (std::chrono::system_clock::now().time_since_epoch().count() - m_lastActivityTime > std::chrono::milliseconds(5).count())
|
||||
{
|
||||
SocketReturn writeState = HasState(SocketParam::CanWrite, std::chrono::milliseconds(1));
|
||||
SocketReturn readState = HasState(SocketParam::CanRead, std::chrono::milliseconds(1));
|
||||
|
||||
if (writeState == SocketReturn::Yes || readState == SocketReturn::Yes)
|
||||
{
|
||||
currentState = SocketConnectionState::Connected;
|
||||
m_lastActivityTime = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
}
|
||||
else if (writeState == SocketReturn::No && readState == SocketReturn::No)
|
||||
currentState = SocketConnectionState::NotConnected;
|
||||
}
|
||||
else
|
||||
currentState = SocketConnectionState::Connected;
|
||||
}
|
||||
|
||||
return currentState;
|
||||
}
|
||||
|
||||
void Socket::GetAddress(IPAddress& outAddr)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t Size = sizeof(sockaddr_in);
|
||||
|
||||
if (getsockname(m_socket, (sockaddr*)&addr, &Size) != 0)
|
||||
return;
|
||||
|
||||
outAddr = IPAddress(inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
}
|
||||
|
||||
bool Socket::GetPeerAddress(IPAddress& outAddr)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t size = sizeof(sockaddr_in);
|
||||
|
||||
int result = getpeername(m_socket, (sockaddr*)&addr, &size);
|
||||
if (result != 0)
|
||||
return false;
|
||||
|
||||
outAddr = IPAddress(inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
bool Socket::SetNonBlocking(bool isNonBlocking)
|
||||
{
|
||||
#if PLATFORM_HTML5 // if we have more platforms later (html5, android, ios) later we need to do some changes to networking
|
||||
throw std::exception("Can't have blocking sockets on HTML5");
|
||||
return false;
|
||||
#else
|
||||
|
||||
#if _WIN32
|
||||
return ioctl(m_socket, FIONBIO, (u_long*)&isNonBlocking) == 0;
|
||||
#else
|
||||
int flags = fcntl(m_socket, F_GETFL, 0);
|
||||
flags = isNonBlocking ? flags | O_NONBLOCK : flags ^ (flags & O_NONBLOCK);
|
||||
int err = fcntl(m_socket, F_SETFL, flags);
|
||||
return (err == 0 ? true : false);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Socket::JoinMulticastGroup(const IPAddress& addrStr)
|
||||
{
|
||||
sockaddr_in addr = addrStr.ToCAddr();
|
||||
|
||||
ip_mreq imr;
|
||||
imr.imr_interface.s_addr = INADDR_ANY;
|
||||
imr.imr_multiaddr = addr.sin_addr;
|
||||
|
||||
return (setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&imr, sizeof(imr)) == 0);
|
||||
}
|
||||
|
||||
bool Socket::LeaveMulticastGroup(const IPAddress& addrStr)
|
||||
{
|
||||
sockaddr_in addr = addrStr.ToCAddr();
|
||||
|
||||
ip_mreq imr;
|
||||
imr.imr_interface.s_addr = INADDR_ANY;
|
||||
imr.imr_multiaddr = addr.sin_addr;
|
||||
|
||||
return (setsockopt(m_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&imr, sizeof(imr)) == 0);
|
||||
}
|
||||
|
||||
bool Socket::SetLinger(bool shouldLinger, int32_t t)
|
||||
{
|
||||
linger ling;
|
||||
ling.l_onoff = shouldLinger;
|
||||
ling.l_linger = t;
|
||||
|
||||
return setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (char*)&ling, sizeof(ling)) == 0;
|
||||
}
|
||||
|
||||
bool Socket::SetSendBufferSize(int32_t size, int32_t& newSize)
|
||||
{
|
||||
socklen_t len = sizeof(int32_t);
|
||||
bool success = setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char*)&size, sizeof(int32_t)) == 0;
|
||||
|
||||
getsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char*)&newSize, &len);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Socket::SetReceiveBufferSize(int32_t size, int32_t& newSize)
|
||||
{
|
||||
socklen_t len = sizeof(int32_t);
|
||||
bool success = setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&size, sizeof(int32_t)) == 0;
|
||||
|
||||
getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&newSize, &len);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
uint32_t Socket::GetPort()
|
||||
{
|
||||
sockaddr_in addr;
|
||||
socklen_t size = sizeof(sockaddr_in);
|
||||
if (getsockname(m_socket, (sockaddr*)&addr, &size) != 0)
|
||||
return 0; // invalid port
|
||||
return ntohs(addr.sin_port);
|
||||
}
|
||||
|
||||
SocketReturn Socket::HasState(SocketParam state, std::chrono::milliseconds t)
|
||||
{
|
||||
timeval time;
|
||||
time.tv_sec = t.count();
|
||||
time.tv_usec = t.count() * 1000 + t.count();
|
||||
|
||||
fd_set socketSet;
|
||||
|
||||
FD_ZERO(&socketSet);
|
||||
FD_SET(m_socket, &socketSet);
|
||||
|
||||
int32_t SelectStatus = 0;
|
||||
switch (state)
|
||||
{
|
||||
case SocketParam::CanRead:
|
||||
SelectStatus = select(m_socket + 1, &socketSet, nullptr, nullptr, &time);
|
||||
break;
|
||||
|
||||
case SocketParam::CanWrite:
|
||||
SelectStatus = select(m_socket + 1, nullptr, &socketSet, nullptr, &time);
|
||||
break;
|
||||
|
||||
case SocketParam::HasError:
|
||||
SelectStatus = select(m_socket + 1, nullptr, nullptr, &socketSet, &time);
|
||||
break;
|
||||
}
|
||||
|
||||
return SelectStatus > 0 ? SocketReturn::Yes :
|
||||
SelectStatus == 0 ? SocketReturn::No :
|
||||
SocketReturn::EncounteredError;
|
||||
}
|
||||
|
||||
SocketErrors Socket::TranslateErrorCode(int32_t code)
|
||||
{
|
||||
#if !_WIN32
|
||||
if (code == SOCKET_ERROR)
|
||||
{
|
||||
return SE_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0: return SocketErrors::SE_NO_ERROR;
|
||||
case EINTR: return SocketErrors::SE_EINTR;
|
||||
case EBADF: return SocketErrors::SE_EBADF;
|
||||
case EACCES: return SocketErrors::SE_EACCES;
|
||||
case EFAULT: return SocketErrors::SE_EFAULT;
|
||||
case EINVAL: return SocketErrors::SE_EINVAL;
|
||||
case EMFILE: return SocketErrors::SE_EMFILE;
|
||||
case EWOULDBLOCK: return SocketErrors::SE_EWOULDBLOCK;
|
||||
case EINPROGRESS: return SocketErrors::SE_EINPROGRESS;
|
||||
case EALREADY: return SocketErrors::SE_EALREADY;
|
||||
case ENOTSOCK: return SocketErrors::SE_ENOTSOCK;
|
||||
case EDESTADDRREQ: return SocketErrors::SE_EDESTADDRREQ;
|
||||
case EMSGSIZE: return SocketErrors::SE_EMSGSIZE;
|
||||
case EPROTOTYPE: return SocketErrors::SE_EPROTOTYPE;
|
||||
case ENOPROTOOPT: return SocketErrors::SE_ENOPROTOOPT;
|
||||
case EPROTONOSUPPORT: return SocketErrors::SE_EPROTONOSUPPORT;
|
||||
case ESOCKTNOSUPPORT: return SocketErrors::SE_ESOCKTNOSUPPORT;
|
||||
case EOPNOTSUPP: return SocketErrors::SE_EOPNOTSUPP;
|
||||
case EPFNOSUPPORT: return SocketErrors::SE_EPFNOSUPPORT;
|
||||
case EAFNOSUPPORT: return SocketErrors::SE_EAFNOSUPPORT;
|
||||
case EADDRINUSE: return SocketErrors::SE_EADDRINUSE;
|
||||
case EADDRNOTAVAIL: return SocketErrors::SE_EADDRNOTAVAIL;
|
||||
case ENETDOWN: return SocketErrors::SE_ENETDOWN;
|
||||
case ENETUNREACH: return SocketErrors::SE_ENETUNREACH;
|
||||
case ENETRESET: return SocketErrors::SE_ENETRESET;
|
||||
case ECONNABORTED: return SocketErrors::SE_ECONNABORTED;
|
||||
case ECONNRESET: return SocketErrors::SE_ECONNRESET;
|
||||
case ENOBUFS: return SocketErrors::SE_ENOBUFS;
|
||||
case EISCONN: return SocketErrors::SE_EISCONN;
|
||||
case ENOTCONN: return SocketErrors::SE_ENOTCONN;
|
||||
case ESHUTDOWN: return SocketErrors::SE_ESHUTDOWN;
|
||||
case ETOOMANYREFS: return SocketErrors::SE_ETOOMANYREFS;
|
||||
case ETIMEDOUT: return SocketErrors::SE_ETIMEDOUT;
|
||||
case ECONNREFUSED: return SocketErrors::SE_ECONNREFUSED;
|
||||
case ELOOP: return SocketErrors::SE_ELOOP;
|
||||
case ENAMETOOLONG: return SocketErrors::SE_ENAMETOOLONG;
|
||||
case EHOSTDOWN: return SocketErrors::SE_EHOSTDOWN;
|
||||
case EHOSTUNREACH: return SocketErrors::SE_EHOSTUNREACH;
|
||||
case ENOTEMPTY: return SocketErrors::SE_ENOTEMPTY;
|
||||
case EUSERS: return SocketErrors::SE_EUSERS;
|
||||
case EDQUOT: return SocketErrors::SE_EDQUOT;
|
||||
case ESTALE: return SocketErrors::SE_ESTALE;
|
||||
case EREMOTE: return SocketErrors::SE_EREMOTE;
|
||||
case ENODEV: return SocketErrors::SE_NODEV;
|
||||
#if !PLATFORM_HAS_NO_EPROCLIM
|
||||
case EPROCLIM: return SocketErrors::SE_EPROCLIM;
|
||||
#endif
|
||||
// case EDISCON: return SE_EDISCON;
|
||||
// case SYSNOTREADY: return SE_SYSNOTREADY;
|
||||
// case VERNOTSUPPORTED: return SE_VERNOTSUPPORTED;
|
||||
// case NOTINITIALISED: return SE_NOTINITIALISED;
|
||||
|
||||
#if PLATFORM_HAS_BSD_SOCKET_FEATURE_GETHOSTNAME
|
||||
case HOST_NOT_FOUND: return SocketErrors::SE_HOST_NOT_FOUND;
|
||||
case TRY_AGAIN: return SocketErrors::SE_TRY_AGAIN;
|
||||
case NO_RECOVERY: return SocketErrors::SE_NO_RECOVERY;
|
||||
#endif
|
||||
|
||||
// case NO_DATA: return SE_NO_DATA;
|
||||
// case : return SE_UDP_ERR_PORT_UNREACH; //@TODO Find it's replacement
|
||||
}
|
||||
|
||||
return SocketErrors::SE_EINVAL;
|
||||
#else
|
||||
// handle the generic -1 error
|
||||
if (code == SOCKET_ERROR)
|
||||
{
|
||||
return SocketErrors::SE_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 0: return SocketErrors::SE_NO_ERROR;
|
||||
case ERROR_INVALID_HANDLE: return SocketErrors::SE_ECONNRESET; // invalid socket handle catch
|
||||
case WSAEINTR: return SocketErrors::SE_EINTR;
|
||||
case WSAEBADF: return SocketErrors::SE_EBADF;
|
||||
case WSAEACCES: return SocketErrors::SE_EACCES;
|
||||
case WSAEFAULT: return SocketErrors::SE_EFAULT;
|
||||
case WSAEINVAL: return SocketErrors::SE_EINVAL;
|
||||
case WSAEMFILE: return SocketErrors::SE_EMFILE;
|
||||
case WSAEWOULDBLOCK: return SocketErrors::SE_EWOULDBLOCK;
|
||||
case WSAEINPROGRESS: return SocketErrors::SE_EINPROGRESS;
|
||||
case WSAEALREADY: return SocketErrors::SE_EALREADY;
|
||||
case WSAENOTSOCK: return SocketErrors::SE_ENOTSOCK;
|
||||
case WSAEDESTADDRREQ: return SocketErrors::SE_EDESTADDRREQ;
|
||||
case WSAEMSGSIZE: return SocketErrors::SE_EMSGSIZE;
|
||||
case WSAEPROTOTYPE: return SocketErrors::SE_EPROTOTYPE;
|
||||
case WSAENOPROTOOPT: return SocketErrors::SE_ENOPROTOOPT;
|
||||
case WSAEPROTONOSUPPORT: return SocketErrors::SE_EPROTONOSUPPORT;
|
||||
case WSAESOCKTNOSUPPORT: return SocketErrors::SE_ESOCKTNOSUPPORT;
|
||||
case WSAEOPNOTSUPP: return SocketErrors::SE_EOPNOTSUPP;
|
||||
case WSAEPFNOSUPPORT: return SocketErrors::SE_EPFNOSUPPORT;
|
||||
case WSAEAFNOSUPPORT: return SocketErrors::SE_EAFNOSUPPORT;
|
||||
case WSAEADDRINUSE: return SocketErrors::SE_EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return SocketErrors::SE_EADDRNOTAVAIL;
|
||||
case WSAENETDOWN: return SocketErrors::SE_ENETDOWN;
|
||||
case WSAENETUNREACH: return SocketErrors::SE_ENETUNREACH;
|
||||
case WSAENETRESET: return SocketErrors::SE_ENETRESET;
|
||||
case WSAECONNABORTED: return SocketErrors::SE_ECONNABORTED;
|
||||
case WSAECONNRESET: return SocketErrors::SE_ECONNRESET;
|
||||
case WSAENOBUFS: return SocketErrors::SE_ENOBUFS;
|
||||
case WSAEISCONN: return SocketErrors::SE_EISCONN;
|
||||
case WSAENOTCONN: return SocketErrors::SE_ENOTCONN;
|
||||
case WSAESHUTDOWN: return SocketErrors::SE_ESHUTDOWN;
|
||||
case WSAETOOMANYREFS: return SocketErrors::SE_ETOOMANYREFS;
|
||||
case WSAETIMEDOUT: return SocketErrors::SE_ETIMEDOUT;
|
||||
case WSAECONNREFUSED: return SocketErrors::SE_ECONNREFUSED;
|
||||
case WSAELOOP: return SocketErrors::SE_ELOOP;
|
||||
case WSAENAMETOOLONG: return SocketErrors::SE_ENAMETOOLONG;
|
||||
case WSAEHOSTDOWN: return SocketErrors::SE_EHOSTDOWN;
|
||||
case WSAEHOSTUNREACH: return SocketErrors::SE_EHOSTUNREACH;
|
||||
case WSAENOTEMPTY: return SocketErrors::SE_ENOTEMPTY;
|
||||
case WSAEPROCLIM: return SocketErrors::SE_EPROCLIM;
|
||||
case WSAEUSERS: return SocketErrors::SE_EUSERS;
|
||||
case WSAEDQUOT: return SocketErrors::SE_EDQUOT;
|
||||
case WSAESTALE: return SocketErrors::SE_ESTALE;
|
||||
case WSAEREMOTE: return SocketErrors::SE_EREMOTE;
|
||||
case WSAEDISCON: return SocketErrors::SE_EDISCON;
|
||||
case WSASYSNOTREADY: return SocketErrors::SE_SYSNOTREADY;
|
||||
case WSAVERNOTSUPPORTED: return SocketErrors::SE_VERNOTSUPPORTED;
|
||||
case WSANOTINITIALISED: return SocketErrors::SE_NOTINITIALISED;
|
||||
case WSAHOST_NOT_FOUND: return SocketErrors::SE_HOST_NOT_FOUND;
|
||||
case WSATRY_AGAIN: return SocketErrors::SE_TRY_AGAIN;
|
||||
case WSANO_RECOVERY: return SocketErrors::SE_NO_RECOVERY;
|
||||
case WSANO_DATA: return SocketErrors::SE_NO_DATA;
|
||||
// case : return SE_UDP_ERR_PORT_UNREACH;
|
||||
}
|
||||
|
||||
return SocketErrors::SE_NO_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
int Socket::TranslateFlags(SocketReceiveFlags flags)
|
||||
{
|
||||
int translatedFlags = 0;
|
||||
|
||||
if ((int)flags & (int)SocketReceiveFlags::Peek)
|
||||
{
|
||||
translatedFlags |= MSG_PEEK;
|
||||
#if !_WIN32
|
||||
translatedFlags |= MSG_DONTWAIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((int)flags & (int)SocketReceiveFlags::WaitAll)
|
||||
{
|
||||
translatedFlags |= MSG_WAITALL;
|
||||
}
|
||||
|
||||
return translatedFlags;
|
||||
}
|
||||
}
|
||||
@ -1,255 +1,60 @@
|
||||
#include "TcpClient.hpp"
|
||||
#include "NetworkBuffer.hpp"
|
||||
#include "Utility.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Handshake.hpp"
|
||||
#include "TcpSocketBuilder.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
|
||||
TcpClient::TcpClient(const std::string &ip) : port(default_client_port)
|
||||
namespace std::net
|
||||
{
|
||||
initialize(ip);
|
||||
}
|
||||
|
||||
TcpClient::TcpClient(const std::string &ip, uint16 port) :
|
||||
ip(ip), port(port)
|
||||
{
|
||||
initialize(ip, port);
|
||||
}
|
||||
|
||||
const std::string &TcpClient::GetIP()
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
|
||||
uint16 TcpClient::GetPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
void TcpClient::SetIP(const std::string & ip)
|
||||
{
|
||||
this->ip = ip;
|
||||
}
|
||||
|
||||
void TcpClient::SetPort(uint16 port)
|
||||
{
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
uint16 TcpClient::GetID()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void TcpClient::SetID(uint16 id)
|
||||
{
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
void TcpClient::receive_data(TcpClient *client)
|
||||
{
|
||||
while (client->receive)
|
||||
TcpClient::TcpClient(Socket *soc)
|
||||
{
|
||||
NetworkMessage message(client->ReceiveMessage());
|
||||
if (message.valid)
|
||||
{
|
||||
if (IS_HANDSHAKE(message))
|
||||
{
|
||||
if (message.tag == ConnectTag) // some user has connected - not us, never
|
||||
std::async(std::launch::async, client->OnConnect, message.sender);
|
||||
else if (message.tag == DisconnectTag) // some user has disconnected, it can be us
|
||||
std::async(std::launch::async, client->OnDisconnect, message.sender);
|
||||
else if (message.tag == Close)
|
||||
{
|
||||
std::async(std::launch::async, client->OnDisconnect, message.sender);
|
||||
close_connection(client);
|
||||
}
|
||||
}
|
||||
else
|
||||
std::async(std::launch::async, client->OnMessage, message.sender, message.tag, message.subject, message.data); // we received data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TcpClient::ReceiveMessages()
|
||||
{
|
||||
std::async(std::launch::async, &receive_data, this);
|
||||
}
|
||||
|
||||
const NetworkMessage & TcpClient::ReceiveMessage()
|
||||
{
|
||||
return receive_data_array();
|
||||
}
|
||||
|
||||
std::future<bool> TcpClient::SendMessage(const NetworkMessage &message)
|
||||
{
|
||||
return std::async(std::launch::async, &send_network_message, message, this);
|
||||
}
|
||||
|
||||
void TcpClient::SetOnDisconnectCallback(std::function<void(uint16)> func)
|
||||
{
|
||||
OnDisconnect = func;
|
||||
}
|
||||
|
||||
void TcpClient::SetOnConnectCallback(std::function<void(uint16)> func)
|
||||
{
|
||||
OnConnect = func;
|
||||
}
|
||||
|
||||
void TcpClient::SetOnMessageCallback(std::function<void(uint16, byte, byte, void*)> func)
|
||||
{
|
||||
OnMessage = func;
|
||||
}
|
||||
|
||||
const TcpClient & TcpClient::DefaultTcpClient()
|
||||
{
|
||||
return TcpClient();
|
||||
}
|
||||
|
||||
TcpClient::TcpClient(const SOCKET & socket)
|
||||
{
|
||||
tcp_socket = socket;
|
||||
}
|
||||
|
||||
bool TcpClient::initialize(const std::string &ip, uint16 port)
|
||||
{
|
||||
if (Utility::IPUtil::ValidIPV4(ip) || port == 0)
|
||||
return false;
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
uint16 code = getaddrinfo(ip.c_str(), std::to_string(port).c_str(), &hints, &result);
|
||||
if (code != 0)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << code << std::endl; // display more info
|
||||
WSACleanup();
|
||||
return false;
|
||||
m_socket = std::unique_ptr<Socket>(soc); // will this work
|
||||
}
|
||||
|
||||
tcp_socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
|
||||
if (tcp_socket == INVALID_SOCKET)
|
||||
TcpClient::TcpClient(SocketProtocol protocol)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl; // display more info
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
return false;
|
||||
m_socket = TcpSocketBuilder().AsNonBlocking().AsReusable().Protocol(protocol).Build();
|
||||
}
|
||||
|
||||
return initialized = true;
|
||||
}
|
||||
|
||||
TcpClient::~TcpClient()
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
Utility::Delete(result);
|
||||
}
|
||||
|
||||
void TcpClient::Shutdown()
|
||||
{
|
||||
Handshake handshake(id, Close, Server);
|
||||
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
|
||||
uint16 code = closesocket(tcp_socket);
|
||||
if (code == SOCKET_ERROR)
|
||||
bool TcpClient::Connect(const IPAddress& addrStr)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl; // display more info
|
||||
return m_socket->Connect(addrStr);
|
||||
}
|
||||
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
bool TcpClient::Connect()
|
||||
{
|
||||
if (!initialized)
|
||||
bool TcpClient::Close() const
|
||||
{
|
||||
if (ip.size() == 0 || std::count(ip.begin(), ip.end(), '.') != 4 && port == 0 && !initialize(ip, port))
|
||||
return false;
|
||||
return m_socket->Close();
|
||||
}
|
||||
else return false;
|
||||
|
||||
uint16 connect_code = connect(tcp_socket, result->ai_addr, result->ai_addrlen);
|
||||
if (connect_code == SOCKET_ERROR)
|
||||
return false;
|
||||
|
||||
NetworkMessage message(receive_data_array());
|
||||
if (IS_HANDSHAKE(message))
|
||||
bool TcpClient::HasPendingData(uint32_t& pendingDataSize) const
|
||||
{
|
||||
if (message.tag == Accept)
|
||||
{
|
||||
receive = true;
|
||||
OnConnect(message.sender);
|
||||
return true;
|
||||
}
|
||||
return m_socket->HasPendingData(pendingDataSize);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TcpClient::DataAvailable(int32 &size)
|
||||
{
|
||||
return ioctlsocket(tcp_socket, FIONREAD, reinterpret_cast<u_long*>(size)) != NO_ERROR && size > 0;
|
||||
}
|
||||
|
||||
const NetworkBuffer &TcpClient::receive_data_array()
|
||||
{
|
||||
NetworkBuffer buffer;
|
||||
|
||||
int32 temp;
|
||||
if (DataAvailable(temp) && temp > sizeof(int32))
|
||||
bool TcpClient::Send(const uint8_t* data, int32_t count, int32_t& sent) const
|
||||
{
|
||||
byte *header = new byte[sizeof(int32)]();
|
||||
if (recv(tcp_socket, reinterpret_cast<char*>(header), sizeof(int32), 0) != sizeof(int32))
|
||||
return NetworkBuffer();
|
||||
buffer.header = std::vector<byte>(header, header + sizeof(int32));
|
||||
return m_socket->Send(data, count, sent);
|
||||
}
|
||||
else
|
||||
return NetworkBuffer();
|
||||
|
||||
int32 body_size = Utility::BitConverter::ToInt32(buffer.header);
|
||||
byte *body = new byte[body_size]();
|
||||
int16 received_bytes = recv(tcp_socket, reinterpret_cast<char*>(body), body_size, 0);
|
||||
if (received_bytes == SOCKET_ERROR || received_bytes != body_size || WSAGetLastError() != 0)
|
||||
return NetworkBuffer();
|
||||
|
||||
buffer.body = std::vector<byte>(body, body + body_size);
|
||||
buffer.valid = true;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool TcpClient::send_network_message(const NetworkMessage &message, TcpClient *client)
|
||||
{
|
||||
NetworkBuffer buffer = NetworkMessage::EncodeMessage(message);
|
||||
int32 lenght = Utility::BitConverter::ToInt32(buffer.header);
|
||||
int32 bytes_sent = send(client->tcp_socket, reinterpret_cast<char*>(buffer.body.data()), lenght, 0);
|
||||
return bytes_sent == SOCKET_ERROR || bytes_sent != lenght || WSAGetLastError() != 0;
|
||||
}
|
||||
|
||||
void TcpClient::close_connection(TcpClient * client)
|
||||
{
|
||||
shutdown(client->tcp_socket, SD_BOTH);
|
||||
closesocket(client->tcp_socket);
|
||||
}
|
||||
|
||||
bool TcpClient::SendBytes(const std::vector<byte>& bytes)
|
||||
{
|
||||
int32 bytes_sent = send(tcp_socket, reinterpret_cast<const char*>(bytes.data()), bytes.size(), 0);
|
||||
if (bytes_sent == SOCKET_ERROR || bytes_sent != bytes.size() || WSAGetLastError() != 0)
|
||||
bool TcpClient::Recv(uint8_t* data, int32_t size, int32_t& read, SocketReceiveFlags flags) const
|
||||
{
|
||||
//something went wrong couldnt send anything/some data
|
||||
return m_socket->Recv(data, size, read, flags);
|
||||
}
|
||||
|
||||
bool TcpClient::Wait(SocketWaitConditions cond, std::chrono::milliseconds t) const
|
||||
{
|
||||
return m_socket->Wait(cond, t);
|
||||
}
|
||||
|
||||
SocketConnectionState TcpClient::GetConnectionState() const
|
||||
{
|
||||
return m_socket->GetConnectionState();
|
||||
}
|
||||
|
||||
void TcpClient::GetAddress(IPAddress& outAddr) const
|
||||
{
|
||||
return m_socket->GetAddress(outAddr);
|
||||
}
|
||||
|
||||
int32_t TcpClient::GetPort() const
|
||||
{
|
||||
return m_socket->GetPort();
|
||||
}
|
||||
}
|
||||
|
||||
bool TcpClient::SendBytes(byte * bytes, uint32 size)
|
||||
{
|
||||
int32 bytes_sent = send(tcp_socket, reinterpret_cast<const char*>(bytes), size, 0);
|
||||
return bytes_sent == SOCKET_ERROR || bytes_sent != size || WSAGetLastError() != 0;
|
||||
}
|
||||
54
src/TcpListener.cpp
Normal file
54
src/TcpListener.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "TcpListener.hpp"
|
||||
#include "TcpSocketBuilder.hpp"
|
||||
#include "Socket.hpp"
|
||||
#include "TcpClient.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
TcpListener::TcpListener(uint16_t port, std::chrono::milliseconds inSleepTime)
|
||||
: m_port(port)
|
||||
, m_sleepTime(inSleepTime)
|
||||
{
|
||||
m_socket = TcpSocketBuilder().AsNonBlocking().AsReusable().Bind(IPAddress(0, 0, 0, 0, port)).Listening().Build();
|
||||
}
|
||||
|
||||
TcpListener::TcpListener(Socket *InSocket, std::chrono::milliseconds inSleepTime)
|
||||
: m_sleepTime(inSleepTime)
|
||||
{
|
||||
m_socket = std::unique_ptr<Socket>(InSocket);
|
||||
}
|
||||
|
||||
TcpClient *TcpListener::AcceptClient()
|
||||
{
|
||||
if (m_socket == nullptr)
|
||||
m_socket = TcpSocketBuilder().AsReusable().Bind(IPAddress(0, 0, 0, 0, m_port)).Listening().Build();
|
||||
|
||||
if (m_socket == nullptr)
|
||||
return nullptr;
|
||||
|
||||
std::string remoteAddress;
|
||||
|
||||
const bool hasZeroSleepTime = (m_sleepTime == std::chrono::milliseconds(0));
|
||||
|
||||
bool pending = false;
|
||||
|
||||
if (m_socket->WaitForPendingConnection(pending, m_sleepTime))
|
||||
{
|
||||
if (pending)
|
||||
{
|
||||
std::unique_ptr<Socket> connectionSocket = m_socket->Accept();
|
||||
|
||||
if (connectionSocket != nullptr)
|
||||
{
|
||||
return new TcpClient(connectionSocket.release());
|
||||
}
|
||||
}
|
||||
else if (hasZeroSleepTime)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(0));
|
||||
}
|
||||
else
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(m_sleepTime));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -1,290 +0,0 @@
|
||||
#include "TcpServer.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "Handshake.hpp"
|
||||
#include "Utility.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
|
||||
TcpServer::TcpServer()
|
||||
{
|
||||
initialize(); // initialize with the default port
|
||||
clients.reserve(max_connections);
|
||||
}
|
||||
|
||||
TcpServer::TcpServer(uint16 port)
|
||||
{
|
||||
initialize(port);
|
||||
clients.reserve(max_connections);
|
||||
}
|
||||
|
||||
TcpServer::~TcpServer()
|
||||
{
|
||||
}
|
||||
|
||||
void TcpServer::Shutdown()
|
||||
{
|
||||
running = false;
|
||||
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
(*it).Shutdown();
|
||||
clients.erase(it);
|
||||
}
|
||||
|
||||
shutdown_internal();
|
||||
}
|
||||
|
||||
void TcpServer::AcceptConnections()
|
||||
{
|
||||
if (!running)
|
||||
{
|
||||
running = true;
|
||||
std::async(std::launch::async, &accept_connections, this);
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::process_client_messages(TcpServer *server, TcpClient & client)
|
||||
{
|
||||
while (server->running)
|
||||
{
|
||||
NetworkMessage message(client.ReceiveMessage());
|
||||
if (message.valid)
|
||||
server->SendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
bool TcpServer::SendMessage(const NetworkMessage & message)
|
||||
{
|
||||
switch (message.distribution_mode)
|
||||
{
|
||||
case All: // this will send the message to all except the user that sent it
|
||||
{
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient client = *it;
|
||||
if (message.sender != client.GetID())
|
||||
client.SendMessage(message);
|
||||
}
|
||||
for (uint16 i = 0; i < OnMessageFunctions.size(); i++)
|
||||
OnMessageFunctions[i](message);
|
||||
}
|
||||
case AllAndMe: // this will send the message to EVERYONE including the user that sent it
|
||||
{
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient client = *it;
|
||||
client.SendMessage(message);
|
||||
}
|
||||
for (uint16 i = 0; i < OnMessageFunctions.size(); i++)
|
||||
OnMessageFunctions[i](message);
|
||||
}
|
||||
case Server: // this will only send the message to the server
|
||||
{
|
||||
if (message.tag == DisconnectTag)
|
||||
CloseSocket(message.sender);
|
||||
for (uint16 i = 0; i < OnMessageFunctions.size(); i++)
|
||||
OnMessageFunctions[i](message);
|
||||
}
|
||||
case Others: // this will send the message to others, excluding server and the user that sent it
|
||||
{
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient client = *it;
|
||||
if (message.sender != client.GetID())
|
||||
client.SendMessage(message);
|
||||
}
|
||||
}
|
||||
case ID: // this will send the message to a specific id
|
||||
{
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient client = *it;
|
||||
if (message.sender == client.GetID())
|
||||
client.SendMessage(message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16 TcpServer::allocate_id() // this function is only used in the AddToClientsList function
|
||||
{
|
||||
for (uint16 i = 1; i < max_connections; ++i)
|
||||
{
|
||||
bool flag = true;
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient client = *it;
|
||||
if (client.GetID() == i)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TcpServer::add_to_clients_list(TcpClient & client_socket)
|
||||
{
|
||||
uint16 id = allocate_id();
|
||||
if (id > 0)
|
||||
{
|
||||
client_socket.SetID(id);
|
||||
clients.emplace_back(client_socket);
|
||||
AcceptConnection(client_socket.GetID());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cout << "No available ID's" << std::endl;
|
||||
RejectConnection(client_socket);
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::RejectConnection(TcpClient &client)
|
||||
{
|
||||
Handshake handshake(client.GetID(), Reject, ID);
|
||||
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
|
||||
}
|
||||
|
||||
void TcpServer::AcceptConnection(uint16 id)
|
||||
{
|
||||
Handshake handshake(id, Accept, AllAndMe);
|
||||
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
|
||||
}
|
||||
|
||||
void TcpServer::CloseSocket(TcpClient & client)
|
||||
{
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient it_client = *it;
|
||||
if (client.GetID() == it_client.GetID())
|
||||
{
|
||||
it_client.Shutdown();
|
||||
clients.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::CloseSocket(uint16 id)
|
||||
{
|
||||
TcpClient client = GetClientByID(id);
|
||||
if (client.GetID() != -2)
|
||||
CloseSocket(client);
|
||||
}
|
||||
|
||||
const TcpClient & TcpServer::GetClientByID(uint16 id)
|
||||
{
|
||||
for (std::vector<TcpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
TcpClient client = *it;
|
||||
if (client.GetID() == id)
|
||||
return client;
|
||||
}
|
||||
return TcpClient::DefaultTcpClient();
|
||||
}
|
||||
|
||||
void TcpServer::SetMaxConnections(uint16 value)
|
||||
{
|
||||
max_connections = value;
|
||||
}
|
||||
|
||||
uint16 TcpServer::GetMaxConnections()
|
||||
{
|
||||
return max_connections;
|
||||
}
|
||||
|
||||
bool TcpServer::initialize(uint16 port)
|
||||
{
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
uint16 code = getaddrinfo(0, std::to_string(port).c_str(), &hints, &result);
|
||||
if (code != 0)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl; // display more info
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
server_tcp_socket = ::socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
|
||||
if (server_tcp_socket == INVALID_SOCKET)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl; // display more info
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
code = bind(server_tcp_socket, result->ai_addr, result->ai_addrlen);
|
||||
if (code == SOCKET_ERROR)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl; // display more info
|
||||
freeaddrinfo(result);
|
||||
closesocket(server_tcp_socket);
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return initialized = true;
|
||||
}
|
||||
|
||||
bool TcpServer::StartServer(bool accept_connections)
|
||||
{
|
||||
if (listen(server_tcp_socket, SOMAXCONN) == SOCKET_ERROR)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl;
|
||||
closesocket(server_tcp_socket);
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (accept_connections)
|
||||
AcceptConnections();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TcpServer::accept_connections(TcpServer *server)
|
||||
{
|
||||
while (server->running)
|
||||
{
|
||||
SOCKET client_socket = accept(server->server_tcp_socket, 0, 0);
|
||||
if (client_socket == INVALID_SOCKET)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl;
|
||||
closesocket(server->server_tcp_socket);
|
||||
WSACleanup();
|
||||
server->running = false; // if we cant accept a connection idk if we should stop the server or not mh
|
||||
break;
|
||||
}
|
||||
|
||||
TcpClient client(client_socket);
|
||||
server->add_to_clients_list(client);
|
||||
|
||||
std::async(std::launch::async, &process_client_messages, server, client);
|
||||
}
|
||||
}
|
||||
|
||||
void TcpServer::shutdown_internal()
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
Utility::Delete(result);
|
||||
}
|
||||
52
src/TcpSocketBuilder.cpp
Normal file
52
src/TcpSocketBuilder.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "TcpSocketBuilder.hpp"
|
||||
|
||||
#include "Socket.hpp"
|
||||
#include "TcpClient.hpp"
|
||||
#include "TcpListener.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
std::unique_ptr<Socket> TcpSocketBuilder::Build() const
|
||||
{
|
||||
std::unique_ptr<Socket> socket = std::make_unique<Socket>(SocketType::Streaming, m_socketProtocol);
|
||||
|
||||
if (socket != nullptr)
|
||||
{
|
||||
bool Error = !socket->SetReuseAddr(m_reusable) ||
|
||||
!socket->SetLinger(m_linger, m_lingerTimeout);
|
||||
|
||||
if (!Error)
|
||||
Error = m_bound && !socket->Bind(m_boundAddr);
|
||||
if (!Error)
|
||||
Error = m_listen && !socket->Listen();
|
||||
if (!Error)
|
||||
Error = !socket->SetNonBlocking(!m_blocking);
|
||||
|
||||
if (!Error)
|
||||
{
|
||||
int32_t out_new_size;
|
||||
if (m_receiveBufferSize > 0)
|
||||
socket->SetReceiveBufferSize(m_receiveBufferSize, out_new_size);
|
||||
if (m_sendBufferSize > 0)
|
||||
socket->SetSendBufferSize(m_sendBufferSize, out_new_size);
|
||||
}
|
||||
|
||||
if (Error)
|
||||
throw std::runtime_error("Couldnt create socket"); // make parameter a string depending on the error
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
std::unique_ptr<TcpClient> TcpSocketBuilder::BuildClient() const
|
||||
{
|
||||
std::unique_ptr<Socket> socket = Build();
|
||||
return std::make_unique<TcpClient>(socket.release());
|
||||
}
|
||||
|
||||
std::unique_ptr<TcpListener> TcpSocketBuilder::BuildListener() const
|
||||
{
|
||||
std::unique_ptr<Socket> socket = Build();
|
||||
return std::make_unique<TcpListener>(socket.release());
|
||||
}
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
#include "UdpClient.hpp"
|
||||
#include "Handshake.hpp"
|
||||
#include "Config.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <future>
|
||||
|
||||
UdpClient::UdpClient(const std::string & ip)
|
||||
{
|
||||
initialize(ip);
|
||||
}
|
||||
|
||||
UdpClient::UdpClient(const std::string & ip, uint16)
|
||||
{
|
||||
initialize(ip, port);
|
||||
}
|
||||
|
||||
uint16 UdpClient::GetPort()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
void UdpClient::SetPort(uint16 port)
|
||||
{
|
||||
this->port = port;
|
||||
}
|
||||
|
||||
uint16 UdpClient::GetID()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void UdpClient::SetID(uint16 id)
|
||||
{
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
void UdpClient::ReceiveMessages()
|
||||
{
|
||||
}
|
||||
|
||||
const NetworkMessage & UdpClient::ReceiveMessage()
|
||||
{
|
||||
// TODO: insert return statement here
|
||||
}
|
||||
|
||||
std::future<bool> UdpClient::SendMessage(const NetworkMessage & message)
|
||||
{
|
||||
return std::async(std::launch::async, &send_network_message, message, this);
|
||||
}
|
||||
|
||||
const std::string &UdpClient::GetIP()
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
|
||||
void UdpClient::SetIP(const std::string & ip)
|
||||
{
|
||||
this->ip = ip;
|
||||
}
|
||||
|
||||
UdpClient::UdpClient(const SOCKET & socket)
|
||||
{
|
||||
udp_socket = socket;
|
||||
}
|
||||
|
||||
const NetworkBuffer & UdpClient::receive_data_array()
|
||||
{
|
||||
// TODO: insert return statement here
|
||||
}
|
||||
|
||||
void UdpClient::receive_data(UdpClient * client)
|
||||
{
|
||||
}
|
||||
|
||||
bool UdpClient::initialize(const std::string &ip, uint16 port)
|
||||
{
|
||||
if (Utility::IPUtil::ValidIPV4(ip) || port == 0)
|
||||
return false;
|
||||
|
||||
udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (udp_socket == INVALID_SOCKET)
|
||||
{
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UdpClient::~UdpClient()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
void UdpClient::Shutdown()
|
||||
{
|
||||
Handshake handshake(id, Close, Server);
|
||||
SendMessage(Handshake::HandshakeToNetworkMessage(handshake));
|
||||
uint16 code = closesocket(udp_socket);
|
||||
if (code == SOCKET_ERROR)
|
||||
{
|
||||
if (Config::GetUsingConsole())
|
||||
std::cerr << WSAGetLastError() << std::endl; // display more info
|
||||
}
|
||||
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
bool UdpClient::SendBytes(const std::vector<byte> &bytes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool UdpClient::SendBytes(byte *bytes, uint32 lenght)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool UdpClient::send_network_message(const NetworkMessage &message, UdpClient *client)
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
#include "UdpServer.hpp"
|
||||
#include "Utility.hpp"
|
||||
|
||||
uint16 UdpServer::allocate_id()
|
||||
{
|
||||
for (uint16 i = 1; i < max_connections; ++i)
|
||||
{
|
||||
bool flag = true;
|
||||
for (std::vector<UdpClient>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||
{
|
||||
UdpClient client = *it;
|
||||
if (client.GetID() == i)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UdpServer::initialize(uint16 port)
|
||||
{
|
||||
server_udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (server_udp_socket == INVALID_SOCKET)
|
||||
{
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&server, '\0', sizeof(struct sockaddr_in));
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
server.sin_addr.S_un.S_un_b.s_b1 = 0;
|
||||
server.sin_addr.S_un.S_un_b.s_b2 = 0;
|
||||
server.sin_addr.S_un.S_un_b.s_b3 = 0;
|
||||
server.sin_addr.S_un.S_un_b.s_b4 = 0;
|
||||
|
||||
if (bind(server_udp_socket, reinterpret_cast<struct sockaddr*>(&server), sizeof(struct sockaddr_in)) == -1)
|
||||
{
|
||||
closesocket(server_udp_socket);
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
return initialized = true;
|
||||
}
|
||||
|
||||
void UdpServer::shutdown_internal()
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
64
src/UdpSocket.cpp
Normal file
64
src/UdpSocket.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "UdpSocket.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
UdpSocket::UdpSocket(Socket * soc)
|
||||
{
|
||||
m_socket = std::unique_ptr<Socket>(soc); // will this work
|
||||
}
|
||||
|
||||
UdpSocket::UdpSocket(SocketProtocol protocol)
|
||||
{
|
||||
m_socket = std::make_unique<Socket>(SocketType::Datagram, protocol);
|
||||
}
|
||||
|
||||
bool UdpSocket::Bind(const IPAddress & addr)
|
||||
{
|
||||
return m_socket->Bind(addr);
|
||||
}
|
||||
|
||||
bool UdpSocket::SendTo(const uint8_t * data, int32_t count, int32_t & sent, const IPAddress & addrDest)
|
||||
{
|
||||
return m_socket->SendTo(data, count, sent, addrDest);
|
||||
}
|
||||
|
||||
bool UdpSocket::RecvFrom(uint8_t * data, int32_t size, int32_t & read, IPAddress & srcAddr, SocketReceiveFlags flags)
|
||||
{
|
||||
return m_socket->RecvFrom(data, size, read, srcAddr, flags);
|
||||
}
|
||||
|
||||
bool UdpSocket::GetPeerAddress(IPAddress & outAddr)
|
||||
{
|
||||
return m_socket->GetPeerAddress(outAddr);
|
||||
}
|
||||
|
||||
bool UdpSocket::JoinMulticastGroup(const IPAddress & addrStr)
|
||||
{
|
||||
return m_socket->JoinMulticastGroup(addrStr);
|
||||
}
|
||||
|
||||
bool UdpSocket::LeaveMulticastGroup(const IPAddress & addrStr)
|
||||
{
|
||||
return m_socket->LeaveMulticastGroup(addrStr);
|
||||
}
|
||||
|
||||
bool UdpSocket::SetMulticastLoopback(bool loopback)
|
||||
{
|
||||
return m_socket->SetMulticastLoopback(loopback);
|
||||
}
|
||||
|
||||
bool UdpSocket::SetMulticastTtl(uint8_t timeToLive)
|
||||
{
|
||||
return m_socket->SetMulticastTtl(timeToLive);
|
||||
}
|
||||
|
||||
uint32_t UdpSocket::GetPort()
|
||||
{
|
||||
return m_socket->GetPort();
|
||||
}
|
||||
|
||||
bool UdpSocket::SetReuseAddr(bool allowReuse)
|
||||
{
|
||||
return m_socket->SetReuseAddr(allowReuse);
|
||||
}
|
||||
}
|
||||
188
src/Uri.cpp
Normal file
188
src/Uri.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
// https://github.com/mfichman/http
|
||||
|
||||
#include "Uri.hpp"
|
||||
#include "Parse.hpp"
|
||||
|
||||
namespace std::net
|
||||
{
|
||||
static bool IsReserved(char ch)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '/':
|
||||
return true;
|
||||
case '#':
|
||||
return true;
|
||||
case '?':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static ParseResult<std::string> ParseScheme(char const* str)
|
||||
{
|
||||
auto result = ParseWhile(str, [](char ch)
|
||||
{
|
||||
return ch != ':' && !IsReserved(ch);
|
||||
});
|
||||
|
||||
result.ch = (result.ch[0] == ':') ? (result.ch + 1) : (result.ch);
|
||||
return result;
|
||||
}
|
||||
|
||||
static ParseResult<std::string> ParseUser(char const* str)
|
||||
{
|
||||
auto result = ParseWhile(str, [](char ch)
|
||||
{
|
||||
return ch != '@' && !IsReserved(ch);
|
||||
});
|
||||
|
||||
if (result.ch[0] == '@')
|
||||
result.ch = result.ch + 1;
|
||||
else {
|
||||
result.ch = str;
|
||||
result.value = "";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static ParseResult<std::string> ParseHost(char const* str)
|
||||
{
|
||||
return ParseWhile(str, [](char ch)
|
||||
{
|
||||
return ch != ':' && !IsReserved(ch);
|
||||
});
|
||||
}
|
||||
|
||||
static ParseResult<uint16_t> ParsePort(char const* str)
|
||||
{
|
||||
ParseResult<uint16_t> result;
|
||||
if (str[0] != ':')
|
||||
{
|
||||
result.value = 0;
|
||||
result.ch = str;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto tmp = ParseWhile(str + 1, [](char ch)
|
||||
{
|
||||
return !IsReserved(ch);
|
||||
});
|
||||
|
||||
result.value = uint16_t(strtol(tmp.value.c_str(), 0, 10));
|
||||
result.ch = tmp.ch;
|
||||
return result;
|
||||
}
|
||||
|
||||
static ParseResult<Authority> parseAuthority(char const* str)
|
||||
{
|
||||
ParseResult<Authority> result
|
||||
{
|
||||
};
|
||||
|
||||
if (str[0] == '\0' || str[0] != '/' || str[1] != '/')
|
||||
{
|
||||
result.ch = str;
|
||||
return result;
|
||||
}
|
||||
|
||||
auto user = ParseUser(str + 2); // For "//"
|
||||
auto host = ParseHost(user.ch);
|
||||
auto port = ParsePort(host.ch);
|
||||
|
||||
result.value.SetUser(user.value);
|
||||
result.value.SetHost(host.value);
|
||||
result.value.SetPort(port.value);
|
||||
result.ch = port.ch;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static ParseResult<std::string> parsePath(char const* str)
|
||||
{
|
||||
// Return query/frag as part of path for now
|
||||
ParseResult<std::string> result = ParseWhile(str, [](char ch)
|
||||
{
|
||||
return true;
|
||||
});
|
||||
/*
|
||||
ParseResult<std::string> result = parseWhile(str, [](char ch) {
|
||||
return ch != '/' && !isReserved(ch);
|
||||
});
|
||||
result.ch = (result.ch[0] == '?') ? (result.ch+1) : (result.ch);
|
||||
*/
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static Uri parseUri(char const* str)
|
||||
{
|
||||
Uri uri;
|
||||
|
||||
auto scheme = ParseScheme(str);
|
||||
auto authority = parseAuthority(scheme.ch);
|
||||
auto path = parsePath(authority.ch);
|
||||
|
||||
uri.SetScheme(scheme.value);
|
||||
uri.SetAuthority(authority.value);
|
||||
uri.SetPath(path.value);
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
Authority::Authority(std::string const& user, std::string const& host, uint16_t port)
|
||||
{
|
||||
m_user = user;
|
||||
m_host = host;
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
Authority::Authority()
|
||||
{
|
||||
m_port = 0;
|
||||
}
|
||||
|
||||
void Authority::SetUser(std::string const& user)
|
||||
{
|
||||
m_user = user;
|
||||
}
|
||||
|
||||
void Authority::SetHost(std::string const& host)
|
||||
{
|
||||
m_host = host;
|
||||
}
|
||||
|
||||
void Authority::SetPort(uint16_t port)
|
||||
{
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
Uri::Uri(const char* value)
|
||||
{
|
||||
*this = parseUri(value);
|
||||
}
|
||||
|
||||
Uri::Uri(const std::string& value)
|
||||
{
|
||||
*this = parseUri(value.c_str());
|
||||
}
|
||||
|
||||
Uri::Uri() {
|
||||
}
|
||||
|
||||
void Uri::SetScheme(const std::string& scheme)
|
||||
{
|
||||
m_scheme = scheme;
|
||||
}
|
||||
|
||||
void Uri::SetAuthority(const Authority& authority)
|
||||
{
|
||||
m_authority = authority;
|
||||
}
|
||||
|
||||
void Uri::SetPath(const std::string& path)
|
||||
{
|
||||
m_path = path;
|
||||
}
|
||||
}
|
||||
280
src/Utility.cpp
280
src/Utility.cpp
@ -1,280 +0,0 @@
|
||||
#include "Utility.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
void Utility::Delete(void *pointer)
|
||||
{
|
||||
if (pointer == nullptr)
|
||||
return;
|
||||
delete pointer;
|
||||
pointer = nullptr;
|
||||
}
|
||||
|
||||
void Utility::DeleteArray(void *pointer)
|
||||
{
|
||||
if (pointer == nullptr)
|
||||
return;
|
||||
delete[] pointer;
|
||||
pointer = nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> Utility::StringConverter::Split(const std::string & str, const std::string & delimiter)
|
||||
{
|
||||
std::vector<std::string> splited;
|
||||
if (str.empty() && delimiter.empty())
|
||||
return std::vector<std::string>();
|
||||
std::stringstream ss(str);
|
||||
std::string token;
|
||||
while (std::getline(ss, token, delimiter[0]))
|
||||
splited.push_back(token);
|
||||
return splited;
|
||||
}
|
||||
|
||||
const std::vector<byte> &Utility::BitConverter::ToBytes(uint8 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
uint8 Utility::BitConverter::ToUint8(const std::vector<byte> &bytes, uint16 start_index)
|
||||
{
|
||||
return uint8();
|
||||
}
|
||||
|
||||
const std::vector<byte> &Utility::BitConverter::ToBytes(uint16 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
uint16 Utility::BitConverter::ToUint16(const std::vector<byte> &bytes, uint16 start_index)
|
||||
{
|
||||
return uint16();
|
||||
}
|
||||
|
||||
const std::vector<byte> & Utility::BitConverter::ToBytes(uint32 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
uint32 Utility::BitConverter::ToUint32(const std::vector<byte> & bytes, uint16 start_index)
|
||||
{
|
||||
return uint32();
|
||||
}
|
||||
|
||||
const std::vector<byte> & Utility::BitConverter::ToBytes(uint64 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
uint64 Utility::BitConverter::ToUint64(const std::vector<byte> & bytes, uint16 start_index)
|
||||
{
|
||||
return uint64();
|
||||
}
|
||||
|
||||
const std::vector<byte> & Utility::BitConverter::ToBytes(int8 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
int8 Utility::BitConverter::ToInt8(const std::vector<byte> & bytes, uint16 start_index)
|
||||
{
|
||||
return int8();
|
||||
}
|
||||
|
||||
const std::vector<byte> & Utility::BitConverter::ToBytes(int16 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
int16 Utility::BitConverter::ToInt16(const std::vector<byte> & bytes, uint16 start_index)
|
||||
{
|
||||
return int16();
|
||||
}
|
||||
|
||||
const std::vector<byte> & Utility::BitConverter::ToBytes(int32 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
int32 Utility::BitConverter::ToInt32(const std::vector<byte> & bytes, uint16 start_index)
|
||||
{
|
||||
return int32();
|
||||
}
|
||||
|
||||
const std::vector<byte> & Utility::BitConverter::ToBytes(int64 number)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
int64 Utility::BitConverter::ToInt64(const std::vector<byte> & bytes, uint16 start_index)
|
||||
{
|
||||
return int64();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(bool value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(uint8 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(uint16 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(uint32 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(uint64 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(int8 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(int16 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(int32 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(int64 value)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(const std::vector<byte>& bytes)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
uint8 Utility::StringConverter::ToUint8(const std::string & str)
|
||||
{
|
||||
return uint8();
|
||||
}
|
||||
|
||||
uint16 Utility::StringConverter::ToUint16(const std::string & str)
|
||||
{
|
||||
return uint16();
|
||||
}
|
||||
|
||||
uint32 Utility::StringConverter::ToUint32(const std::string & str)
|
||||
{
|
||||
return uint32();
|
||||
}
|
||||
|
||||
uint64 Utility::StringConverter::ToUint64(const std::string & str)
|
||||
{
|
||||
return uint64();
|
||||
}
|
||||
|
||||
int8 Utility::StringConverter::ToInt8(const std::string & str)
|
||||
{
|
||||
return int8();
|
||||
}
|
||||
|
||||
int16 Utility::StringConverter::ToInt16(const std::string & str)
|
||||
{
|
||||
return int16();
|
||||
}
|
||||
|
||||
int32 Utility::StringConverter::ToInt32(const std::string & str)
|
||||
{
|
||||
return int32();
|
||||
}
|
||||
|
||||
int64 Utility::StringConverter::ToInt64(const std::string & str)
|
||||
{
|
||||
return int64();
|
||||
}
|
||||
|
||||
const std::vector<byte>& Utility::StringConverter::ToBytes(const std::string & str)
|
||||
{
|
||||
return std::vector<byte>();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::ToString(const std::vector<byte> & bytes, uint16 start_index, uint16 lenght)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const std::string & Utility::StringConverter::Trim(std::string & str, char ch)
|
||||
{
|
||||
if (str.empty() && ch == 0)
|
||||
return std::string();
|
||||
for (std::string::iterator it = str.begin(); it != str.end(); ++it)
|
||||
{
|
||||
if (*it == ch)
|
||||
str.erase(it);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void Utility::ConfigReader::ReadConfig(const std::string & file_name)
|
||||
{
|
||||
if (file_name.empty())
|
||||
return;
|
||||
std::fstream file;
|
||||
file.open(file_name);
|
||||
if (file.is_open())
|
||||
{
|
||||
longlong file_lenght = file.gcount();
|
||||
char *content = new char[static_cast<uint32>(file_lenght)]();
|
||||
file.read(content, file_lenght);
|
||||
file_content = std::string(content);
|
||||
}
|
||||
}
|
||||
|
||||
void Utility::ConfigReader::ReadNodes()
|
||||
{
|
||||
if (file_content.empty())
|
||||
return;
|
||||
std::stringstream ss(file_content);
|
||||
std::string temp;
|
||||
std::vector<std::string> nodes_lines;
|
||||
while (std::getline(ss, temp, '\n'))
|
||||
{
|
||||
if (temp.substr(0, 2) != "//")
|
||||
nodes_lines.emplace_back(temp);
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = nodes_lines.begin(); it != nodes_lines.end(); ++it)
|
||||
{
|
||||
std::string node_str = Utility::StringConverter::Trim(*it, ' ');
|
||||
std::vector<std::string> node = Utility::StringConverter::Split(node_str, "=");
|
||||
nodes.insert(std::pair<std::string, std::string>(node.at(0), node.at(1)));
|
||||
}
|
||||
}
|
||||
|
||||
const std::string & Utility::ConfigReader::operator[](const std::string &key)
|
||||
{
|
||||
return nodes.at(key);
|
||||
}
|
||||
|
||||
bool Utility::IPUtil::ValidIPV4(const std::string & ip)
|
||||
{
|
||||
std::vector<std::string> splitted_address = Utility::StringConverter::Split(ip, ".");
|
||||
if (splitted_address.size() != 4)
|
||||
return false;
|
||||
uint8 a1 = Utility::StringConverter::ToUint8(splitted_address[0]);
|
||||
uint8 a2 = Utility::StringConverter::ToUint8(splitted_address[1]);
|
||||
uint8 a3 = Utility::StringConverter::ToUint8(splitted_address[2]);
|
||||
uint8 a4 = Utility::StringConverter::ToUint8(splitted_address[3]);
|
||||
|
||||
return a1 != 0 && a2 != 0 && a3 != 0 && a4 != 0 &&
|
||||
a1 != 255 && a2 != 255 && a3 != 255 && a4 != 255;
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
#include "VoidNetClient.hpp"
|
||||
#include "Utility.hpp"
|
||||
|
||||
#include <future>
|
||||
|
||||
bool VoidNetClientAPI::Connect(const std::string &ip, uint16 port)
|
||||
{
|
||||
tcp_client.SetIP(ip);
|
||||
tcp_client.SetPort(port);
|
||||
return tcp_client.Connect();
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::SendMessageToServer(byte tag, byte subject, void *data)
|
||||
{
|
||||
SendMessage(Server, 0, tag, subject, data);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::SendMessageToID(uint16 destination_id, byte tag, byte subject, void *data)
|
||||
{
|
||||
SendMessage(ID, destination_id, tag, subject, data);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::SendMessageToOthers(byte tag, byte subject, void *data)
|
||||
{
|
||||
SendMessage(Others, 0, tag, subject, data);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::SendMessageToAll(byte tag, byte subject, void *data)
|
||||
{
|
||||
SendMessage(All, 0, tag, subject, data);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::SendMessageToAllAndMe(byte tag, byte subject, void *data)
|
||||
{
|
||||
SendMessage(AllAndMe, 0, tag, subject, data);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::SendMessage(byte distribution_mode, uint16 destination_id, byte tag, byte subject, void *data)
|
||||
{
|
||||
NetworkMessage message;
|
||||
message.tag = tag;
|
||||
message.subject = subject;
|
||||
message.data = data;
|
||||
message.distribution_mode = distribution_mode;
|
||||
message.sender = id;
|
||||
message.destination_id = destination_id;
|
||||
if (!IS_HANDSHAKE(message))
|
||||
tcp_client.SendMessage(message);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::Receive()
|
||||
{
|
||||
std::async(std::launch::async, &receive_data);
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::receive_data()
|
||||
{
|
||||
tcp_client.ReceiveMessages();
|
||||
}
|
||||
|
||||
void VoidNetClientAPI::Disconnect()
|
||||
{
|
||||
tcp_client.Shutdown();
|
||||
}
|
||||
Reference in New Issue
Block a user