Add sfml network library. Hopefully this will make net-related coding a breeze :)
Note that as it is not used by anything yet, it has not yet been added as a dependency for any projects git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3184 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
79aa90b876
commit
56398758b0
|
@ -0,0 +1,395 @@
|
||||||
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="SFML_Network"
|
||||||
|
ProjectGUID="{823DDC98-42D5-4A38-88CF-9DC06C788AE4}"
|
||||||
|
RootNamespace="sfml-network"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="131072"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
<Platform
|
||||||
|
Name="x64"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)..\..\Temp\vc2008\$(ProjectName)\$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(SolutionDir)..\..\Temp\vc2008\$(ProjectName)\$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description=""
|
||||||
|
CommandLine=""
|
||||||
|
Outputs=""
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories=""$(ProjectDir)..\..\src";"$(ProjectDir)..\..\include""
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;SFML_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
AdditionalDependencies="ws2_32.lib"
|
||||||
|
OutputFile="$(SolutionDir)..\..\lib\vc2008\$(ProjectName)-s-d.lib"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
CommandLine=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|x64"
|
||||||
|
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="2"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description=""
|
||||||
|
CommandLine=""
|
||||||
|
Outputs=""
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TargetEnvironment="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories=""$(ProjectDir)..\..\src";"$(ProjectDir)..\..\include""
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;SFML_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
AdditionalDependencies="ws2_32.lib"
|
||||||
|
OutputFile="$(SolutionDir)..\..\lib\vc2008\$(ProjectName)-s-d.lib"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
CommandLine=""
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)..\..\Temp\vc2008\$(ProjectName)\$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(SolutionDir)..\..\Temp\vc2008\$(ProjectName)\$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="0"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description=""
|
||||||
|
CommandLine=""
|
||||||
|
Outputs=""
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="3"
|
||||||
|
InlineFunctionExpansion="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
FavorSizeOrSpeed="1"
|
||||||
|
WholeProgramOptimization="false"
|
||||||
|
AdditionalIncludeDirectories=""$(ProjectDir)..\..\src";"$(ProjectDir)..\..\include""
|
||||||
|
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;SFML_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
|
StringPooling="true"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="false"
|
||||||
|
EnableEnhancedInstructionSet="0"
|
||||||
|
FloatingPointModel="2"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="0"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
AdditionalDependencies="ws2_32.lib"
|
||||||
|
OutputFile="$(SolutionDir)..\..\lib\vc2008\$(ProjectName)-s.lib"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|x64"
|
||||||
|
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||||
|
ConfigurationType="4"
|
||||||
|
CharacterSet="2"
|
||||||
|
WholeProgramOptimization="0"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
Description=""
|
||||||
|
CommandLine=""
|
||||||
|
Outputs=""
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
TargetEnvironment="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="3"
|
||||||
|
InlineFunctionExpansion="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
FavorSizeOrSpeed="1"
|
||||||
|
WholeProgramOptimization="false"
|
||||||
|
AdditionalIncludeDirectories=""$(ProjectDir)..\..\src";"$(ProjectDir)..\..\include""
|
||||||
|
PreprocessorDefinitions="NDEBUG;WIN32;_LIB;SFML_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||||
|
StringPooling="true"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
BufferSecurityCheck="false"
|
||||||
|
EnableEnhancedInstructionSet="0"
|
||||||
|
FloatingPointModel="2"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="4"
|
||||||
|
DebugInformationFormat="0"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLibrarianTool"
|
||||||
|
AdditionalDependencies="ws2_32.lib"
|
||||||
|
OutputFile="$(SolutionDir)..\..\lib\vc2008\$(ProjectName)-s.lib"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="Win32"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Win32\SocketHelper.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Win32\SocketHelper.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Ftp.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\Ftp.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Http.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\Http.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\IPAddress.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\IPAddress.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Packet.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Packet.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Selector.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\Selector.inl"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\SelectorBase.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\SelectorBase.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\SocketHelper.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\SocketTCP.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\SocketTCP.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\SocketUDP.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\SocketUDP.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
|
@ -0,0 +1,160 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_CONFIG_HPP
|
||||||
|
#define SFML_CONFIG_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Identify the operating system
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#if defined(_WIN32) || defined(__WIN32__)
|
||||||
|
|
||||||
|
// Windows
|
||||||
|
#define SFML_SYSTEM_WINDOWS
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#ifndef NOMINMAX
|
||||||
|
#define NOMINMAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(linux) || defined(__linux)
|
||||||
|
|
||||||
|
// Linux
|
||||||
|
#define SFML_SYSTEM_LINUX
|
||||||
|
|
||||||
|
#elif defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)
|
||||||
|
|
||||||
|
// MacOS
|
||||||
|
#define SFML_SYSTEM_MACOS
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Unsupported system
|
||||||
|
#error This operating system is not supported by SFML library
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Define a portable debug macro
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
|
||||||
|
#define SFML_DEBUG
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Define portable import / export macros
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#if defined(SFML_SYSTEM_WINDOWS)
|
||||||
|
|
||||||
|
#ifdef SFML_DYNAMIC
|
||||||
|
|
||||||
|
// Windows platforms
|
||||||
|
#ifdef SFML_EXPORTS
|
||||||
|
|
||||||
|
// From DLL side, we must export
|
||||||
|
#define SFML_API __declspec(dllexport)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// From client application side, we must import
|
||||||
|
#define SFML_API __declspec(dllimport)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For Visual C++ compilers, we also need to turn off this annoying C4251 warning.
|
||||||
|
// You can read lots ot different things about it, but the point is the code will
|
||||||
|
// just work fine, and so the simplest way to get rid of this warning is to disable it
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#pragma warning(disable : 4251)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// No specific directive needed for static build
|
||||||
|
#define SFML_API
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Other platforms don't need to define anything
|
||||||
|
#define SFML_API
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Define portable fixed-size types
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
// 8 bits integer types
|
||||||
|
#if UCHAR_MAX == 0xFF
|
||||||
|
typedef signed char Int8;
|
||||||
|
typedef unsigned char Uint8;
|
||||||
|
#else
|
||||||
|
#error No 8 bits integer type for this platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 16 bits integer types
|
||||||
|
#if USHRT_MAX == 0xFFFF
|
||||||
|
typedef signed short Int16;
|
||||||
|
typedef unsigned short Uint16;
|
||||||
|
#elif UINT_MAX == 0xFFFF
|
||||||
|
typedef signed int Int16;
|
||||||
|
typedef unsigned int Uint16;
|
||||||
|
#elif ULONG_MAX == 0xFFFF
|
||||||
|
typedef signed long Int16;
|
||||||
|
typedef unsigned long Uint16;
|
||||||
|
#else
|
||||||
|
#error No 16 bits integer type for this platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 32 bits integer types
|
||||||
|
#if USHRT_MAX == 0xFFFFFFFF
|
||||||
|
typedef signed short Int32;
|
||||||
|
typedef unsigned short Uint32;
|
||||||
|
#elif UINT_MAX == 0xFFFFFFFF
|
||||||
|
typedef signed int Int32;
|
||||||
|
typedef unsigned int Uint32;
|
||||||
|
#elif ULONG_MAX == 0xFFFFFFFF
|
||||||
|
typedef signed long Int32;
|
||||||
|
typedef unsigned long Uint32;
|
||||||
|
#else
|
||||||
|
#error No 32 bits integer type for this platform
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_CONFIG_HPP
|
|
@ -0,0 +1,42 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_NETWORK_HPP
|
||||||
|
#define SFML_NETWORK_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
#include <SFML/Network/Ftp.hpp>
|
||||||
|
#include <SFML/Network/Http.hpp>
|
||||||
|
#include <SFML/Network/IPAddress.hpp>
|
||||||
|
#include <SFML/Network/Packet.hpp>
|
||||||
|
#include <SFML/Network/Selector.hpp>
|
||||||
|
#include <SFML/Network/SocketTCP.hpp>
|
||||||
|
#include <SFML/Network/SocketUDP.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_NETWORK_HPP
|
|
@ -0,0 +1,448 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_FTP_HPP
|
||||||
|
#define SFML_FTP_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
|
#include <SFML/Network/SocketTCP.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class IPAddress;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class provides methods for manipulating the FTP
|
||||||
|
/// protocol (described in RFC 959).
|
||||||
|
/// It provides easy access and transfers to remote
|
||||||
|
/// directories and files on a FTP server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Ftp : NonCopyable
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Enumeration of transfer modes
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum TransferMode
|
||||||
|
{
|
||||||
|
Binary, ///< Binary mode (file is transfered as a sequence of bytes)
|
||||||
|
Ascii, ///< Text mode using ASCII encoding
|
||||||
|
Ebcdic ///< Text mode using EBCDIC encoding
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class wraps a FTP response, which is basically :
|
||||||
|
/// - a status code
|
||||||
|
/// - a message
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Response
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Enumerate all the valid status codes returned in
|
||||||
|
/// a FTP response
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
// 1xx: the requested action is being initiated,
|
||||||
|
// expect another reply before proceeding with a new command
|
||||||
|
RestartMarkerReply = 110, ///< Restart marker reply
|
||||||
|
ServiceReadySoon = 120, ///< Service ready in N minutes
|
||||||
|
DataConnectionAlreadyOpened = 125, ///< Data connection already opened, transfer starting
|
||||||
|
OpeningDataConnection = 150, ///< File status ok, about to open data connection
|
||||||
|
|
||||||
|
// 2xx: the requested action has been successfully completed
|
||||||
|
Ok = 200, ///< Command ok
|
||||||
|
PointlessCommand = 202, ///< Command not implemented
|
||||||
|
SystemStatus = 211, ///< System status, or system help reply
|
||||||
|
DirectoryStatus = 212, ///< Directory status
|
||||||
|
FileStatus = 213, ///< File status
|
||||||
|
HelpMessage = 214, ///< Help message
|
||||||
|
SystemType = 215, ///< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document
|
||||||
|
ServiceReady = 220, ///< Service ready for new user
|
||||||
|
ClosingConnection = 221, ///< Service closing control connection
|
||||||
|
DataConnectionOpened = 225, ///< Data connection open, no transfer in progress
|
||||||
|
ClosingDataConnection = 226, ///< Closing data connection, requested file action successful
|
||||||
|
EnteringPassiveMode = 227, ///< Entering passive mode
|
||||||
|
LoggedIn = 230, ///< User logged in, proceed. Logged out if appropriate
|
||||||
|
FileActionOk = 250, ///< Requested file action ok
|
||||||
|
DirectoryOk = 257, ///< PATHNAME created
|
||||||
|
|
||||||
|
// 3xx: the command has been accepted, but the requested action
|
||||||
|
// is dormant, pending receipt of further information
|
||||||
|
NeedPassword = 331, ///< User name ok, need password
|
||||||
|
NeedAccountToLogIn = 332, ///< Need account for login
|
||||||
|
NeedInformation = 350, ///< Requested file action pending further information
|
||||||
|
|
||||||
|
// 4xx: the command was not accepted and the requested action did not take place,
|
||||||
|
// but the error condition is temporary and the action may be requested again
|
||||||
|
ServiceUnavailable = 421, ///< Service not available, closing control connection
|
||||||
|
DataConnectionUnavailable = 425, ///< Can't open data connection
|
||||||
|
TransferAborted = 426, ///< Connection closed, transfer aborted
|
||||||
|
FileActionAborted = 450, ///< Requested file action not taken
|
||||||
|
LocalError = 451, ///< Requested action aborted, local error in processing
|
||||||
|
InsufficientStorageSpace = 452, ///< Requested action not taken; insufficient storage space in system, file unavailable
|
||||||
|
|
||||||
|
// 5xx: the command was not accepted and
|
||||||
|
// the requested action did not take place
|
||||||
|
CommandUnknown = 500, ///< Syntax error, command unrecognized
|
||||||
|
ParametersUnknown = 501, ///< Syntax error in parameters or arguments
|
||||||
|
CommandNotImplemented = 502, ///< Command not implemented
|
||||||
|
BadCommandSequence = 503, ///< Bad sequence of commands
|
||||||
|
ParameterNotImplemented = 504, ///< Command not implemented for that parameter
|
||||||
|
NotLoggedIn = 530, ///< Not logged in
|
||||||
|
NeedAccountToStore = 532, ///< Need account for storing files
|
||||||
|
FileUnavailable = 550, ///< Requested action not taken, file unavailable
|
||||||
|
PageTypeUnknown = 551, ///< Requested action aborted, page type unknown
|
||||||
|
NotEnoughMemory = 552, ///< Requested file action aborted, exceeded storage allocation
|
||||||
|
FilenameNotAllowed = 553, ///< Requested action not taken, file name not allowed
|
||||||
|
|
||||||
|
// 10xx: SFML custom codes
|
||||||
|
InvalidResponse = 1000, ///< Response is not a valid FTP one
|
||||||
|
ConnectionFailed = 1001, ///< Connection with server failed
|
||||||
|
ConnectionClosed = 1002, ///< Connection with server closed
|
||||||
|
InvalidFile = 1003 ///< Invalid file to upload / download
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
/// \param Code : Response status code (InvalidResponse by default)
|
||||||
|
/// \param Message : Response message (empty by default)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response(Status Code = InvalidResponse, const std::string& Message = "");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Convenience function to check if the response status code
|
||||||
|
/// means a success
|
||||||
|
///
|
||||||
|
/// \return True if status is success (code < 400)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IsOk() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the response status code
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status GetStatus() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the full message contained in the response
|
||||||
|
///
|
||||||
|
/// \return The response message
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& GetMessage() const;
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status myStatus; ///< Status code returned from the server
|
||||||
|
std::string myMessage; ///< Last message received from the server
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Specialization of FTP response returning a directory
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API DirectoryResponse : public Response
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
/// \param Resp : Source response
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
DirectoryResponse(Response Resp);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the directory returned in the response
|
||||||
|
///
|
||||||
|
/// \return Directory name
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& GetDirectory() const;
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::string myDirectory; ///< Directory extracted from the response message
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Specialization of FTP response returning a filename lisiting
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API ListingResponse : public Response
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
/// \param Resp : Source response
|
||||||
|
/// \param Data : Data containing the raw listing
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
ListingResponse(Response Resp, const std::vector<char>& Data);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the number of filenames in the listing
|
||||||
|
///
|
||||||
|
/// \return Total number of filenames
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::size_t GetCount() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the Index-th filename in the directory
|
||||||
|
///
|
||||||
|
/// \param Index : Index of the filename to get
|
||||||
|
///
|
||||||
|
/// \return Index-th filename
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& GetFilename(std::size_t Index) const;
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::vector<std::string> myFilenames; ///< Filenames extracted from the data
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Destructor -- close the connection with the server
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
~Ftp();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Connect to the specified FTP server
|
||||||
|
///
|
||||||
|
/// \param Server : FTP server to connect to
|
||||||
|
/// \param Port : Port used for connection (21 by default, standard FTP port)
|
||||||
|
/// \param Timeout : Maximum time to wait, in seconds (0 by default, means no timeout)
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Connect(const IPAddress& Server, unsigned short Port = 21, float Timeout = 0.f);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Log in using anonymous account
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Login();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Log in using a username and a password
|
||||||
|
///
|
||||||
|
/// \param UserName : User name
|
||||||
|
/// \param Password : Password
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Login(const std::string& UserName, const std::string& Password);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close the connection with FTP server
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Disconnect();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a null command just to prevent from being disconnected
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response KeepAlive();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the current working directory
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
DirectoryResponse GetWorkingDirectory();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the contents of the given directory
|
||||||
|
/// (subdirectories and files)
|
||||||
|
///
|
||||||
|
/// \param Directory : Directory to list ("" by default, the current one)
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
ListingResponse GetDirectoryListing(const std::string& Directory = "");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the current working directory
|
||||||
|
///
|
||||||
|
/// \param Directory : New directory, relative to the current one
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response ChangeDirectory(const std::string& Directory);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Go to the parent directory of the current one
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response ParentDirectory();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Create a new directory
|
||||||
|
///
|
||||||
|
/// \param Name : Name of the directory to create
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response MakeDirectory(const std::string& Name);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove an existing directory
|
||||||
|
///
|
||||||
|
/// \param Name : Name of the directory to remove
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response DeleteDirectory(const std::string& Name);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Rename a file
|
||||||
|
///
|
||||||
|
/// \param File : File to rename
|
||||||
|
/// \param NewName : New name
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response RenameFile(const std::string& File, const std::string& NewName);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove an existing file
|
||||||
|
///
|
||||||
|
/// \param Name : File to remove
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response DeleteFile(const std::string& Name);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Download a file from the server
|
||||||
|
///
|
||||||
|
/// \param DistantFile : Path of the distant file to download
|
||||||
|
/// \param DestPath : Where to put to file on the local computer
|
||||||
|
/// \param Mode : Transfer mode (binary by default)
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Download(const std::string& DistantFile, const std::string& DestPath, TransferMode Mode = Binary);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Upload a file to the server
|
||||||
|
///
|
||||||
|
/// \param LocalFile : Path of the local file to upload
|
||||||
|
/// \param DestPath : Where to put to file on the server
|
||||||
|
/// \param Mode : Transfer mode (binary by default)
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Upload(const std::string& LocalFile, const std::string& DestPath, TransferMode Mode = Binary);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a command to the FTP server
|
||||||
|
///
|
||||||
|
/// \param Command : Command to send
|
||||||
|
/// \param Parameter : Command parameter ("" by default)
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response SendCommand(const std::string& Command, const std::string& Parameter = "");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive a response from the server
|
||||||
|
/// (usually after a command has been sent)
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response GetResponse();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Utility class for exchanging datas with the server
|
||||||
|
/// on the data channel
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class DataChannel;
|
||||||
|
|
||||||
|
friend class DataChannel;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTCP myCommandSocket; ///< Socket holding the control connection with the server
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_FTP_HPP
|
|
@ -0,0 +1,339 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_HTTP_HPP
|
||||||
|
#define SFML_HTTP_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
|
#include <SFML/Network/IPAddress.hpp>
|
||||||
|
#include <SFML/Network/SocketTCP.hpp>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class provides methods for manipulating the HTTP
|
||||||
|
/// protocol (described in RFC 1945).
|
||||||
|
/// It can connect to a website, get its files, send requests, etc.
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Http : NonCopyable
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class wraps an HTTP request, which is basically :
|
||||||
|
/// - a header with a method, a target URI, and a set of field/value pairs
|
||||||
|
/// - an optional body (for POST requests)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Request
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Enumerate the available HTTP methods for a request
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum Method
|
||||||
|
{
|
||||||
|
Get, ///< Request in get mode, standard method to retrieve a page
|
||||||
|
Post, ///< Request in post mode, usually to send data to a page
|
||||||
|
Head ///< Request a page's header only
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
/// \param RequestMethod : Method to use for the request (Get by default)
|
||||||
|
/// \param URI : Target URI ("/" by default -- index page)
|
||||||
|
/// \param Body : Content of the request's body (empty by default)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Request(Method RequestMethod = Get, const std::string& URI = "/", const std::string& Body = "");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the value of a field; the field is added if it doesn't exist
|
||||||
|
///
|
||||||
|
/// \param Field : Name of the field to set (case-insensitive)
|
||||||
|
/// \param Value : Value of the field
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetField(const std::string& Field, const std::string& Value);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the request method.
|
||||||
|
/// This parameter is Http::Request::Get by default
|
||||||
|
///
|
||||||
|
/// \param RequestMethod : Method to use for the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetMethod(Method RequestMethod);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the target URI of the request.
|
||||||
|
/// This parameter is "/" by default
|
||||||
|
///
|
||||||
|
/// \param URI : URI to request, local to the host
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetURI(const std::string& URI);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the HTTP version of the request.
|
||||||
|
/// This parameter is 1.0 by default
|
||||||
|
///
|
||||||
|
/// \param Major : Major version number
|
||||||
|
/// \param Minor : Minor version number
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetHttpVersion(unsigned int Major, unsigned int Minor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the body of the request. This parameter is optional and
|
||||||
|
/// makes sense only for POST requests.
|
||||||
|
/// This parameter is empty by default
|
||||||
|
///
|
||||||
|
/// \param Body : Content of the request body
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetBody(const std::string& Body);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
friend class Http;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the string representation of the request header
|
||||||
|
///
|
||||||
|
/// \return String containing the request
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the given field has been defined
|
||||||
|
///
|
||||||
|
/// \param Field : Name of the field to check (case-insensitive)
|
||||||
|
///
|
||||||
|
/// \return True if the field exists
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool HasField(const std::string& Field) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Types
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
typedef std::map<std::string, std::string> FieldTable;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
FieldTable myFields; ///< Fields of the header
|
||||||
|
Method myMethod; ///< Method to use for the request
|
||||||
|
std::string myURI; ///< Target URI of the request
|
||||||
|
unsigned int myMajorVersion; ///< Major HTTP version
|
||||||
|
unsigned int myMinorVersion; ///< Minor HTTP version
|
||||||
|
std::string myBody; ///< Body of the request
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class wraps an HTTP response, which is basically :
|
||||||
|
/// - a header with a status code and a set of field/value pairs
|
||||||
|
/// - a body (the content of the requested resource)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Response
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Enumerate all the valid status codes returned in
|
||||||
|
/// a HTTP response
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
// 2xx: success
|
||||||
|
Ok = 200, ///< Most common code returned when operation was successful
|
||||||
|
Created = 201, ///< The resource has successfully been created
|
||||||
|
Accepted = 202, ///< The request has been accepted, but will be processed later by the server
|
||||||
|
NoContent = 204, ///< Sent when the server didn't send any data in return
|
||||||
|
|
||||||
|
// 3xx: redirection
|
||||||
|
MultipleChoices = 300, ///< The requested page can be accessed from several locations
|
||||||
|
MovedPermanently = 301, ///< The requested page has permanently moved to a new location
|
||||||
|
MovedTemporarily = 302, ///< The requested page has temporarily moved to a new location
|
||||||
|
NotModified = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed
|
||||||
|
|
||||||
|
// 4xx: client error
|
||||||
|
BadRequest = 400, ///< The server couldn't understand the request (syntax error)
|
||||||
|
Unauthorized = 401, ///< The requested page needs an authentification to be accessed
|
||||||
|
Forbidden = 403, ///< The requested page cannot be accessed at all, even with authentification
|
||||||
|
NotFound = 404, ///< The requested page doesn't exist
|
||||||
|
|
||||||
|
// 5xx: server error
|
||||||
|
InternalServerError = 500, ///< The server encountered an unexpected error
|
||||||
|
NotImplemented = 501, ///< The server doesn't implement a requested feature
|
||||||
|
BadGateway = 502, ///< The gateway server has received an error from the source server
|
||||||
|
ServiceNotAvailable = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...)
|
||||||
|
|
||||||
|
// 10xx: SFML custom codes
|
||||||
|
InvalidResponse = 1000, ///< Response is not a valid HTTP one
|
||||||
|
ConnectionFailed = 1001 ///< Connection with server failed
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the value of a field
|
||||||
|
///
|
||||||
|
/// \param Field : Name of the field to get (case-insensitive)
|
||||||
|
///
|
||||||
|
/// \return Value of the field, or empty string if not found
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& GetField(const std::string& Field) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the header's status code
|
||||||
|
///
|
||||||
|
/// \return Header's status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status GetStatus() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the major HTTP version number of the response
|
||||||
|
///
|
||||||
|
/// \return Major version number
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int GetMajorHttpVersion() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the major HTTP version number of the response
|
||||||
|
///
|
||||||
|
/// \return Major version number
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int GetMinorHttpVersion() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the body of the response. The body can contain :
|
||||||
|
/// - the requested page (for GET requests)
|
||||||
|
/// - a response from the server (for POST requests)
|
||||||
|
/// - nothing (for HEAD requests)
|
||||||
|
/// - an error message (in case of an error)
|
||||||
|
///
|
||||||
|
/// \return The response body
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& GetBody() const;
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
friend class Http;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the header from a response string
|
||||||
|
///
|
||||||
|
/// \param Data : Content of the response's header to parse
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void FromString(const std::string& Data);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Types
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
typedef std::map<std::string, std::string> FieldTable;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
FieldTable myFields; ///< Fields of the header
|
||||||
|
Status myStatus; ///< Status code
|
||||||
|
unsigned int myMajorVersion; ///< Major HTTP version
|
||||||
|
unsigned int myMinorVersion; ///< Minor HTTP version
|
||||||
|
std::string myBody; ///< Body of the response
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the Http instance with the target host
|
||||||
|
///
|
||||||
|
/// \param Host : Web server to connect to
|
||||||
|
/// \param Port : Port to use for connection (0 by default -- use the standard port of the protocol used)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http(const std::string& Host, unsigned short Port = 0);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the target host
|
||||||
|
///
|
||||||
|
/// \param Host : Web server to connect to
|
||||||
|
/// \param Port : Port to use for connection (0 by default -- use the standard port of the protocol used)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetHost(const std::string& Host, unsigned short Port = 0);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a HTTP request and return the server's response.
|
||||||
|
/// You must be connected to a host before sending requests.
|
||||||
|
/// Any missing mandatory header field will be added with an appropriate value.
|
||||||
|
/// Warning : this function waits for the server's response and may
|
||||||
|
/// not return instantly; use a thread if you don't want to block your
|
||||||
|
/// application.
|
||||||
|
///
|
||||||
|
/// \param Req : Request to send
|
||||||
|
///
|
||||||
|
/// \return Server's response
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response SendRequest(const Request& Req);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTCP myConnection; ///< Connection to the host
|
||||||
|
IPAddress myHost; ///< Web host address
|
||||||
|
std::string myHostName; ///< Web host name
|
||||||
|
unsigned short myPort; ///< Port used for connection with host
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_HTTP_HPP
|
|
@ -0,0 +1,229 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_IPADDRESS_HPP
|
||||||
|
#define SFML_IPADDRESS_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
#include <istream>
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// IPAddress provides easy manipulation of IP v4 addresses
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API IPAddress
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor -- constructs an invalid address
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from a string
|
||||||
|
///
|
||||||
|
/// \param Address : IP address ("xxx.xxx.xxx.xxx") or network name
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress(const std::string& Address);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from a C-style string ;
|
||||||
|
/// Needed for implicit conversions from literal strings to IPAddress to work
|
||||||
|
///
|
||||||
|
/// \param Address : IP address ("xxx.xxx.xxx.xxx") or network name
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress(const char* Address);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from 4 bytes
|
||||||
|
///
|
||||||
|
/// \param Byte0 : First byte of the address
|
||||||
|
/// \param Byte1 : Second byte of the address
|
||||||
|
/// \param Byte2 : Third byte of the address
|
||||||
|
/// \param Byte3 : Fourth byte of the address
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress(Uint8 Byte0, Uint8 Byte1, Uint8 Byte2, Uint8 Byte3);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from a 32-bits integer
|
||||||
|
///
|
||||||
|
/// \param Address : 4 bytes of the address packed into a 32-bits integer
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress(Uint32 Address);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Tell if the address is a valid one
|
||||||
|
///
|
||||||
|
/// \return True if address has a valid syntax
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get a string representation of the address
|
||||||
|
///
|
||||||
|
/// \return String representation of the IP address ("xxx.xxx.xxx.xxx")
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get an integer representation of the address
|
||||||
|
///
|
||||||
|
/// \return 32-bits integer containing the 4 bytes of the address, in system endianness
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Uint32 ToInteger() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the computer's local IP address (from the LAN point of view)
|
||||||
|
///
|
||||||
|
/// \return Local IP address
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static IPAddress GetLocalAddress();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the computer's public IP address (from the web point of view).
|
||||||
|
/// The only way to get a public address is to ask it to a
|
||||||
|
/// distant website ; as a consequence, this function may be
|
||||||
|
/// very slow -- use it as few as possible !
|
||||||
|
///
|
||||||
|
/// \return Public IP address
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static IPAddress GetPublicAddress();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator ==
|
||||||
|
///
|
||||||
|
/// \param Other : Address to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this == Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator ==(const IPAddress& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator !=
|
||||||
|
///
|
||||||
|
/// \param Other : Address to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this != Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator !=(const IPAddress& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <
|
||||||
|
///
|
||||||
|
/// \param Other : Address to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this < Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator <(const IPAddress& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator >
|
||||||
|
///
|
||||||
|
/// \param Other : Address to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this > Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator >(const IPAddress& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <=
|
||||||
|
///
|
||||||
|
/// \param Other : Address to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this <= Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator <=(const IPAddress& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator >=
|
||||||
|
///
|
||||||
|
/// \param Other : Address to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this >= Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator >=(const IPAddress& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Static member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static const IPAddress LocalHost; ///< Local host address (to connect to the same computer)
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Uint32 myAddress; ///< Address stored as an unsigned 32 bits integer
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator >> overload to extract an address from an input stream
|
||||||
|
///
|
||||||
|
/// \param Stream : Input stream
|
||||||
|
/// \param Address : Address to extract
|
||||||
|
///
|
||||||
|
/// \return Reference to the input stream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_API std::istream& operator >>(std::istream& Stream, IPAddress& Address);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator << overload to print an address to an output stream
|
||||||
|
///
|
||||||
|
/// \param Stream : Output stream
|
||||||
|
/// \param Address : Address to print
|
||||||
|
///
|
||||||
|
/// \return Reference to the output stream
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SFML_API std::ostream& operator <<(std::ostream& Stream, const IPAddress& Address);
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_IPADDRESS_HPP
|
|
@ -0,0 +1,187 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_PACKET_HPP
|
||||||
|
#define SFML_PACKET_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Packet wraps data to send / to receive through the network
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Packet
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Virtual destructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual ~Packet();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Append data to the end of the packet
|
||||||
|
///
|
||||||
|
/// \param Data : Pointer to the bytes to append
|
||||||
|
/// \param SizeInBytes : Number of bytes to append
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Append(const void* Data, std::size_t SizeInBytes);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Clear the packet data
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get a pointer to the data contained in the packet
|
||||||
|
/// Warning : the returned pointer may be invalid after you
|
||||||
|
/// append data to the packet
|
||||||
|
///
|
||||||
|
/// \return Pointer to the data
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const char* GetData() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the size of the data contained in the packet
|
||||||
|
///
|
||||||
|
/// \return Data size, in bytes
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::size_t GetDataSize() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Tell if the reading position has reached the end of the packet
|
||||||
|
///
|
||||||
|
/// \return True if all data have been read into the packet
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool EndOfPacket() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Return the validity of packet
|
||||||
|
///
|
||||||
|
/// \return True if last data extraction from packet was successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator >> overloads to extract data from the packet
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet& operator >>(bool& Data);
|
||||||
|
Packet& operator >>(Int8& Data);
|
||||||
|
Packet& operator >>(Uint8& Data);
|
||||||
|
Packet& operator >>(Int16& Data);
|
||||||
|
Packet& operator >>(Uint16& Data);
|
||||||
|
Packet& operator >>(Int32& Data);
|
||||||
|
Packet& operator >>(Uint32& Data);
|
||||||
|
Packet& operator >>(float& Data);
|
||||||
|
Packet& operator >>(double& Data);
|
||||||
|
Packet& operator >>(char* Data);
|
||||||
|
Packet& operator >>(std::string& Data);
|
||||||
|
Packet& operator >>(wchar_t* Data);
|
||||||
|
Packet& operator >>(std::wstring& Data);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator << overloads to put data into the packet
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet& operator <<(bool Data);
|
||||||
|
Packet& operator <<(Int8 Data);
|
||||||
|
Packet& operator <<(Uint8 Data);
|
||||||
|
Packet& operator <<(Int16 Data);
|
||||||
|
Packet& operator <<(Uint16 Data);
|
||||||
|
Packet& operator <<(Int32 Data);
|
||||||
|
Packet& operator <<(Uint32 Data);
|
||||||
|
Packet& operator <<(float Data);
|
||||||
|
Packet& operator <<(double Data);
|
||||||
|
Packet& operator <<(const char* Data);
|
||||||
|
Packet& operator <<(const std::string& Data);
|
||||||
|
Packet& operator <<(const wchar_t* Data);
|
||||||
|
Packet& operator <<(const std::wstring& Data);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
friend class SocketTCP;
|
||||||
|
friend class SocketUDP;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the packet can extract a given size of bytes
|
||||||
|
///
|
||||||
|
/// \param Size : Size to check
|
||||||
|
///
|
||||||
|
/// \return True if Size bytes can be read from the packet's data
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool CheckSize(std::size_t Size);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Called before the packet is sent to the network
|
||||||
|
///
|
||||||
|
/// \param DataSize : Variable to fill with the size of data to send
|
||||||
|
///
|
||||||
|
/// \return Pointer to the array of bytes to send
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual const char* OnSend(std::size_t& DataSize);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Called after the packet has been received from the network
|
||||||
|
///
|
||||||
|
/// \param Data : Pointer to the array of received bytes
|
||||||
|
/// \param DataSize : Size of the array of bytes
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void OnReceive(const char* Data, std::size_t DataSize);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::vector<char> myData; ///< Data stored in the packet
|
||||||
|
std::size_t myReadPos; ///< Current reading position in the packet
|
||||||
|
bool myIsValid; ///< Reading state of the packet
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_PACKET_HPP
|
|
@ -0,0 +1,116 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SELECTOR_HPP
|
||||||
|
#define SFML_SELECTOR_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketUDP.hpp>
|
||||||
|
#include <SFML/Network/SocketTCP.hpp>
|
||||||
|
#include <SFML/Network/SelectorBase.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Selector allow reading from multiple sockets
|
||||||
|
/// without blocking. It's a kind of multiplexer
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename Type>
|
||||||
|
class Selector : private SelectorBase
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Add a socket to watch
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to add
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Add(Type Socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove a socket
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to remove
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Remove(Type Socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove all sockets
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait and collect sockets which are ready for reading.
|
||||||
|
/// This functions will return either when at least one socket
|
||||||
|
/// is ready, or when the given time is out
|
||||||
|
///
|
||||||
|
/// \param Timeout : Timeout, in seconds (0 by default : no timeout)
|
||||||
|
///
|
||||||
|
/// \return Number of sockets ready to be read
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int Wait(float Timeout = 0.f);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// After a call to Wait(), get the Index-th socket which is
|
||||||
|
/// ready for reading. The total number of sockets ready
|
||||||
|
/// is the integer returned by the previous call to Wait()
|
||||||
|
///
|
||||||
|
/// \param Index : Index of the socket to get
|
||||||
|
///
|
||||||
|
/// \return The Index-th socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Type GetSocketReady(unsigned int Index);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Types
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
typedef std::map<SocketHelper::SocketType, Type> SocketTable;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTable mySockets; ///< Table matching the SFML socket instances with their low-level handles
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <SFML/Network/Selector.inl>
|
||||||
|
|
||||||
|
// Let's define the two only valid types of Selector
|
||||||
|
typedef Selector<SocketUDP> SelectorUDP;
|
||||||
|
typedef Selector<SocketTCP> SelectorTCP;
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SELECTOR_HPP
|
|
@ -0,0 +1,97 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Add a socket to watch
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename Type>
|
||||||
|
void Selector<Type>::Add(Type Socket)
|
||||||
|
{
|
||||||
|
if (Socket.IsValid())
|
||||||
|
{
|
||||||
|
SelectorBase::Add(Socket.mySocket);
|
||||||
|
mySockets[Socket.mySocket] = Socket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove a socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename Type>
|
||||||
|
void Selector<Type>::Remove(Type Socket)
|
||||||
|
{
|
||||||
|
typename SocketTable::iterator It = mySockets.find(Socket.mySocket);
|
||||||
|
if (It != mySockets.end())
|
||||||
|
{
|
||||||
|
SelectorBase::Remove(Socket.mySocket);
|
||||||
|
mySockets.erase(It);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove all sockets
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename Type>
|
||||||
|
void Selector<Type>::Clear()
|
||||||
|
{
|
||||||
|
SelectorBase::Clear();
|
||||||
|
mySockets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait and collect sockets which are ready for reading.
|
||||||
|
/// This functions will return either when at least one socket
|
||||||
|
/// is ready, or when the given time is out
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename Type>
|
||||||
|
unsigned int Selector<Type>::Wait(float Timeout)
|
||||||
|
{
|
||||||
|
// No socket in the selector : return 0
|
||||||
|
if (mySockets.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return SelectorBase::Wait(Timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// After a call to Wait(), get the Index-th socket which is
|
||||||
|
/// ready for reading. The total number of sockets ready
|
||||||
|
/// is the integer returned by the previous call to Wait()
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
template <typename Type>
|
||||||
|
Type Selector<Type>::GetSocketReady(unsigned int Index)
|
||||||
|
{
|
||||||
|
SocketHelper::SocketType Socket = SelectorBase::GetSocketReady(Index);
|
||||||
|
|
||||||
|
typename SocketTable::const_iterator It = mySockets.find(Socket);
|
||||||
|
if (It != mySockets.end())
|
||||||
|
return It->second;
|
||||||
|
else
|
||||||
|
return Type(Socket);
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SELECTORBASE_HPP
|
||||||
|
#define SFML_SELECTORBASE_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Private base class for selectors.
|
||||||
|
/// As Selector is a template class, this base is needed so that
|
||||||
|
/// every system call get compiled in SFML (not inlined)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API SelectorBase
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SelectorBase();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Add a socket to watch
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to add
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Add(SocketHelper::SocketType Socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove a socket
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to remove
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Remove(SocketHelper::SocketType Socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove all sockets
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait and collect sockets which are ready for reading.
|
||||||
|
/// This functions will return either when at least one socket
|
||||||
|
/// is ready, or when the given time is out
|
||||||
|
///
|
||||||
|
/// \param Timeout : Timeout, in seconds (0 by default : no timeout)
|
||||||
|
///
|
||||||
|
/// \return Number of sockets ready to be read
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int Wait(float Timeout = 0.f);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// After a call to Wait(), get the Index-th socket which is
|
||||||
|
/// ready for reading. The total number of sockets ready
|
||||||
|
/// is the integer returned by the previous call to Wait()
|
||||||
|
///
|
||||||
|
/// \param Index : Index of the socket to get
|
||||||
|
///
|
||||||
|
/// \return The Index-th socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHelper::SocketType GetSocketReady(unsigned int Index);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
fd_set mySet; ///< Set of socket to watch
|
||||||
|
fd_set mySetReady; ///< Set of socket which are ready for reading
|
||||||
|
int myMaxSocket; ///< Maximum socket index
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SELECTORBASE_HPP
|
|
@ -0,0 +1,64 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SOCKETHELPER_HPP
|
||||||
|
#define SFML_SOCKETHELPER_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
namespace Socket
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Enumeration of status returned by socket functions
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
Done, ///< The socket has sent / received the data
|
||||||
|
NotReady, ///< The socket is not ready to send / receive data yet
|
||||||
|
Disconnected, ///< The TCP socket has been disconnected
|
||||||
|
Error ///< An unexpected error happened
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SFML_SYSTEM_WINDOWS
|
||||||
|
|
||||||
|
#include <SFML/Network/Win32/SocketHelper.hpp>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <SFML/Network/Unix/SocketHelper.hpp>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETHELPER_HPP
|
|
@ -0,0 +1,225 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SOCKETTCP_HPP
|
||||||
|
#define SFML_SOCKETTCP_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class Packet;
|
||||||
|
class IPAddress;
|
||||||
|
template <typename> class Selector;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// SocketTCP wraps a socket using TCP protocol to
|
||||||
|
/// send data safely (but a bit slower)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API SocketTCP
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTCP();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the blocking state of the socket.
|
||||||
|
/// The default behaviour of a socket is blocking
|
||||||
|
///
|
||||||
|
/// \param Blocking : Pass true to set the socket as blocking, or false for non-blocking
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetBlocking(bool Blocking);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Connect to another computer on a specified port
|
||||||
|
///
|
||||||
|
/// \param Port : Port to use for transfers (warning : ports < 1024 are reserved)
|
||||||
|
/// \param HostAddress : IP Address of the host to connect to
|
||||||
|
/// \param Timeout : Maximum time to wait, in seconds (0 by default : no timeout) (this parameter is ignored for non-blocking sockets)
|
||||||
|
///
|
||||||
|
/// \return True if operation has been successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout = 0.f);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Listen to a specified port for incoming data or connections
|
||||||
|
///
|
||||||
|
/// \param Port : Port to listen to
|
||||||
|
///
|
||||||
|
/// \return True if operation has been successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Listen(unsigned short Port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait for a connection (must be listening to a port).
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
///
|
||||||
|
/// \param Connected : Socket containing the connection with the connected client
|
||||||
|
/// \param Address : Pointer to an address to fill with client infos (NULL by default)
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Accept(SocketTCP& Connected, IPAddress* Address = NULL);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send an array of bytes to the host (must be connected first)
|
||||||
|
///
|
||||||
|
/// \param Data : Pointer to the bytes to send
|
||||||
|
/// \param Size : Number of bytes to send
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Send(const char* Data, std::size_t Size);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive an array of bytes from the host (must be connected first).
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
///
|
||||||
|
/// \param Data : Pointer to a byte array to fill (make sure it is big enough)
|
||||||
|
/// \param MaxSize : Maximum number of bytes to read
|
||||||
|
/// \param SizeReceived : Number of bytes received
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a packet of data to the host (must be connected first)
|
||||||
|
///
|
||||||
|
/// \param PacketToSend : Packet to send
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Send(Packet& PacketToSend);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive a packet from the host (must be connected first).
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
///
|
||||||
|
/// \param PacketToReceive : Packet to fill with received data
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Receive(Packet& PacketToReceive);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close the socket
|
||||||
|
///
|
||||||
|
/// \return True if operation has been successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Close();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the socket is in a valid state ; this function
|
||||||
|
/// can be called any time to check if the socket is OK
|
||||||
|
///
|
||||||
|
/// \return True if the socket is valid
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator ==
|
||||||
|
///
|
||||||
|
/// \param Other : Socket to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this == Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator ==(const SocketTCP& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator !=
|
||||||
|
///
|
||||||
|
/// \param Other : Socket to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this != Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator !=(const SocketTCP& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <.
|
||||||
|
/// Provided for compatibility with standard containers, as
|
||||||
|
/// comparing two sockets doesn't make much sense...
|
||||||
|
///
|
||||||
|
/// \param Other : Socket to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this < Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator <(const SocketTCP& Other) const;
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
friend class Selector<SocketTCP>;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the socket from a socket descriptor
|
||||||
|
/// (for internal use only)
|
||||||
|
///
|
||||||
|
/// \param Descriptor : Socket descriptor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTCP(SocketHelper::SocketType Descriptor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Create the socket
|
||||||
|
///
|
||||||
|
/// \param Descriptor : System socket descriptor to use (0 by default -- create a new socket)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Create(SocketHelper::SocketType Descriptor = 0);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHelper::SocketType mySocket; ///< Socket descriptor
|
||||||
|
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any (in non-blocking mode)
|
||||||
|
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any (in non-blocking mode)
|
||||||
|
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETTCP_HPP
|
|
@ -0,0 +1,224 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SOCKETUDP_HPP
|
||||||
|
#define SFML_SOCKETUDP_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class Packet;
|
||||||
|
class IPAddress;
|
||||||
|
template <typename> class Selector;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// SocketUDP wraps a socket using UDP protocol to
|
||||||
|
/// send data fastly (but with less safety)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API SocketUDP
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketUDP();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the blocking state of the socket.
|
||||||
|
/// The default behaviour of a socket is blocking
|
||||||
|
///
|
||||||
|
/// \param Blocking : Pass true to set the socket as blocking, or false for non-blocking
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetBlocking(bool Blocking);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Bind the socket to a specific port
|
||||||
|
///
|
||||||
|
/// \param Port : Port to bind the socket to
|
||||||
|
///
|
||||||
|
/// \return True if operation has been successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Bind(unsigned short Port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Unbind the socket from its previous port, if any
|
||||||
|
///
|
||||||
|
/// \return True if operation has been successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Unbind();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send an array of bytes
|
||||||
|
///
|
||||||
|
/// \param Data : Pointer to the bytes to send
|
||||||
|
/// \param Size : Number of bytes to send
|
||||||
|
/// \param Address : Address of the computer to send the packet to
|
||||||
|
/// \param Port : Port to send the data to
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Send(const char* Data, std::size_t Size, const IPAddress& Address, unsigned short Port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive an array of bytes.
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
///
|
||||||
|
/// \param Data : Pointer to a byte array to fill (make sure it is big enough)
|
||||||
|
/// \param MaxSize : Maximum number of bytes to read
|
||||||
|
/// \param SizeReceived : Number of bytes received
|
||||||
|
/// \param Address : Address of the computer which sent the data
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived, IPAddress& Address);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a packet of data
|
||||||
|
///
|
||||||
|
/// \param PacketToSend : Packet to send
|
||||||
|
/// \param Address : Address of the computer to send the packet to
|
||||||
|
/// \param Port : Port to send the data to
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Send(Packet& PacketToSend, const IPAddress& Address, unsigned short Port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive a packet.
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
///
|
||||||
|
/// \param PacketToReceive : Packet to fill with received data
|
||||||
|
/// \param Address : Address of the computer which sent the packet
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status Receive(Packet& PacketToReceive, IPAddress& Address);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close the socket
|
||||||
|
///
|
||||||
|
/// \return True if operation has been successful
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Close();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the socket is in a valid state ; this function
|
||||||
|
/// can be called any time to check if the socket is OK
|
||||||
|
///
|
||||||
|
/// \return True if the socket is valid
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port the socket is currently bound to
|
||||||
|
///
|
||||||
|
/// \return Current port (0 means the socket is not bound)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short GetPort() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator ==
|
||||||
|
///
|
||||||
|
/// \param Other : Socket to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this == Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator ==(const SocketUDP& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator !=
|
||||||
|
///
|
||||||
|
/// \param Other : Socket to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this != Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator !=(const SocketUDP& Other) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <.
|
||||||
|
/// Provided for compatibility with standard containers, as
|
||||||
|
/// comparing two sockets doesn't make much sense...
|
||||||
|
///
|
||||||
|
/// \param Other : Socket to compare
|
||||||
|
///
|
||||||
|
/// \return True if *this < Other
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool operator <(const SocketUDP& Other) const;
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
friend class Selector<SocketUDP>;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the socket from a socket descriptor
|
||||||
|
/// (for internal use only)
|
||||||
|
///
|
||||||
|
/// \param Descriptor : Socket descriptor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketUDP(SocketHelper::SocketType Descriptor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Create the socket
|
||||||
|
///
|
||||||
|
/// \param Descriptor : System socket descriptor to use (0 by default -- create a new socket)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Create(SocketHelper::SocketType Descriptor = 0);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHelper::SocketType mySocket; ///< Socket identifier
|
||||||
|
unsigned short myPort; ///< Port to which the socket is bound
|
||||||
|
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any (in non-blocking mode)
|
||||||
|
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any (in non-blocking mode)
|
||||||
|
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETUDP_HPP
|
|
@ -0,0 +1,45 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SOCKETS_HPP
|
||||||
|
#define SFML_SOCKETS_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SFML_SYSTEM_WINDOWS
|
||||||
|
|
||||||
|
#include <SFML/Network/Win32/Sockets.hpp>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <SFML/Network/Unix/Sockets.hpp>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETS_HPP
|
|
@ -0,0 +1,96 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SOCKETHELPERUNIX_HPP
|
||||||
|
#define SFML_SOCKETHELPERUNIX_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class defines helper functions to do all the
|
||||||
|
/// non-portable socket stuff. This class is meant for internal
|
||||||
|
/// use only
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API SocketHelper
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Define some socket types
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
typedef int SocketType;
|
||||||
|
typedef socklen_t LengthType;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Return the value of the invalid socket
|
||||||
|
///
|
||||||
|
/// \return Unique value of the invalid socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static SocketType InvalidSocket();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close / destroy a socket
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to close
|
||||||
|
///
|
||||||
|
/// \return True on success
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static bool Close(SocketType Socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set a socket as blocking or non-blocking
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to modify
|
||||||
|
/// \param Block : New blocking state of the socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void SetBlocking(SocketType Socket, bool Block);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the last socket error status
|
||||||
|
///
|
||||||
|
/// \return Status corresponding to the last socket error
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static Socket::Status GetErrorStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETHELPERUNIX_HPP
|
|
@ -0,0 +1,90 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SOCKETHELPERWIN32_HPP
|
||||||
|
#define SFML_SOCKETHELPERWIN32_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// This class defines helper functions to do all the
|
||||||
|
/// non-portable socket stuff. This class is meant for internal
|
||||||
|
/// use only
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API SocketHelper
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Define some socket types
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
typedef SOCKET SocketType;
|
||||||
|
typedef int LengthType;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Return the value of the invalid socket
|
||||||
|
///
|
||||||
|
/// \return Unique value of the invalid socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static SocketType InvalidSocket();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close / destroy a socket
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to close
|
||||||
|
///
|
||||||
|
/// \return True on success
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static bool Close(SocketType Socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set a socket as blocking or non-blocking
|
||||||
|
///
|
||||||
|
/// \param Socket : Socket to modify
|
||||||
|
/// \param Block : New blocking state of the socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void SetBlocking(SocketType Socket, bool Block);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the last socket error status
|
||||||
|
///
|
||||||
|
/// \return Status corresponding to the last socket error
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static Socket::Status GetErrorStatus();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETHELPERWIN32_HPP
|
|
@ -0,0 +1,43 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_SYSTEM_HPP
|
||||||
|
#define SFML_SYSTEM_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
//#include <SFML/System/Clock.hpp>
|
||||||
|
//#include <SFML/System/Lock.hpp>
|
||||||
|
//#include <SFML/System/Mutex.hpp>
|
||||||
|
//#include <SFML/System/Randomizer.hpp>
|
||||||
|
//#include <SFML/System/Sleep.hpp>
|
||||||
|
//#include <SFML/System/Thread.hpp>
|
||||||
|
//#include <SFML/System/Unicode.hpp>
|
||||||
|
//#include <SFML/System/Vector2.hpp>
|
||||||
|
//#include <SFML/System/Vector3.hpp>
|
||||||
|
|
||||||
|
#endif // SFML_SYSTEM_HPP
|
|
@ -0,0 +1,70 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SFML_NONCOPYABLE_HPP
|
||||||
|
#define SFML_NONCOPYABLE_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Utility base class to easily declare non-copyable classes.
|
||||||
|
/// Just inherit from NonCopyable to get a non-copyable class
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct SFML_API NonCopyable
|
||||||
|
{
|
||||||
|
protected :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// The default constructor won't be generated, so provide it
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
NonCopyable() {}
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Copy constructor : declare it private and don't implement
|
||||||
|
/// it to prevent from calling it
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
NonCopyable(const NonCopyable&);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Assignment operator : declare it private and don't implement
|
||||||
|
/// it to prevent from calling it
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
NonCopyable& operator =(const NonCopyable&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_NONCOPYABLE_HPP
|
|
@ -0,0 +1,709 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Ftp.hpp>
|
||||||
|
#include <SFML/Network/IPAddress.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Utility class for exchanging stuff with the server
|
||||||
|
// on the data channel
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class Ftp::DataChannel : NonCopyable
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
DataChannel(Ftp& Owner);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Destructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
~DataChannel();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Open the data channel using the specified mode and port
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Open(Ftp::TransferMode Mode);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Send data on the data channel
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Send(const std::vector<char>& Data);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Receive data on the data channel until it is closed
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Receive(std::vector<char>& Data);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp& myFtp; ///< Reference to the owner Ftp instance
|
||||||
|
SocketTCP myDataSocket; ///< Socket used for data transfers
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response::Response(Status Code, const std::string& Message) :
|
||||||
|
myStatus (Code),
|
||||||
|
myMessage(Message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Convenience function to check if the response status code
|
||||||
|
/// means a success
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Ftp::Response::IsOk() const
|
||||||
|
{
|
||||||
|
return myStatus < 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the response status code
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response::Status Ftp::Response::GetStatus() const
|
||||||
|
{
|
||||||
|
return myStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the full message contained in the response
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& Ftp::Response::GetMessage() const
|
||||||
|
{
|
||||||
|
return myMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::DirectoryResponse::DirectoryResponse(Ftp::Response Resp) :
|
||||||
|
Ftp::Response(Resp)
|
||||||
|
{
|
||||||
|
if (IsOk())
|
||||||
|
{
|
||||||
|
// Extract the directory from the server response
|
||||||
|
std::string::size_type Begin = Resp.GetMessage().find('"', 0);
|
||||||
|
std::string::size_type End = Resp.GetMessage().find('"', Begin + 1);
|
||||||
|
myDirectory = Resp.GetMessage().substr(Begin + 1, End - Begin - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the directory returned in the response
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& Ftp::DirectoryResponse::GetDirectory() const
|
||||||
|
{
|
||||||
|
return myDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::ListingResponse::ListingResponse(Ftp::Response Resp, const std::vector<char>& Data) :
|
||||||
|
Ftp::Response(Resp)
|
||||||
|
{
|
||||||
|
if (IsOk())
|
||||||
|
{
|
||||||
|
// Fill the array of strings
|
||||||
|
std::string Paths(Data.begin(), Data.end());
|
||||||
|
std::string::size_type LastPos = 0;
|
||||||
|
for (std::string::size_type Pos = Paths.find("\r\n"); Pos != std::string::npos; Pos = Paths.find("\r\n", LastPos))
|
||||||
|
{
|
||||||
|
myFilenames.push_back(Paths.substr(LastPos, Pos - LastPos));
|
||||||
|
LastPos = Pos + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the number of filenames in the listing
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::size_t Ftp::ListingResponse::GetCount() const
|
||||||
|
{
|
||||||
|
return myFilenames.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the Index-th filename in the directory
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& Ftp::ListingResponse::GetFilename(std::size_t Index) const
|
||||||
|
{
|
||||||
|
return myFilenames[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Destructor -- close the connection with the server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::~Ftp()
|
||||||
|
{
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Connect to the specified FTP server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::Connect(const IPAddress& Server, unsigned short Port, float Timeout)
|
||||||
|
{
|
||||||
|
// Connect to the server
|
||||||
|
if (myCommandSocket.Connect(Port, Server, Timeout) != Socket::Done)
|
||||||
|
return Response(Response::ConnectionFailed);
|
||||||
|
|
||||||
|
// Get the response to the connection
|
||||||
|
return GetResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Log in using anonymous account
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::Login()
|
||||||
|
{
|
||||||
|
return Login("anonymous", "user@sfml-dev.org");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Log in using a username and a password
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::Login(const std::string& UserName, const std::string& Password)
|
||||||
|
{
|
||||||
|
Response Resp = SendCommand("USER", UserName);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
Resp = SendCommand("PASS", Password);
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close the connection with FTP server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::Disconnect()
|
||||||
|
{
|
||||||
|
// Send the exit command
|
||||||
|
Response Resp = SendCommand("QUIT");
|
||||||
|
if (Resp.IsOk())
|
||||||
|
myCommandSocket.Close();
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a null command just to prevent from being disconnected
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::KeepAlive()
|
||||||
|
{
|
||||||
|
return SendCommand("NOOP");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the current working directory
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::DirectoryResponse Ftp::GetWorkingDirectory()
|
||||||
|
{
|
||||||
|
return DirectoryResponse(SendCommand("PWD"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the contents of the given directory
|
||||||
|
/// (subdirectories and files)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::ListingResponse Ftp::GetDirectoryListing(const std::string& Directory)
|
||||||
|
{
|
||||||
|
// Open a data channel on default port (20) using ASCII transfer mode
|
||||||
|
std::vector<char> DirData;
|
||||||
|
DataChannel Data(*this);
|
||||||
|
Response Resp = Data.Open(Ascii);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Tell the server to send us the listing
|
||||||
|
Resp = SendCommand("NLST", Directory);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Receive the listing
|
||||||
|
Data.Receive(DirData);
|
||||||
|
|
||||||
|
// Get the response from the server
|
||||||
|
Resp = GetResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListingResponse(Resp, DirData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the current working directory
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::ChangeDirectory(const std::string& Directory)
|
||||||
|
{
|
||||||
|
return SendCommand("CWD", Directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Go to the parent directory of the current one
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::ParentDirectory()
|
||||||
|
{
|
||||||
|
return SendCommand("CDUP");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Create a new directory
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::MakeDirectory(const std::string& Name)
|
||||||
|
{
|
||||||
|
return SendCommand("MKD", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove an existing directory
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::DeleteDirectory(const std::string& Name)
|
||||||
|
{
|
||||||
|
return SendCommand("RMD", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Rename a file
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::RenameFile(const std::string& File, const std::string& NewName)
|
||||||
|
{
|
||||||
|
Response Resp = SendCommand("RNFR", File);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
Resp = SendCommand("RNTO", NewName);
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove an existing file
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::DeleteFile(const std::string& Name)
|
||||||
|
{
|
||||||
|
return SendCommand("DELE", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Download a file from the server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::Download(const std::string& DistantFile, const std::string& DestPath, TransferMode Mode)
|
||||||
|
{
|
||||||
|
// Open a data channel using the given transfer mode
|
||||||
|
DataChannel Data(*this);
|
||||||
|
Response Resp = Data.Open(Mode);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Tell the server to start the transfer
|
||||||
|
Resp = SendCommand("RETR", DistantFile);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Receive the file data
|
||||||
|
std::vector<char> FileData;
|
||||||
|
Data.Receive(FileData);
|
||||||
|
|
||||||
|
// Get the response from the server
|
||||||
|
Resp = GetResponse();
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Extract the filename from the file path
|
||||||
|
std::string Filename = DistantFile;
|
||||||
|
std::string::size_type Pos = Filename.find_last_of("/\\");
|
||||||
|
if (Pos != std::string::npos)
|
||||||
|
Filename = Filename.substr(Pos + 1);
|
||||||
|
|
||||||
|
// Make sure the destination path ends with a slash
|
||||||
|
std::string Path = DestPath;
|
||||||
|
if (!Path.empty() && (Path[Path.size() - 1] != '\\') && (Path[Path.size() - 1] != '/'))
|
||||||
|
Path += "/";
|
||||||
|
|
||||||
|
// Create the file and copy the received data into it
|
||||||
|
std::ofstream File((Path + Filename).c_str(), std::ios_base::binary);
|
||||||
|
if (!File)
|
||||||
|
return Response(Response::InvalidFile);
|
||||||
|
File.write(&FileData[0], static_cast<std::streamsize>(FileData.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Upload a file to the server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::Upload(const std::string& LocalFile, const std::string& DestPath, TransferMode Mode)
|
||||||
|
{
|
||||||
|
// Get the contents of the file to send
|
||||||
|
std::ifstream File(LocalFile.c_str(), std::ios_base::binary);
|
||||||
|
if (!File)
|
||||||
|
return Response(Response::InvalidFile);
|
||||||
|
File.seekg(0, std::ios::end);
|
||||||
|
std::size_t Length = File.tellg();
|
||||||
|
File.seekg(0, std::ios::beg);
|
||||||
|
std::vector<char> FileData(Length);
|
||||||
|
File.read(&FileData[0], static_cast<std::streamsize>(Length));
|
||||||
|
|
||||||
|
// Extract the filename from the file path
|
||||||
|
std::string Filename = LocalFile;
|
||||||
|
std::string::size_type Pos = Filename.find_last_of("/\\");
|
||||||
|
if (Pos != std::string::npos)
|
||||||
|
Filename = Filename.substr(Pos + 1);
|
||||||
|
|
||||||
|
// Make sure the destination path ends with a slash
|
||||||
|
std::string Path = DestPath;
|
||||||
|
if (!Path.empty() && (Path[Path.size() - 1] != '\\') && (Path[Path.size() - 1] != '/'))
|
||||||
|
Path += "/";
|
||||||
|
|
||||||
|
// Open a data channel using the given transfer mode
|
||||||
|
DataChannel Data(*this);
|
||||||
|
Response Resp = Data.Open(Mode);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Tell the server to start the transfer
|
||||||
|
Resp = SendCommand("STOR", Path + Filename);
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Send the file data
|
||||||
|
Data.Send(FileData);
|
||||||
|
|
||||||
|
// Get the response from the server
|
||||||
|
Resp = GetResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a command to the FTP server
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::SendCommand(const std::string& Command, const std::string& Parameter)
|
||||||
|
{
|
||||||
|
// Build the command string
|
||||||
|
std::string CommandStr;
|
||||||
|
if (Parameter != "")
|
||||||
|
CommandStr = Command + " " + Parameter + "\r\n";
|
||||||
|
else
|
||||||
|
CommandStr = Command + "\r\n";
|
||||||
|
|
||||||
|
// Send it to the server
|
||||||
|
if (myCommandSocket.Send(CommandStr.c_str(), CommandStr.length()) != sf::Socket::Done)
|
||||||
|
return Response(Response::ConnectionClosed);
|
||||||
|
|
||||||
|
// Get the response
|
||||||
|
return GetResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive a response from the server
|
||||||
|
/// (usually after a command has been sent)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::GetResponse()
|
||||||
|
{
|
||||||
|
// We'll use a variable to keep track of the last valid code.
|
||||||
|
// It is useful in case of multi-lines responses, because the end of such a response
|
||||||
|
// will start by the same code
|
||||||
|
unsigned int LastCode = 0;
|
||||||
|
bool IsInsideMultiline = false;
|
||||||
|
std::string Message;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
// Receive the response from the server
|
||||||
|
char Buffer[1024];
|
||||||
|
std::size_t Length;
|
||||||
|
if (myCommandSocket.Receive(Buffer, sizeof(Buffer), Length) != sf::Socket::Done)
|
||||||
|
return Response(Response::ConnectionClosed);
|
||||||
|
|
||||||
|
// There can be several lines inside the received buffer, extract them all
|
||||||
|
std::istringstream In(std::string(Buffer, Length), std::ios_base::binary);
|
||||||
|
while (In)
|
||||||
|
{
|
||||||
|
// Try to extract the code
|
||||||
|
unsigned int Code;
|
||||||
|
if (In >> Code)
|
||||||
|
{
|
||||||
|
// Extract the separator
|
||||||
|
char Sep;
|
||||||
|
In.get(Sep);
|
||||||
|
|
||||||
|
// The '-' character means a multiline response
|
||||||
|
if ((Sep == '-') && !IsInsideMultiline)
|
||||||
|
{
|
||||||
|
// Set the multiline flag
|
||||||
|
IsInsideMultiline = true;
|
||||||
|
|
||||||
|
// Keep track of the code
|
||||||
|
if (LastCode == 0)
|
||||||
|
LastCode = Code;
|
||||||
|
|
||||||
|
// Extract the line
|
||||||
|
std::getline(In, Message);
|
||||||
|
|
||||||
|
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||||
|
Message.erase(Message.length() - 1);
|
||||||
|
Message = Sep + Message + "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We must make sure that the code is the same, otherwise it means
|
||||||
|
// we haven't reached the end of the multiline response
|
||||||
|
if ((Sep != '-') && ((Code == LastCode) || (LastCode == 0)))
|
||||||
|
{
|
||||||
|
// Clear the multiline flag
|
||||||
|
IsInsideMultiline = false;
|
||||||
|
|
||||||
|
// Extract the line
|
||||||
|
std::string Line;
|
||||||
|
std::getline(In, Line);
|
||||||
|
|
||||||
|
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||||
|
Line.erase(Line.length() - 1);
|
||||||
|
|
||||||
|
// Append it to the message
|
||||||
|
if (Code == LastCode)
|
||||||
|
{
|
||||||
|
std::ostringstream Out;
|
||||||
|
Out << Code << Sep << Line;
|
||||||
|
Message += Out.str();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Message = Sep + Line;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the response code and message
|
||||||
|
return Response(static_cast<Response::Status>(Code), Message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The line we just read was actually not a response,
|
||||||
|
// only a new part of the current multiline response
|
||||||
|
|
||||||
|
// Extract the line
|
||||||
|
std::string Line;
|
||||||
|
std::getline(In, Line);
|
||||||
|
|
||||||
|
if (!Line.empty())
|
||||||
|
{
|
||||||
|
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||||
|
Line.erase(Line.length() - 1);
|
||||||
|
|
||||||
|
// Append it to the current message
|
||||||
|
std::ostringstream Out;
|
||||||
|
Out << Code << Sep << Line << "\n";
|
||||||
|
Message += Out.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (LastCode != 0)
|
||||||
|
{
|
||||||
|
// It seems we are in the middle of a multiline response
|
||||||
|
|
||||||
|
// Clear the error bits of the stream
|
||||||
|
In.clear();
|
||||||
|
|
||||||
|
// Extract the line
|
||||||
|
std::string Line;
|
||||||
|
std::getline(In, Line);
|
||||||
|
|
||||||
|
if (!Line.empty())
|
||||||
|
{
|
||||||
|
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||||
|
Line.erase(Line.length() - 1);
|
||||||
|
|
||||||
|
// Append it to the current message
|
||||||
|
Message += Line + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error : cannot extract the code, and we are not in a multiline response
|
||||||
|
return Response(Response::InvalidResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We never reach there
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::DataChannel::DataChannel(Ftp& Owner) :
|
||||||
|
myFtp(Owner)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Destructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::DataChannel::~DataChannel()
|
||||||
|
{
|
||||||
|
// Close the data socket
|
||||||
|
myDataSocket.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Open the data channel using the specified mode and port
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Ftp::Response Ftp::DataChannel::Open(Ftp::TransferMode Mode)
|
||||||
|
{
|
||||||
|
// Open a data connection in active mode (we connect to the server)
|
||||||
|
Ftp::Response Resp = myFtp.SendCommand("PASV");
|
||||||
|
if (Resp.IsOk())
|
||||||
|
{
|
||||||
|
// Extract the connection address and port from the response
|
||||||
|
std::string::size_type begin = Resp.GetMessage().find_first_of("0123456789");
|
||||||
|
if (begin != std::string::npos)
|
||||||
|
{
|
||||||
|
sf::Uint8 Data[6] = {0, 0, 0, 0, 0, 0};
|
||||||
|
std::string Str = Resp.GetMessage().substr(begin);
|
||||||
|
std::size_t Index = 0;
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
// Extract the current number
|
||||||
|
while (isdigit(Str[Index]))
|
||||||
|
{
|
||||||
|
Data[i] = Data[i] * 10 + (Str[Index] - '0');
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip separator
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconstruct connection port and address
|
||||||
|
unsigned short Port = Data[4] * 256 + Data[5];
|
||||||
|
sf::IPAddress Address(static_cast<sf::Uint8>(Data[0]),
|
||||||
|
static_cast<sf::Uint8>(Data[1]),
|
||||||
|
static_cast<sf::Uint8>(Data[2]),
|
||||||
|
static_cast<sf::Uint8>(Data[3]));
|
||||||
|
|
||||||
|
// Connect the data channel to the server
|
||||||
|
if (myDataSocket.Connect(Port, Address) == Socket::Done)
|
||||||
|
{
|
||||||
|
// Translate the transfer mode to the corresponding FTP parameter
|
||||||
|
std::string ModeStr;
|
||||||
|
switch (Mode)
|
||||||
|
{
|
||||||
|
case Ftp::Binary : ModeStr = "I"; break;
|
||||||
|
case Ftp::Ascii : ModeStr = "A"; break;
|
||||||
|
case Ftp::Ebcdic : ModeStr = "E"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the transfer mode
|
||||||
|
Resp = myFtp.SendCommand("TYPE", ModeStr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Failed to connect to the server
|
||||||
|
Resp = Ftp::Response(Ftp::Response::ConnectionFailed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive data on the data channel until it is closed
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Ftp::DataChannel::Receive(std::vector<char>& Data)
|
||||||
|
{
|
||||||
|
// Receive data
|
||||||
|
Data.clear();
|
||||||
|
char Buffer[1024];
|
||||||
|
std::size_t Received;
|
||||||
|
while (myDataSocket.Receive(Buffer, sizeof(Buffer), Received) == sf::Socket::Done)
|
||||||
|
{
|
||||||
|
std::copy(Buffer, Buffer + Received, std::back_inserter(Data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the data socket
|
||||||
|
myDataSocket.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send data on the data channel
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Ftp::DataChannel::Send(const std::vector<char>& Data)
|
||||||
|
{
|
||||||
|
// Send data
|
||||||
|
myDataSocket.Send(&Data[0], Data.size());
|
||||||
|
|
||||||
|
// Close the data socket
|
||||||
|
myDataSocket.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,425 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Http.hpp>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Convenience function to convert a string to lower case
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::string ToLower(const std::string& Str)
|
||||||
|
{
|
||||||
|
std::string Ret = Str;
|
||||||
|
for (std::string::iterator i = Ret.begin(); i != Ret.end(); ++i)
|
||||||
|
*i = static_cast<char>(tolower(*i));
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http::Request::Request(Method RequestMethod, const std::string& URI, const std::string& Body) :
|
||||||
|
myMethod (RequestMethod),
|
||||||
|
myURI (URI),
|
||||||
|
myMajorVersion(1),
|
||||||
|
myMinorVersion(0),
|
||||||
|
myBody (Body)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the value of a field; the field is added if it doesn't exist
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::Request::SetField(const std::string& Field, const std::string& Value)
|
||||||
|
{
|
||||||
|
myFields[ToLower(Field)] = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the request method.
|
||||||
|
/// This parameter is Get by default
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::Request::SetMethod(Http::Request::Method RequestMethod)
|
||||||
|
{
|
||||||
|
myMethod = RequestMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the target URI of the request.
|
||||||
|
/// This parameter is "/" by default
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::Request::SetURI(const std::string& URI)
|
||||||
|
{
|
||||||
|
myURI = URI;
|
||||||
|
|
||||||
|
// Make sure it starts with a '/'
|
||||||
|
if (myURI.empty() || (myURI[0] != '/'))
|
||||||
|
myURI.insert(0, "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the HTTP version of the request.
|
||||||
|
/// This parameter is 1.0 by default
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::Request::SetHttpVersion(unsigned int Major, unsigned int Minor)
|
||||||
|
{
|
||||||
|
myMajorVersion = Major;
|
||||||
|
myMinorVersion = Minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the body of the request. This parameter is optional and
|
||||||
|
/// makes sense only for POST requests.
|
||||||
|
/// This parameter is empty by default
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::Request::SetBody(const std::string& Body)
|
||||||
|
{
|
||||||
|
myBody = Body;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the string representation of a request header
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::string Http::Request::ToString() const
|
||||||
|
{
|
||||||
|
std::ostringstream Out;
|
||||||
|
|
||||||
|
// Convert the method to its string representation
|
||||||
|
std::string RequestMethod;
|
||||||
|
switch (myMethod)
|
||||||
|
{
|
||||||
|
default :
|
||||||
|
case Get : RequestMethod = "GET"; break;
|
||||||
|
case Post : RequestMethod = "POST"; break;
|
||||||
|
case Head : RequestMethod = "HEAD"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the first line containing the request type
|
||||||
|
Out << RequestMethod << " " << myURI << " ";
|
||||||
|
Out << "HTTP/" << myMajorVersion << "." << myMinorVersion << "\r\n";
|
||||||
|
|
||||||
|
// Write fields
|
||||||
|
for (FieldTable::const_iterator i = myFields.begin(); i != myFields.end(); ++i)
|
||||||
|
{
|
||||||
|
Out << i->first << ": " << i->second << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use an extra \r\n to separate the header from the body
|
||||||
|
Out << "\r\n";
|
||||||
|
|
||||||
|
// Add the body
|
||||||
|
Out << myBody;
|
||||||
|
|
||||||
|
return Out.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the given field has been defined
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Http::Request::HasField(const std::string& Field) const
|
||||||
|
{
|
||||||
|
return myFields.find(Field) != myFields.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http::Response::Response() :
|
||||||
|
myStatus (ConnectionFailed),
|
||||||
|
myMajorVersion(0),
|
||||||
|
myMinorVersion(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the value of a field
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& Http::Response::GetField(const std::string& Field) const
|
||||||
|
{
|
||||||
|
FieldTable::const_iterator It = myFields.find(Field);
|
||||||
|
if (It != myFields.end())
|
||||||
|
{
|
||||||
|
return It->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const std::string Empty = "";
|
||||||
|
return Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the header's status code
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http::Response::Status Http::Response::GetStatus() const
|
||||||
|
{
|
||||||
|
return myStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the major HTTP version number of the response
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int Http::Response::GetMajorHttpVersion() const
|
||||||
|
{
|
||||||
|
return myMajorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the major HTTP version number of the response
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int Http::Response::GetMinorHttpVersion() const
|
||||||
|
{
|
||||||
|
return myMinorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the body of the response. The body can contain :
|
||||||
|
/// - the requested page (for GET requests)
|
||||||
|
/// - a response from the server (for POST requests)
|
||||||
|
/// - nothing (for HEAD requests)
|
||||||
|
/// - an error message (in case of an error)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const std::string& Http::Response::GetBody() const
|
||||||
|
{
|
||||||
|
return myBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the header from a response string
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::Response::FromString(const std::string& Data)
|
||||||
|
{
|
||||||
|
std::istringstream In(Data);
|
||||||
|
|
||||||
|
// Extract the HTTP version from the first line
|
||||||
|
std::string Version;
|
||||||
|
if (In >> Version)
|
||||||
|
{
|
||||||
|
if ((Version.size() >= 8) && (Version[6] == '.') &&
|
||||||
|
(ToLower(Version.substr(0, 5)) == "http/") &&
|
||||||
|
isdigit(Version[5]) && isdigit(Version[7]))
|
||||||
|
{
|
||||||
|
myMajorVersion = Version[5] - '0';
|
||||||
|
myMinorVersion = Version[7] - '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid HTTP version
|
||||||
|
myStatus = InvalidResponse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the status code from the first line
|
||||||
|
int StatusCode;
|
||||||
|
if (In >> StatusCode)
|
||||||
|
{
|
||||||
|
myStatus = static_cast<Status>(StatusCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid status code
|
||||||
|
myStatus = InvalidResponse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore the end of the first line
|
||||||
|
In.ignore(10000, '\n');
|
||||||
|
|
||||||
|
// Parse the other lines, which contain fields, one by one
|
||||||
|
std::string Line;
|
||||||
|
while (std::getline(In, Line) && (Line.size() > 2))
|
||||||
|
{
|
||||||
|
std::string::size_type Pos = Line.find(": ");
|
||||||
|
if (Pos != std::string::npos)
|
||||||
|
{
|
||||||
|
// Extract the field name and its value
|
||||||
|
std::string Field = Line.substr(0, Pos);
|
||||||
|
std::string Value = Line.substr(Pos + 2);
|
||||||
|
|
||||||
|
// Remove any trailing \r
|
||||||
|
if (!Value.empty() && (*Value.rbegin() == '\r'))
|
||||||
|
Value.erase(Value.size() - 1);
|
||||||
|
|
||||||
|
// Add the field
|
||||||
|
myFields[ToLower(Field)] = Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally extract the body
|
||||||
|
myBody.clear();
|
||||||
|
while (std::getline(In, Line))
|
||||||
|
myBody += Line + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http::Http() :
|
||||||
|
myHost(),
|
||||||
|
myPort(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the Http instance with the target host
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http::Http(const std::string& Host, unsigned short Port)
|
||||||
|
{
|
||||||
|
SetHost(Host, Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set the target host
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Http::SetHost(const std::string& Host, unsigned short Port)
|
||||||
|
{
|
||||||
|
// Detect the protocol used
|
||||||
|
std::string Protocol = ToLower(Host.substr(0, 8));
|
||||||
|
if (Protocol.substr(0, 7) == "http://")
|
||||||
|
{
|
||||||
|
// HTTP protocol
|
||||||
|
myHostName = Host.substr(7);
|
||||||
|
myPort = (Port != 0 ? Port : 80);
|
||||||
|
}
|
||||||
|
else if (Protocol == "https://")
|
||||||
|
{
|
||||||
|
// HTTPS protocol
|
||||||
|
myHostName = Host.substr(8);
|
||||||
|
myPort = (Port != 0 ? Port : 443);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Undefined protocol - use HTTP
|
||||||
|
myHostName = Host;
|
||||||
|
myPort = (Port != 0 ? Port : 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any trailing '/' from the host name
|
||||||
|
if (!myHostName.empty() && (*myHostName.rbegin() == '/'))
|
||||||
|
myHostName.erase(myHostName.size() - 1);
|
||||||
|
|
||||||
|
myHost = sf::IPAddress(myHostName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a HTTP request and return the server's response.
|
||||||
|
/// You must be connected to a host before sending requests.
|
||||||
|
/// Any missing mandatory header field will be added with an appropriate value.
|
||||||
|
/// Warning : this function waits for the server's response and may
|
||||||
|
/// not return instantly; use a thread if you don't want to block your
|
||||||
|
/// application.
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Http::Response Http::SendRequest(const Http::Request& Req)
|
||||||
|
{
|
||||||
|
// First make sure the request is valid -- add missing mandatory fields
|
||||||
|
Request ToSend(Req);
|
||||||
|
if (!ToSend.HasField("From"))
|
||||||
|
{
|
||||||
|
ToSend.SetField("From", "user@sfml-dev.org");
|
||||||
|
}
|
||||||
|
if (!ToSend.HasField("User-Agent"))
|
||||||
|
{
|
||||||
|
ToSend.SetField("User-Agent", "libsfml-network/1.x");
|
||||||
|
}
|
||||||
|
if (!ToSend.HasField("Host"))
|
||||||
|
{
|
||||||
|
ToSend.SetField("Host", myHostName);
|
||||||
|
}
|
||||||
|
if (!ToSend.HasField("Content-Length"))
|
||||||
|
{
|
||||||
|
std::ostringstream Out;
|
||||||
|
Out << ToSend.myBody.size();
|
||||||
|
ToSend.SetField("Content-Length", Out.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the response
|
||||||
|
Response Received;
|
||||||
|
|
||||||
|
// Connect the socket to the host
|
||||||
|
if (myConnection.Connect(myPort, myHost) == Socket::Done)
|
||||||
|
{
|
||||||
|
// Convert the request to string and send it through the connected socket
|
||||||
|
std::string RequestStr = ToSend.ToString();
|
||||||
|
|
||||||
|
if (!RequestStr.empty())
|
||||||
|
{
|
||||||
|
// Send it through the socket
|
||||||
|
if (myConnection.Send(RequestStr.c_str(), RequestStr.size()) == sf::Socket::Done)
|
||||||
|
{
|
||||||
|
// Wait for the server's response
|
||||||
|
std::string ReceivedStr;
|
||||||
|
std::size_t Size = 0;
|
||||||
|
char Buffer[1024];
|
||||||
|
while (myConnection.Receive(Buffer, sizeof(Buffer), Size) == sf::Socket::Done)
|
||||||
|
{
|
||||||
|
ReceivedStr.append(Buffer, Buffer + Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the Response object from the received data
|
||||||
|
Received.FromString(ReceivedStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the connection
|
||||||
|
myConnection.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Received;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,303 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/IPAddress.hpp>
|
||||||
|
#include <SFML/Network/Http.hpp>
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Static member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const IPAddress IPAddress::LocalHost("127.0.0.1");
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress::IPAddress() :
|
||||||
|
myAddress(INADDR_NONE)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from a string
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress::IPAddress(const std::string& Address)
|
||||||
|
{
|
||||||
|
// First try to convert it as a byte representation ("xxx.xxx.xxx.xxx")
|
||||||
|
myAddress = inet_addr(Address.c_str());
|
||||||
|
|
||||||
|
// If not successful, try to convert it as a host name
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
hostent* Host = gethostbyname(Address.c_str());
|
||||||
|
if (Host)
|
||||||
|
{
|
||||||
|
// Host found, extract its IP address
|
||||||
|
myAddress = reinterpret_cast<in_addr*>(Host->h_addr)->s_addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Host name not found on the network
|
||||||
|
myAddress = INADDR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from a C-style string ;
|
||||||
|
/// Needed for implicit conversions from literal strings to IPAddress to work
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress::IPAddress(const char* Address)
|
||||||
|
{
|
||||||
|
// First try to convert it as a byte representation ("xxx.xxx.xxx.xxx")
|
||||||
|
myAddress = inet_addr(Address);
|
||||||
|
|
||||||
|
// If not successful, try to convert it as a host name
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
hostent* Host = gethostbyname(Address);
|
||||||
|
if (Host)
|
||||||
|
{
|
||||||
|
// Host found, extract its IP address
|
||||||
|
myAddress = reinterpret_cast<in_addr*>(Host->h_addr)->s_addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Host name not found on the network
|
||||||
|
myAddress = INADDR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from 4 bytes
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress::IPAddress(Uint8 Byte0, Uint8 Byte1, Uint8 Byte2, Uint8 Byte3)
|
||||||
|
{
|
||||||
|
myAddress = htonl((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the address from a 32-bits integer
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress::IPAddress(Uint32 Address)
|
||||||
|
{
|
||||||
|
myAddress = htonl(Address);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Tell if the address is a valid one
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::IsValid() const
|
||||||
|
{
|
||||||
|
return myAddress != INADDR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get a string representation of the address
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::string IPAddress::ToString() const
|
||||||
|
{
|
||||||
|
in_addr InAddr;
|
||||||
|
InAddr.s_addr = myAddress;
|
||||||
|
|
||||||
|
return inet_ntoa(InAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get an integer representation of the address
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Uint32 IPAddress::ToInteger() const
|
||||||
|
{
|
||||||
|
return ntohl(myAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the computer's local IP address (from the LAN point of view)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress IPAddress::GetLocalAddress()
|
||||||
|
{
|
||||||
|
// The method here is to connect a UDP socket to anyone (here to localhost),
|
||||||
|
// and get the local socket address with the getsockname function.
|
||||||
|
// UDP connection will not send anything to the network, so this function won't cause any overhead
|
||||||
|
|
||||||
|
IPAddress LocalAddress;
|
||||||
|
|
||||||
|
// Create the socket
|
||||||
|
SocketHelper::SocketType Socket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (Socket == SocketHelper::InvalidSocket())
|
||||||
|
return LocalAddress;
|
||||||
|
|
||||||
|
// Build the host address (use a random port)
|
||||||
|
sockaddr_in SockAddr;
|
||||||
|
memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
|
||||||
|
SockAddr.sin_addr.s_addr = INADDR_LOOPBACK;
|
||||||
|
SockAddr.sin_family = AF_INET;
|
||||||
|
SockAddr.sin_port = htons(4567);
|
||||||
|
|
||||||
|
// Connect the socket
|
||||||
|
if (connect(Socket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
|
||||||
|
{
|
||||||
|
SocketHelper::Close(Socket);
|
||||||
|
return LocalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the local address of the socket connection
|
||||||
|
SocketHelper::LengthType Size = sizeof(SockAddr);
|
||||||
|
if (getsockname(Socket, reinterpret_cast<sockaddr*>(&SockAddr), &Size) == -1)
|
||||||
|
{
|
||||||
|
SocketHelper::Close(Socket);
|
||||||
|
return LocalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the socket
|
||||||
|
SocketHelper::Close(Socket);
|
||||||
|
|
||||||
|
// Finally build the IP address
|
||||||
|
LocalAddress.myAddress = SockAddr.sin_addr.s_addr;
|
||||||
|
|
||||||
|
return LocalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the computer's public IP address (from the web point of view)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IPAddress IPAddress::GetPublicAddress()
|
||||||
|
{
|
||||||
|
// The trick here is more complicated, because the only way
|
||||||
|
// to get our public IP address is to get it from a distant computer.
|
||||||
|
// Here we get the web page from http://www.whatismyip.org
|
||||||
|
// and parse the result to extract our IP address
|
||||||
|
// (not very hard : the web page contains only our IP address)
|
||||||
|
|
||||||
|
IPAddress PublicAddress;
|
||||||
|
|
||||||
|
// Connect to the web server and get its index page
|
||||||
|
Http Server("www.whatismyip.org");
|
||||||
|
Http::Request Request(Http::Request::Get, "/");
|
||||||
|
Http::Response Page = Server.SendRequest(Request);
|
||||||
|
|
||||||
|
// If the request was successful, we can extract
|
||||||
|
// the address from the body of the web page
|
||||||
|
if (Page.GetStatus() == Http::Response::Ok)
|
||||||
|
PublicAddress = Page.GetBody();
|
||||||
|
|
||||||
|
return PublicAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator ==
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::operator ==(const IPAddress& Other) const
|
||||||
|
{
|
||||||
|
return myAddress == Other.myAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator !=
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::operator !=(const IPAddress& Other) const
|
||||||
|
{
|
||||||
|
return myAddress != Other.myAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::operator <(const IPAddress& Other) const
|
||||||
|
{
|
||||||
|
return myAddress < Other.myAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator >
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::operator >(const IPAddress& Other) const
|
||||||
|
{
|
||||||
|
return myAddress > Other.myAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <=
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::operator <=(const IPAddress& Other) const
|
||||||
|
{
|
||||||
|
return myAddress <= Other.myAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator >=
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IPAddress::operator >=(const IPAddress& Other) const
|
||||||
|
{
|
||||||
|
return myAddress >= Other.myAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator >> overload to extract an address from an input stream
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::istream& operator >>(std::istream& Stream, IPAddress& Address)
|
||||||
|
{
|
||||||
|
std::string Str;
|
||||||
|
Stream >> Str;
|
||||||
|
Address = IPAddress(Str);
|
||||||
|
|
||||||
|
return Stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator << overload to print an address to an output stream
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::ostream& operator <<(std::ostream& Stream, const IPAddress& Address)
|
||||||
|
{
|
||||||
|
return Stream << Address.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,426 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Packet.hpp>
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet::Packet() :
|
||||||
|
myReadPos(0),
|
||||||
|
myIsValid(true)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Virtual destructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet::~Packet()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Append data to the end of the packet
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Packet::Append(const void* Data, std::size_t SizeInBytes)
|
||||||
|
{
|
||||||
|
if (Data && (SizeInBytes > 0))
|
||||||
|
{
|
||||||
|
std::size_t Start = myData.size();
|
||||||
|
myData.resize(Start + SizeInBytes);
|
||||||
|
memcpy(&myData[Start], Data, SizeInBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Clear the packet data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Packet::Clear()
|
||||||
|
{
|
||||||
|
myData.clear();
|
||||||
|
myReadPos = 0;
|
||||||
|
myIsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get a pointer to the data contained in the packet
|
||||||
|
/// Warning : the returned pointer may be invalid after you
|
||||||
|
/// append data to the packet
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const char* Packet::GetData() const
|
||||||
|
{
|
||||||
|
return !myData.empty() ? &myData[0] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the size of the data contained in the packet
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
std::size_t Packet::GetDataSize() const
|
||||||
|
{
|
||||||
|
return myData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Tell if the reading position has reached the end of the packet
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Packet::EndOfPacket() const
|
||||||
|
{
|
||||||
|
return myReadPos >= myData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Tell if the packet is valid for reading
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet::operator bool() const
|
||||||
|
{
|
||||||
|
return myIsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator >> overloads to extract data from the packet
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet& Packet::operator >>(bool& Data)
|
||||||
|
{
|
||||||
|
Uint8 Value;
|
||||||
|
if (*this >> Value)
|
||||||
|
Data = (Value != 0);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(Int8& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = *reinterpret_cast<const Int8*>(GetData() + myReadPos);
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(Uint8& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = *reinterpret_cast<const Uint8*>(GetData() + myReadPos);
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(Int16& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = ntohs(*reinterpret_cast<const Int16*>(GetData() + myReadPos));
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(Uint16& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = ntohs(*reinterpret_cast<const Uint16*>(GetData() + myReadPos));
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(Int32& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = ntohl(*reinterpret_cast<const Int32*>(GetData() + myReadPos));
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(Uint32& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = ntohl(*reinterpret_cast<const Uint32*>(GetData() + myReadPos));
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(float& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = *reinterpret_cast<const float*>(GetData() + myReadPos);
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(double& Data)
|
||||||
|
{
|
||||||
|
if (CheckSize(sizeof(Data)))
|
||||||
|
{
|
||||||
|
Data = *reinterpret_cast<const double*>(GetData() + myReadPos);
|
||||||
|
myReadPos += sizeof(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(char* Data)
|
||||||
|
{
|
||||||
|
// First extract string length
|
||||||
|
Uint32 Length;
|
||||||
|
*this >> Length;
|
||||||
|
|
||||||
|
if ((Length > 0) && CheckSize(Length))
|
||||||
|
{
|
||||||
|
// Then extract characters
|
||||||
|
memcpy(Data, GetData() + myReadPos, Length);
|
||||||
|
Data[Length] = '\0';
|
||||||
|
|
||||||
|
// Update reading position
|
||||||
|
myReadPos += Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(std::string& Data)
|
||||||
|
{
|
||||||
|
// First extract string length
|
||||||
|
Uint32 Length;
|
||||||
|
*this >> Length;
|
||||||
|
|
||||||
|
Data.clear();
|
||||||
|
if ((Length > 0) && CheckSize(Length))
|
||||||
|
{
|
||||||
|
// Then extract characters
|
||||||
|
Data.assign(GetData() + myReadPos, Length);
|
||||||
|
|
||||||
|
// Update reading position
|
||||||
|
myReadPos += Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(wchar_t* Data)
|
||||||
|
{
|
||||||
|
// First extract string length
|
||||||
|
Uint32 Length;
|
||||||
|
*this >> Length;
|
||||||
|
|
||||||
|
if ((Length > 0) && CheckSize(Length * sizeof(Int32)))
|
||||||
|
{
|
||||||
|
// Then extract characters
|
||||||
|
for (Uint32 i = 0; i < Length; ++i)
|
||||||
|
{
|
||||||
|
Uint32 c;
|
||||||
|
*this >> c;
|
||||||
|
Data[i] = static_cast<wchar_t>(c);
|
||||||
|
}
|
||||||
|
Data[Length] = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator >>(std::wstring& Data)
|
||||||
|
{
|
||||||
|
// First extract string length
|
||||||
|
Uint32 Length;
|
||||||
|
*this >> Length;
|
||||||
|
|
||||||
|
Data.clear();
|
||||||
|
if ((Length > 0) && CheckSize(Length * sizeof(Int32)))
|
||||||
|
{
|
||||||
|
// Then extract characters
|
||||||
|
for (Uint32 i = 0; i < Length; ++i)
|
||||||
|
{
|
||||||
|
Uint32 c;
|
||||||
|
*this >> c;
|
||||||
|
Data += static_cast<wchar_t>(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Operator << overloads to put data into the packet
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Packet& Packet::operator <<(bool Data)
|
||||||
|
{
|
||||||
|
*this << static_cast<Uint8>(Data);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(Int8 Data)
|
||||||
|
{
|
||||||
|
Append(&Data, sizeof(Data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(Uint8 Data)
|
||||||
|
{
|
||||||
|
Append(&Data, sizeof(Data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(Int16 Data)
|
||||||
|
{
|
||||||
|
Int16 ToWrite = htons(Data);
|
||||||
|
Append(&ToWrite, sizeof(ToWrite));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(Uint16 Data)
|
||||||
|
{
|
||||||
|
Uint16 ToWrite = htons(Data);
|
||||||
|
Append(&ToWrite, sizeof(ToWrite));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(Int32 Data)
|
||||||
|
{
|
||||||
|
Int32 ToWrite = htonl(Data);
|
||||||
|
Append(&ToWrite, sizeof(ToWrite));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(Uint32 Data)
|
||||||
|
{
|
||||||
|
Uint32 ToWrite = htonl(Data);
|
||||||
|
Append(&ToWrite, sizeof(ToWrite));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(float Data)
|
||||||
|
{
|
||||||
|
Append(&Data, sizeof(Data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(double Data)
|
||||||
|
{
|
||||||
|
Append(&Data, sizeof(Data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(const char* Data)
|
||||||
|
{
|
||||||
|
// First insert string length
|
||||||
|
Uint32 Length = 0;
|
||||||
|
for (const char* c = Data; *c != '\0'; ++c)
|
||||||
|
++Length;
|
||||||
|
*this << Length;
|
||||||
|
|
||||||
|
// Then insert characters
|
||||||
|
Append(Data, Length * sizeof(char));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(const std::string& Data)
|
||||||
|
{
|
||||||
|
// First insert string length
|
||||||
|
Uint32 Length = static_cast<Uint32>(Data.size());
|
||||||
|
*this << Length;
|
||||||
|
|
||||||
|
// Then insert characters
|
||||||
|
if (Length > 0)
|
||||||
|
{
|
||||||
|
Append(Data.c_str(), Length * sizeof(std::string::value_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(const wchar_t* Data)
|
||||||
|
{
|
||||||
|
// First insert string length
|
||||||
|
Uint32 Length = 0;
|
||||||
|
for (const wchar_t* c = Data; *c != L'\0'; ++c)
|
||||||
|
++Length;
|
||||||
|
*this << Length;
|
||||||
|
|
||||||
|
// Then insert characters
|
||||||
|
for (const wchar_t* c = Data; *c != L'\0'; ++c)
|
||||||
|
*this << static_cast<Int32>(*c);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Packet& Packet::operator <<(const std::wstring& Data)
|
||||||
|
{
|
||||||
|
// First insert string length
|
||||||
|
Uint32 Length = static_cast<Uint32>(Data.size());
|
||||||
|
*this << Length;
|
||||||
|
|
||||||
|
// Then insert characters
|
||||||
|
if (Length > 0)
|
||||||
|
{
|
||||||
|
for (std::wstring::const_iterator c = Data.begin(); c != Data.end(); ++c)
|
||||||
|
*this << static_cast<Int32>(*c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the packet can extract a given size of bytes
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Packet::CheckSize(std::size_t Size)
|
||||||
|
{
|
||||||
|
myIsValid = myIsValid && (myReadPos + Size <= myData.size());
|
||||||
|
|
||||||
|
return myIsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Called before the packet is sent to the network
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const char* Packet::OnSend(std::size_t& DataSize)
|
||||||
|
{
|
||||||
|
DataSize = GetDataSize();
|
||||||
|
return GetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Called after the packet has been received from the network
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Packet::OnReceive(const char* Data, std::size_t DataSize)
|
||||||
|
{
|
||||||
|
Append(Data, DataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,132 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SelectorBase.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SelectorBase::SelectorBase() :
|
||||||
|
myMaxSocket(0)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Add a socket to watch
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SelectorBase::Add(SocketHelper::SocketType Socket)
|
||||||
|
{
|
||||||
|
FD_SET(Socket, &mySet);
|
||||||
|
|
||||||
|
int Size = static_cast<int>(Socket);
|
||||||
|
if (Size > myMaxSocket)
|
||||||
|
myMaxSocket = Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove a socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SelectorBase::Remove(SocketHelper::SocketType Socket)
|
||||||
|
{
|
||||||
|
FD_CLR(Socket, &mySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Remove all sockets
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SelectorBase::Clear()
|
||||||
|
{
|
||||||
|
FD_ZERO(&mySet);
|
||||||
|
FD_ZERO(&mySetReady);
|
||||||
|
|
||||||
|
myMaxSocket = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait and collect sockets which are ready for reading.
|
||||||
|
/// This functions will return either when at least one socket
|
||||||
|
/// is ready, or when the given time is out
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned int SelectorBase::Wait(float Timeout)
|
||||||
|
{
|
||||||
|
// Setup the timeout structure
|
||||||
|
timeval Time;
|
||||||
|
Time.tv_sec = static_cast<long>(Timeout);
|
||||||
|
Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000;
|
||||||
|
|
||||||
|
// Prepare the set of sockets to return
|
||||||
|
mySetReady = mySet;
|
||||||
|
|
||||||
|
// Wait until one of the sockets is ready for reading, or timeout is reached
|
||||||
|
int NbSockets = select(myMaxSocket + 1, &mySetReady, NULL, NULL, Timeout > 0 ? &Time : NULL);
|
||||||
|
|
||||||
|
return NbSockets >= 0 ? static_cast<unsigned int>(NbSockets) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// After a call to Wait(), get the Index-th socket which is
|
||||||
|
/// ready for reading. The total number of sockets ready
|
||||||
|
/// is the integer returned by the previous call to Wait()
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHelper::SocketType SelectorBase::GetSocketReady(unsigned int Index)
|
||||||
|
{
|
||||||
|
// The standard FD_xxx interface doesn't define a direct access,
|
||||||
|
// so we must go through the whole set to find the socket we're looking for
|
||||||
|
for (int i = 0; i < myMaxSocket + 1; ++i)
|
||||||
|
{
|
||||||
|
if (FD_ISSET(i, &mySetReady))
|
||||||
|
{
|
||||||
|
// Current socket is ready, but is it the Index-th one ?
|
||||||
|
if (Index > 0)
|
||||||
|
{
|
||||||
|
Index--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return static_cast<SocketHelper::SocketType>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid index : return an invalid socket
|
||||||
|
return SocketHelper::InvalidSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,490 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketTCP.hpp>
|
||||||
|
#include <SFML/Network/IPAddress.hpp>
|
||||||
|
#include <SFML/Network/Packet.hpp>
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTCP::SocketTCP()
|
||||||
|
{
|
||||||
|
Create(SocketHelper::InvalidSocket());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the blocking state of the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketTCP::SetBlocking(bool Blocking)
|
||||||
|
{
|
||||||
|
// Make sure our socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
Create();
|
||||||
|
|
||||||
|
SocketHelper::SetBlocking(mySocket, Blocking);
|
||||||
|
myIsBlocking = Blocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Connect to another computer on a specified port
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout)
|
||||||
|
{
|
||||||
|
// Make sure our socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Build the host address
|
||||||
|
sockaddr_in SockAddr;
|
||||||
|
memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
|
||||||
|
SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str());
|
||||||
|
SockAddr.sin_family = AF_INET;
|
||||||
|
SockAddr.sin_port = htons(Port);
|
||||||
|
|
||||||
|
if (Timeout <= 0)
|
||||||
|
{
|
||||||
|
// ----- We're not using a timeout : just try to connect -----
|
||||||
|
|
||||||
|
if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
|
||||||
|
{
|
||||||
|
// Failed to connect
|
||||||
|
return SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection succeeded
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ----- We're using a timeout : we'll need a few tricks to make it work -----
|
||||||
|
|
||||||
|
// Save the previous blocking state
|
||||||
|
bool IsBlocking = myIsBlocking;
|
||||||
|
|
||||||
|
// Switch to non-blocking to enable our connection timeout
|
||||||
|
if (IsBlocking)
|
||||||
|
SetBlocking(false);
|
||||||
|
|
||||||
|
// Try to connect to host
|
||||||
|
if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) >= 0)
|
||||||
|
{
|
||||||
|
// We got instantly connected! (it may no happen a lot...)
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the error status
|
||||||
|
Socket::Status Status = SocketHelper::GetErrorStatus();
|
||||||
|
|
||||||
|
// If we were in non-blocking mode, return immediatly
|
||||||
|
if (!IsBlocking)
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
// Otherwise, wait until something happens to our socket (success, timeout or error)
|
||||||
|
if (Status == Socket::NotReady)
|
||||||
|
{
|
||||||
|
// Setup the selector
|
||||||
|
fd_set Selector;
|
||||||
|
FD_ZERO(&Selector);
|
||||||
|
FD_SET(mySocket, &Selector);
|
||||||
|
|
||||||
|
// Setup the timeout
|
||||||
|
timeval Time;
|
||||||
|
Time.tv_sec = static_cast<long>(Timeout);
|
||||||
|
Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000;
|
||||||
|
|
||||||
|
// Wait for something to write on our socket (would mean the connection has been accepted)
|
||||||
|
if (select(static_cast<int>(mySocket + 1), NULL, &Selector, NULL, &Time) > 0)
|
||||||
|
{
|
||||||
|
// Connection succeeded
|
||||||
|
Status = Socket::Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Failed to connect before timeout is over
|
||||||
|
Status = SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch back to blocking mode
|
||||||
|
SetBlocking(true);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Listen to a specified port for incoming data or connections
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketTCP::Listen(unsigned short Port)
|
||||||
|
{
|
||||||
|
// Make sure our socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Build the address
|
||||||
|
sockaddr_in SockAddr;
|
||||||
|
memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
|
||||||
|
SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
SockAddr.sin_family = AF_INET;
|
||||||
|
SockAddr.sin_port = htons(Port);
|
||||||
|
|
||||||
|
// Bind the socket to the specified port
|
||||||
|
if (bind(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
|
||||||
|
{
|
||||||
|
// Not likely to happen, but...
|
||||||
|
std::cerr << "Failed to bind socket to port " << Port << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen to the bound port
|
||||||
|
if (listen(mySocket, 0) == -1)
|
||||||
|
{
|
||||||
|
// Oops, socket is deaf
|
||||||
|
std::cerr << "Failed to listen to port " << Port << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait for a connection (must be listening to a port).
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketTCP::Accept(SocketTCP& Connected, IPAddress* Address)
|
||||||
|
{
|
||||||
|
// Address that will be filled with client informations
|
||||||
|
sockaddr_in ClientAddress;
|
||||||
|
SocketHelper::LengthType Length = sizeof(ClientAddress);
|
||||||
|
|
||||||
|
// Accept a new connection
|
||||||
|
Connected = accept(mySocket, reinterpret_cast<sockaddr*>(&ClientAddress), &Length);
|
||||||
|
|
||||||
|
// Check errors
|
||||||
|
if (!Connected.IsValid())
|
||||||
|
{
|
||||||
|
if (Address)
|
||||||
|
*Address = IPAddress();
|
||||||
|
|
||||||
|
return SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill address if requested
|
||||||
|
if (Address)
|
||||||
|
*Address = IPAddress(inet_ntoa(ClientAddress.sin_addr));
|
||||||
|
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send an array of bytes to the host (must be connected first)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketTCP::Send(const char* Data, std::size_t Size)
|
||||||
|
{
|
||||||
|
// First check that socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
return Socket::Error;
|
||||||
|
|
||||||
|
// Check parameters
|
||||||
|
if (Data && Size)
|
||||||
|
{
|
||||||
|
// Loop until every byte has been sent
|
||||||
|
int Sent = 0;
|
||||||
|
int SizeToSend = static_cast<int>(Size);
|
||||||
|
for (int Length = 0; Length < SizeToSend; Length += Sent)
|
||||||
|
{
|
||||||
|
// Send a chunk of data
|
||||||
|
Sent = send(mySocket, Data + Length, SizeToSend - Length, 0);
|
||||||
|
|
||||||
|
// Check if an error occured
|
||||||
|
if (Sent <= 0)
|
||||||
|
return SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error...
|
||||||
|
std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl;
|
||||||
|
return Socket::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive an array of bytes from the host (must be connected first).
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketTCP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived)
|
||||||
|
{
|
||||||
|
// First clear the size received
|
||||||
|
SizeReceived = 0;
|
||||||
|
|
||||||
|
// Check that socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
return Socket::Error;
|
||||||
|
|
||||||
|
// Check parameters
|
||||||
|
if (Data && MaxSize)
|
||||||
|
{
|
||||||
|
// Receive a chunk of bytes
|
||||||
|
int Received = recv(mySocket, Data, static_cast<int>(MaxSize), 0);
|
||||||
|
|
||||||
|
// Check the number of bytes received
|
||||||
|
if (Received > 0)
|
||||||
|
{
|
||||||
|
SizeReceived = static_cast<std::size_t>(Received);
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
else if (Received == 0)
|
||||||
|
{
|
||||||
|
return Socket::Disconnected;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error...
|
||||||
|
std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
||||||
|
return Socket::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a packet of data to the host (must be connected first)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketTCP::Send(Packet& PacketToSend)
|
||||||
|
{
|
||||||
|
// Get the data to send from the packet
|
||||||
|
std::size_t DataSize = 0;
|
||||||
|
const char* Data = PacketToSend.OnSend(DataSize);
|
||||||
|
|
||||||
|
// Send the packet size
|
||||||
|
Uint32 PacketSize = htonl(static_cast<unsigned long>(DataSize));
|
||||||
|
Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize));
|
||||||
|
|
||||||
|
// Send the packet data
|
||||||
|
if (PacketSize > 0)
|
||||||
|
{
|
||||||
|
return Send(Data, DataSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive a packet from the host (must be connected first).
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketTCP::Receive(Packet& PacketToReceive)
|
||||||
|
{
|
||||||
|
// We start by getting the size of the incoming packet
|
||||||
|
Uint32 PacketSize = 0;
|
||||||
|
std::size_t Received = 0;
|
||||||
|
if (myPendingPacketSize < 0)
|
||||||
|
{
|
||||||
|
Socket::Status Status = Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received);
|
||||||
|
if (Status != Socket::Done)
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
PacketSize = ntohl(PacketSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There is a pending packet : we already know its size
|
||||||
|
PacketSize = myPendingPacketSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then loop until we receive all the packet data
|
||||||
|
char Buffer[1024];
|
||||||
|
while (myPendingPacket.size() < PacketSize)
|
||||||
|
{
|
||||||
|
// Receive a chunk of data
|
||||||
|
std::size_t SizeToGet = std::min(static_cast<std::size_t>(PacketSize - myPendingPacket.size()), sizeof(Buffer));
|
||||||
|
Socket::Status Status = Receive(Buffer, SizeToGet, Received);
|
||||||
|
if (Status != Socket::Done)
|
||||||
|
{
|
||||||
|
// We must save the size of the pending packet until we can receive its content
|
||||||
|
if (Status == Socket::NotReady)
|
||||||
|
myPendingPacketSize = PacketSize;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append it into the packet
|
||||||
|
if (Received > 0)
|
||||||
|
{
|
||||||
|
myPendingPacket.resize(myPendingPacket.size() + Received);
|
||||||
|
char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received;
|
||||||
|
memcpy(Begin, Buffer, Received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have received all the datas : we can copy it to the user packet, and clear our internal packet
|
||||||
|
PacketToReceive.Clear();
|
||||||
|
if (!myPendingPacket.empty())
|
||||||
|
PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
|
||||||
|
myPendingPacket.clear();
|
||||||
|
myPendingPacketSize = -1;
|
||||||
|
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketTCP::Close()
|
||||||
|
{
|
||||||
|
if (IsValid())
|
||||||
|
{
|
||||||
|
if (!SocketHelper::Close(mySocket))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to close socket" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mySocket = SocketHelper::InvalidSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
myIsBlocking = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the socket is in a valid state ; this function
|
||||||
|
/// can be called any time to check if the socket is OK
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketTCP::IsValid() const
|
||||||
|
{
|
||||||
|
return mySocket != SocketHelper::InvalidSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator ==
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketTCP::operator ==(const SocketTCP& Other) const
|
||||||
|
{
|
||||||
|
return mySocket == Other.mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator !=
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketTCP::operator !=(const SocketTCP& Other) const
|
||||||
|
{
|
||||||
|
return mySocket != Other.mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <.
|
||||||
|
/// Provided for compatibility with standard containers, as
|
||||||
|
/// comparing two sockets doesn't make much sense...
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketTCP::operator <(const SocketTCP& Other) const
|
||||||
|
{
|
||||||
|
return mySocket < Other.mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the socket from a socket descriptor
|
||||||
|
/// (for internal use only)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketTCP::SocketTCP(SocketHelper::SocketType Descriptor)
|
||||||
|
{
|
||||||
|
Create(Descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Create the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketTCP::Create(SocketHelper::SocketType Descriptor)
|
||||||
|
{
|
||||||
|
// Use the given socket descriptor, or get a new one
|
||||||
|
mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_STREAM, 0);
|
||||||
|
myIsBlocking = true;
|
||||||
|
|
||||||
|
// Reset the pending packet
|
||||||
|
myPendingPacket.clear();
|
||||||
|
myPendingPacketSize = -1;
|
||||||
|
|
||||||
|
// Setup default options
|
||||||
|
if (IsValid())
|
||||||
|
{
|
||||||
|
// To avoid the "Address already in use" error message when trying to bind to the same port
|
||||||
|
int Yes = 1;
|
||||||
|
if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to set socket option \"SO_REUSEADDR\" ; "
|
||||||
|
<< "binding to a same port may fail if too fast" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
|
||||||
|
if (setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to set socket option \"TCP_NODELAY\" ; "
|
||||||
|
<< "all your TCP packets will be buffered" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set blocking by default (should always be the case anyway)
|
||||||
|
SetBlocking(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,431 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketUDP.hpp>
|
||||||
|
#include <SFML/Network/IPAddress.hpp>
|
||||||
|
#include <SFML/Network/Packet.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Default constructor
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketUDP::SocketUDP()
|
||||||
|
{
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the blocking state of the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketUDP::SetBlocking(bool Blocking)
|
||||||
|
{
|
||||||
|
// Make sure our socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
Create();
|
||||||
|
|
||||||
|
SocketHelper::SetBlocking(mySocket, Blocking);
|
||||||
|
myIsBlocking = Blocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Bind the socket to a specific port
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::Bind(unsigned short Port)
|
||||||
|
{
|
||||||
|
// Check if the socket is already bound to the specified port
|
||||||
|
if (myPort != Port)
|
||||||
|
{
|
||||||
|
// If the socket was previously bound to another port, we need to recreate it
|
||||||
|
if (myPort != 0)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Port != 0)
|
||||||
|
{
|
||||||
|
// Build an address with the specified port
|
||||||
|
sockaddr_in Addr;
|
||||||
|
Addr.sin_family = AF_INET;
|
||||||
|
Addr.sin_port = htons(Port);
|
||||||
|
Addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
memset(Addr.sin_zero, 0, sizeof(Addr.sin_zero));
|
||||||
|
|
||||||
|
// Bind the socket to the port
|
||||||
|
if (bind(mySocket, reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr)) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to bind the socket to port " << Port << std::endl;
|
||||||
|
myPort = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the new port
|
||||||
|
myPort = Port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Unbind the socket to its previous port
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::Unbind()
|
||||||
|
{
|
||||||
|
// To unbind the socket, we just recreate it
|
||||||
|
if (myPort != 0)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
Create();
|
||||||
|
myPort = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send an array of bytes
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketUDP::Send(const char* Data, std::size_t Size, const IPAddress& Address, unsigned short Port)
|
||||||
|
{
|
||||||
|
// Make sure the socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Check parameters
|
||||||
|
if (Data && Size)
|
||||||
|
{
|
||||||
|
// Build the target address
|
||||||
|
sockaddr_in Target;
|
||||||
|
Target.sin_family = AF_INET;
|
||||||
|
Target.sin_port = htons(Port);
|
||||||
|
Target.sin_addr.s_addr = inet_addr(Address.ToString().c_str());
|
||||||
|
memset(Target.sin_zero, 0, sizeof(Target.sin_zero));
|
||||||
|
|
||||||
|
// Loop until every byte has been sent
|
||||||
|
int Sent = 0;
|
||||||
|
int SizeToSend = static_cast<int>(Size);
|
||||||
|
for (int Length = 0; Length < SizeToSend; Length += Sent)
|
||||||
|
{
|
||||||
|
// Send a chunk of data
|
||||||
|
Sent = sendto(mySocket, Data + Length, SizeToSend - Length, 0, reinterpret_cast<sockaddr*>(&Target), sizeof(Target));
|
||||||
|
|
||||||
|
// Check errors
|
||||||
|
if (Sent <= 0)
|
||||||
|
return SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error...
|
||||||
|
std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl;
|
||||||
|
return Socket::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive an array of bytes.
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketUDP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived, IPAddress& Address)
|
||||||
|
{
|
||||||
|
// First clear the size received
|
||||||
|
SizeReceived = 0;
|
||||||
|
|
||||||
|
// Make sure the socket is bound to a port
|
||||||
|
if (myPort == 0)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to receive data ; the UDP socket first needs to be bound to a port" << std::endl;
|
||||||
|
return Socket::Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the socket is valid
|
||||||
|
if (!IsValid())
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Check parameters
|
||||||
|
if (Data && MaxSize)
|
||||||
|
{
|
||||||
|
// Data that will be filled with the other computer's address
|
||||||
|
sockaddr_in Sender;
|
||||||
|
Sender.sin_family = AF_INET;
|
||||||
|
Sender.sin_port = htons(myPort);
|
||||||
|
Sender.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
memset(Sender.sin_zero, 0, sizeof(Sender.sin_zero));
|
||||||
|
SocketHelper::LengthType SenderSize = sizeof(Sender);
|
||||||
|
|
||||||
|
// Receive a chunk of bytes
|
||||||
|
int Received = recvfrom(mySocket, Data, static_cast<int>(MaxSize), 0, reinterpret_cast<sockaddr*>(&Sender), &SenderSize);
|
||||||
|
|
||||||
|
// Check the number of bytes received
|
||||||
|
if (Received > 0)
|
||||||
|
{
|
||||||
|
Address = IPAddress(inet_ntoa(Sender.sin_addr));
|
||||||
|
SizeReceived = static_cast<std::size_t>(Received);
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Address = IPAddress();
|
||||||
|
return Received == 0 ? Socket::Disconnected : SocketHelper::GetErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error...
|
||||||
|
std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
||||||
|
return Socket::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a packet of data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketUDP::Send(Packet& PacketToSend, const IPAddress& Address, unsigned short Port)
|
||||||
|
{
|
||||||
|
// Get the data to send from the packet
|
||||||
|
std::size_t DataSize = 0;
|
||||||
|
const char* Data = PacketToSend.OnSend(DataSize);
|
||||||
|
|
||||||
|
// Send the packet size
|
||||||
|
Uint32 PacketSize = htonl(static_cast<unsigned long>(DataSize));
|
||||||
|
Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize), Address, Port);
|
||||||
|
|
||||||
|
// Send the packet data
|
||||||
|
if (PacketSize > 0)
|
||||||
|
{
|
||||||
|
return Send(Data, DataSize, Address, Port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Receive a packet.
|
||||||
|
/// This function will block if the socket is blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address)
|
||||||
|
{
|
||||||
|
// This is not safe at all, as data can be lost, duplicated, or arrive in a different order.
|
||||||
|
// So if a packet is split into more than one chunk, nobody knows what could happen...
|
||||||
|
// Conclusion : we shouldn't use packets with UDP, unless we build a more complex protocol on top of it.
|
||||||
|
|
||||||
|
// We start by getting the size of the incoming packet
|
||||||
|
Uint32 PacketSize = 0;
|
||||||
|
std::size_t Received = 0;
|
||||||
|
if (myPendingPacketSize < 0)
|
||||||
|
{
|
||||||
|
Socket::Status Status = Receive(reinterpret_cast<char*>(&PacketSize), sizeof(PacketSize), Received, Address);
|
||||||
|
if (Status != Socket::Done)
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
PacketSize = ntohl(PacketSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There is a pending packet : we already know its size
|
||||||
|
PacketSize = myPendingPacketSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the user packet
|
||||||
|
PacketToReceive.Clear();
|
||||||
|
|
||||||
|
// Use another address instance for receiving the packet data ;
|
||||||
|
// chunks of data coming from a different sender will be discarded (and lost...)
|
||||||
|
IPAddress Sender;
|
||||||
|
|
||||||
|
// Then loop until we receive all the packet data
|
||||||
|
char Buffer[1024];
|
||||||
|
while (myPendingPacket.size() < PacketSize)
|
||||||
|
{
|
||||||
|
// Receive a chunk of data
|
||||||
|
std::size_t SizeToGet = std::min(static_cast<std::size_t>(PacketSize - myPendingPacket.size()), sizeof(Buffer));
|
||||||
|
Socket::Status Status = Receive(Buffer, SizeToGet, Received, Sender);
|
||||||
|
if (Status != Socket::Done)
|
||||||
|
{
|
||||||
|
// We must save the size of the pending packet until we can receive its content
|
||||||
|
if (Status == Socket::NotReady)
|
||||||
|
myPendingPacketSize = PacketSize;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append it into the packet
|
||||||
|
if ((Sender == Address) && (Received > 0))
|
||||||
|
{
|
||||||
|
myPendingPacket.resize(myPendingPacket.size() + Received);
|
||||||
|
char* Begin = &myPendingPacket[0] + myPendingPacket.size() - Received;
|
||||||
|
memcpy(Begin, Buffer, Received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have received all the datas : we can copy it to the user packet, and clear our internal packet
|
||||||
|
PacketToReceive.Clear();
|
||||||
|
if (!myPendingPacket.empty())
|
||||||
|
PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
|
||||||
|
myPendingPacket.clear();
|
||||||
|
myPendingPacketSize = -1;
|
||||||
|
|
||||||
|
return Socket::Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::Close()
|
||||||
|
{
|
||||||
|
if (IsValid())
|
||||||
|
{
|
||||||
|
if (!SocketHelper::Close(mySocket))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to close socket" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mySocket = SocketHelper::InvalidSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
myPort = 0;
|
||||||
|
myIsBlocking = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Check if the socket is in a valid state ; this function
|
||||||
|
/// can be called any time to check if the socket is OK
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::IsValid() const
|
||||||
|
{
|
||||||
|
return mySocket != SocketHelper::InvalidSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port the socket is currently bound to
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short SocketUDP::GetPort() const
|
||||||
|
{
|
||||||
|
return myPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator ==
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::operator ==(const SocketUDP& Other) const
|
||||||
|
{
|
||||||
|
return mySocket == Other.mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator !=
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::operator !=(const SocketUDP& Other) const
|
||||||
|
{
|
||||||
|
return mySocket != Other.mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Comparison operator <.
|
||||||
|
/// Provided for compatibility with standard containers, as
|
||||||
|
/// comparing two sockets doesn't make much sense...
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketUDP::operator <(const SocketUDP& Other) const
|
||||||
|
{
|
||||||
|
return mySocket < Other.mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct the socket from a socket descriptor
|
||||||
|
/// (for internal use only)
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketUDP::SocketUDP(SocketHelper::SocketType Descriptor)
|
||||||
|
{
|
||||||
|
Create(Descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Create the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketUDP::Create(SocketHelper::SocketType Descriptor)
|
||||||
|
{
|
||||||
|
// Use the given socket descriptor, or get a new one
|
||||||
|
mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
myIsBlocking = true;
|
||||||
|
|
||||||
|
// Clear the last port used
|
||||||
|
myPort = 0;
|
||||||
|
|
||||||
|
// Reset the pending packet
|
||||||
|
myPendingPacket.clear();
|
||||||
|
myPendingPacketSize = -1;
|
||||||
|
|
||||||
|
// Setup default options
|
||||||
|
if (IsValid())
|
||||||
|
{
|
||||||
|
// To avoid the "Address already in use" error message when trying to bind to the same port
|
||||||
|
int Yes = 1;
|
||||||
|
if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to set socket option \"reuse address\" ; "
|
||||||
|
<< "binding to a same port may fail if too fast" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable broadcast by default
|
||||||
|
if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to enable broadcast on UDP socket" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set blocking by default (should always be the case anyway)
|
||||||
|
SetBlocking(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,83 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Return the value of the invalid socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHelper::SocketType SocketHelper::InvalidSocket()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close / destroy a socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketHelper::Close(SocketHelper::SocketType Socket)
|
||||||
|
{
|
||||||
|
return close(Socket) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set a socket as blocking or non-blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketHelper::SetBlocking(SocketHelper::SocketType Socket, bool Block)
|
||||||
|
{
|
||||||
|
int Status = fcntl(Socket, F_GETFL);
|
||||||
|
if (Block)
|
||||||
|
fcntl(Socket, F_SETFL, Status & ~O_NONBLOCK);
|
||||||
|
else
|
||||||
|
fcntl(Socket, F_SETFL, Status | O_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the last socket error status
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketHelper::GetErrorStatus()
|
||||||
|
{
|
||||||
|
switch (errno)
|
||||||
|
{
|
||||||
|
case EWOULDBLOCK : return Socket::NotReady;
|
||||||
|
case ECONNABORTED : return Socket::Disconnected;
|
||||||
|
case ECONNRESET : return Socket::Disconnected;
|
||||||
|
case ETIMEDOUT : return Socket::Disconnected;
|
||||||
|
case ENETRESET : return Socket::Disconnected;
|
||||||
|
case ENOTCONN : return Socket::Disconnected;
|
||||||
|
default : return Socket::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -0,0 +1,100 @@
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied warranty.
|
||||||
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
//
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it freely,
|
||||||
|
// subject to the following restrictions:
|
||||||
|
//
|
||||||
|
// 1. The origin of this software must not be misrepresented;
|
||||||
|
// you must not claim that you wrote the original software.
|
||||||
|
// If you use this software in a product, an acknowledgment
|
||||||
|
// in the product documentation would be appreciated but is not required.
|
||||||
|
//
|
||||||
|
// 2. Altered source versions must be plainly marked as such,
|
||||||
|
// and must not be misrepresented as being the original software.
|
||||||
|
//
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketHelper.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Return the value of the invalid socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHelper::SocketType SocketHelper::InvalidSocket()
|
||||||
|
{
|
||||||
|
return INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Close / destroy a socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketHelper::Close(SocketHelper::SocketType Socket)
|
||||||
|
{
|
||||||
|
return closesocket(Socket) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Set a socket as blocking or non-blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketHelper::SetBlocking(SocketHelper::SocketType Socket, bool Block)
|
||||||
|
{
|
||||||
|
unsigned long Blocking = Block ? 0 : 1;
|
||||||
|
ioctlsocket(Socket, FIONBIO, &Blocking);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the last socket error status
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status SocketHelper::GetErrorStatus()
|
||||||
|
{
|
||||||
|
switch (WSAGetLastError())
|
||||||
|
{
|
||||||
|
case WSAEWOULDBLOCK : return Socket::NotReady;
|
||||||
|
case WSAECONNABORTED : return Socket::Disconnected;
|
||||||
|
case WSAECONNRESET : return Socket::Disconnected;
|
||||||
|
case WSAETIMEDOUT : return Socket::Disconnected;
|
||||||
|
case WSAENETRESET : return Socket::Disconnected;
|
||||||
|
case WSAENOTCONN : return Socket::Disconnected;
|
||||||
|
default : return Socket::Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Windows needs some initialization and cleanup to get
|
||||||
|
// sockets working properly... so let's create a class that will
|
||||||
|
// do it automatically
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct SocketInitializer
|
||||||
|
{
|
||||||
|
SocketInitializer()
|
||||||
|
{
|
||||||
|
WSADATA InitData;
|
||||||
|
WSAStartup(MAKEWORD(2,2), &InitData);
|
||||||
|
}
|
||||||
|
|
||||||
|
~SocketInitializer()
|
||||||
|
{
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SocketInitializer GlobalInitializer;
|
||||||
|
|
||||||
|
} // namespace sf
|
|
@ -182,6 +182,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSPSpy", "DSPSpy\DSPSpy.vcp
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SOIL", "..\Externals\SOIL\SOIL.vcproj", "{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SOIL", "..\Externals\SOIL\SOIL.vcproj", "{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SFML_Network", "..\Externals\SFML\build\vc2008\sfml-network.vcproj", "{823DDC98-42D5-4A38-88CF-9DC06C788AE4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
|
@ -604,6 +606,20 @@ Global
|
||||||
{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}.Release|Win32.Build.0 = Release|Win32
|
{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}.Release|Win32.Build.0 = Release|Win32
|
||||||
{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}.Release|x64.ActiveCfg = Release|x64
|
{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}.Release|x64.Build.0 = Release|x64
|
{C0B84DA9-FF15-4FAB-9590-17132F3C6DE4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.DebugFast|Win32.ActiveCfg = Debug|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.DebugFast|x64.ActiveCfg = Debug|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.DebugFast|x64.Build.0 = Debug|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release_JITIL|Win32.ActiveCfg = Release|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release_JITIL|x64.ActiveCfg = Release|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release_JITIL|x64.Build.0 = Release|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{823DDC98-42D5-4A38-88CF-9DC06C788AE4}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
Loading…
Reference in New Issue