mirror of
https://github.com/SFML/SFML.git
synced 2025-03-04 02:48:04 +08:00
FS#86 - Rewrite the sockets API
Updated the API documentation of the whole network module The system headers are no longer included by the sfml-network public headers git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1475 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
a09ee0f9e3
commit
9280771665
@ -243,49 +243,57 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\Selector.cpp"
|
RelativePath="..\..\src\SFML\Network\SocketSelector.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Selector.h"
|
RelativePath="..\..\include\SFML\Network\SocketSelector.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SelectorStruct.h"
|
RelativePath="..\..\src\SFML\Network\SocketSelectorStruct.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketStatus.h"
|
RelativePath="..\..\src\SFML\Network\TcpListener.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketTCP.cpp"
|
RelativePath="..\..\include\SFML\Network\TcpListener.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketTCP.h"
|
RelativePath="..\..\src\SFML\Network\TcpListenerStruct.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketTCPStruct.h"
|
RelativePath="..\..\src\SFML\Network\TcpSocket.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketUDP.cpp"
|
RelativePath="..\..\include\SFML\Network\TcpSocket.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketUDP.h"
|
RelativePath="..\..\src\SFML\Network\TcpSocketStruct.h"
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\src\SFML\Network\SocketUDPStruct.h"
|
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Types.h"
|
RelativePath="..\..\include\SFML\Network\Types.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\UdpSocket.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\UdpSocket.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\UdpSocketStruct.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
</Globals>
|
</Globals>
|
||||||
|
@ -242,15 +242,15 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\Selector.cpp"
|
RelativePath="..\..\src\SFML\Network\SocketSelector.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Selector.h"
|
RelativePath="..\..\include\SFML\Network\SocketSelector.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SelectorStruct.h"
|
RelativePath="..\..\src\SFML\Network\SocketSelectorStruct.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
@ -258,33 +258,45 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketTCP.cpp"
|
RelativePath="..\..\src\SFML\Network\TcpListener.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketTCP.h"
|
RelativePath="..\..\include\SFML\Network\TcpListener.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketTCPStruct.h"
|
RelativePath="..\..\src\SFML\Network\TcpListenerStruct.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketUDP.cpp"
|
RelativePath="..\..\src\SFML\Network\TcpSocket.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketUDP.h"
|
RelativePath="..\..\include\SFML\Network\TcpSocket.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketUDPStruct.h"
|
RelativePath="..\..\src\SFML\Network\TcpSocketStruct.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Types.h"
|
RelativePath="..\..\include\SFML\Network\Types.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\UdpSocket.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\UdpSocket.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\UdpSocketStruct.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
</Globals>
|
</Globals>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
<CodeBlocks_workspace_file>
|
<CodeBlocks_workspace_file>
|
||||||
<Workspace title="CSFML workspace">
|
<Workspace title="CSFML workspace">
|
||||||
<Project filename="csfml-main.cbp" active="1" />
|
<Project filename="csfml-main.cbp" />
|
||||||
<Project filename="csfml-system.cbp" />
|
<Project filename="csfml-system.cbp" />
|
||||||
<Project filename="csfml-window.cbp" />
|
<Project filename="csfml-window.cbp" />
|
||||||
<Project filename="csfml-graphics.cbp" />
|
<Project filename="csfml-graphics.cbp" />
|
||||||
<Project filename="csfml-audio.cbp" />
|
<Project filename="csfml-audio.cbp" />
|
||||||
<Project filename="csfml-network.cbp" />
|
<Project filename="csfml-network.cbp" active="1" />
|
||||||
</Workspace>
|
</Workspace>
|
||||||
</CodeBlocks_workspace_file>
|
</CodeBlocks_workspace_file>
|
||||||
|
@ -58,11 +58,14 @@
|
|||||||
<Unit filename="..\..\include\SFML\Network\Http.h" />
|
<Unit filename="..\..\include\SFML\Network\Http.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\IpAddress.h" />
|
<Unit filename="..\..\include\SFML\Network\IpAddress.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Packet.h" />
|
<Unit filename="..\..\include\SFML\Network\Packet.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Selector.h" />
|
<Unit filename="..\..\include\SFML\Network\SocketSelector.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SocketStatus.h" />
|
<Unit filename="..\..\include\SFML\Network\SocketStatus.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SocketTCP.h" />
|
<Unit filename="..\..\include\SFML\Network\SocketTCP.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SocketUDP.h" />
|
<Unit filename="..\..\include\SFML\Network\SocketUDP.h" />
|
||||||
|
<Unit filename="..\..\include\SFML\Network\TcpListener.h" />
|
||||||
|
<Unit filename="..\..\include\SFML\Network\TcpSocket.h" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Types.h" />
|
<Unit filename="..\..\include\SFML\Network\Types.h" />
|
||||||
|
<Unit filename="..\..\include\SFML\Network\UdpSocket.h" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Ftp.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Ftp.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\FtpStruct.h" />
|
<Unit filename="..\..\src\SFML\Network\FtpStruct.h" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Http.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Http.cpp" />
|
||||||
@ -70,12 +73,14 @@
|
|||||||
<Unit filename="..\..\src\SFML\Network\IpAddress.cpp" />
|
<Unit filename="..\..\src\SFML\Network\IpAddress.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Packet.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Packet.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\PacketStruct.h" />
|
<Unit filename="..\..\src\SFML\Network\PacketStruct.h" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Selector.cpp" />
|
<Unit filename="..\..\src\SFML\Network\SocketSelector.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SelectorStruct.h" />
|
<Unit filename="..\..\src\SFML\Network\SocketSelectorStruct.h" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SocketTCP.cpp" />
|
<Unit filename="..\..\src\SFML\Network\TcpListener.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SocketTCPStruct.h" />
|
<Unit filename="..\..\src\SFML\Network\TcpListenerStruct.h" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SocketUDP.cpp" />
|
<Unit filename="..\..\src\SFML\Network\TcpSocket.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SocketUDPStruct.h" />
|
<Unit filename="..\..\src\SFML\Network\TcpSocketStruct.h" />
|
||||||
|
<Unit filename="..\..\src\SFML\Network\UdpSocket.cpp" />
|
||||||
|
<Unit filename="..\..\src\SFML\Network\UdpSocketStruct.h" />
|
||||||
<Extensions>
|
<Extensions>
|
||||||
<code_completion />
|
<code_completion />
|
||||||
<envvars />
|
<envvars />
|
||||||
|
@ -32,9 +32,10 @@
|
|||||||
#include <SFML/System.h>
|
#include <SFML/System.h>
|
||||||
#include <SFML/Network/IpAddress.h>
|
#include <SFML/Network/IpAddress.h>
|
||||||
#include <SFML/Network/Packet.h>
|
#include <SFML/Network/Packet.h>
|
||||||
#include <SFML/Network/Selector.h>
|
#include <SFML/Network/SocketSelector.h>
|
||||||
#include <SFML/Network/SocketTCP.h>
|
#include <SFML/Network/TcpListener.h>
|
||||||
#include <SFML/Network/SocketUDP.h>
|
#include <SFML/Network/TcpSocket.h>
|
||||||
|
#include <SFML/Network/UdpSocket.h>
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_NETWORK_H
|
#endif // SFML_NETWORK_H
|
||||||
|
@ -383,7 +383,7 @@ CSFML_API sfFtpResponse* sfFtp_ParentDirectory(sfFtp* ftp);
|
|||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfFtpResponse* sfFtp_MakeDirectory(sfFtp* ftp, const char* name);
|
CSFML_API sfFtpResponse* sfFtp_CreateDirectory(sfFtp* ftp, const char* name);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove an existing directory
|
/// Remove an existing directory
|
||||||
|
@ -123,7 +123,7 @@ CSFML_API void sfHttpRequest_SetMethod(sfHttpRequest* httpRequest, sfHttpMethod
|
|||||||
/// \param URI : URI to request, local to the host
|
/// \param URI : URI to request, local to the host
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfHttpRequest_SetURI(sfHttpRequest* httpRequest, const char* URI);
|
CSFML_API void sfHttpRequest_SetUri(sfHttpRequest* httpRequest, const char* uri);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the HTTP version of the request.
|
/// Set the HTTP version of the request.
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SELECTOR_H
|
#ifndef SFML_SOCKETSELECTOR_H
|
||||||
#define SFML_SELECTOR_H
|
#define SFML_SOCKETSELECTOR_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
@ -38,8 +38,7 @@
|
|||||||
/// \return A new sfSelector object
|
/// \return A new sfSelector object
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSelectorTCP* sfSelectorTCP_Create();
|
CSFML_API sfSocketSelector* sfSocketSelector_Create();
|
||||||
CSFML_API sfSelectorUDP* sfSelectorUDP_Create();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Copy an existing selector
|
/// Copy an existing selector
|
||||||
@ -49,8 +48,7 @@ CSFML_API sfSelectorUDP* sfSelectorUDP_Create();
|
|||||||
/// \return Copied object
|
/// \return Copied object
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSelectorTCP* sfSelectorTCP_Copy(sfSelectorTCP* selector);
|
CSFML_API sfSocketSelector* sfSocketSelector_Copy(sfSocketSelector* selector);
|
||||||
CSFML_API sfSelectorUDP* sfSelectorUDP_Copy(sfSelectorUDP* selector);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destroy an existing selector
|
/// Destroy an existing selector
|
||||||
@ -58,8 +56,7 @@ CSFML_API sfSelectorUDP* sfSelectorUDP_Copy(sfSelectorUDP* selector);
|
|||||||
/// \param selector : Selector to delete
|
/// \param selector : Selector to delete
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSelectorTCP_Destroy(sfSelectorTCP* selector);
|
CSFML_API void sfSocketSelector_Destroy(sfSocketSelector* selector);
|
||||||
CSFML_API void sfSelectorUDP_Destroy(sfSelectorUDP* selector);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Add a socket to watch to a selector
|
/// Add a socket to watch to a selector
|
||||||
@ -68,8 +65,9 @@ CSFML_API void sfSelectorUDP_Destroy(sfSelectorUDP* selector);
|
|||||||
/// \param socket : Socket to add
|
/// \param socket : Socket to add
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSelectorTCP_Add(sfSelectorTCP* selector, sfSocketTCP* socket);
|
CSFML_API void sfSocketSelector_AddTcpListener(sfSocketSelector* selector, sfTcpListener* socket);
|
||||||
CSFML_API void sfSelectorUDP_Add(sfSelectorUDP* selector, sfSocketUDP* socket);
|
CSFML_API void sfSocketSelector_AddTcpSocket(sfSocketSelector* selector, sfTcpSocket* socket);
|
||||||
|
CSFML_API void sfSocketSelector_AddUdpSocket(sfSocketSelector* selector, sfUdpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove a socket from a selector
|
/// Remove a socket from a selector
|
||||||
@ -78,8 +76,9 @@ CSFML_API void sfSelectorUDP_Add(sfSelectorUDP* selector, sfSocketUDP* socket);
|
|||||||
/// \param socket : Socket to remove
|
/// \param socket : Socket to remove
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSelectorTCP_Remove(sfSelectorTCP* selector, sfSocketTCP* socket);
|
CSFML_API void sfSocketSelector_RemoveTcpListener(sfSocketSelector* selector, sfTcpListener* socket);
|
||||||
CSFML_API void sfSelectorUDP_Remove(sfSelectorUDP* selector, sfSocketUDP* socket);
|
CSFML_API void sfSocketSelector_RemoveTcpSocket(sfSocketSelector* selector, sfTcpSocket* socket);
|
||||||
|
CSFML_API void sfSocketSelector_RemoveUdpSocket(sfSocketSelector* selector, sfUdpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove all sockets from a selector
|
/// Remove all sockets from a selector
|
||||||
@ -87,36 +86,33 @@ CSFML_API void sfSelectorUDP_Remove(sfSelectorUDP* selector, sfSocketUDP* socket
|
|||||||
/// \param selector : Selector to remove the socket from
|
/// \param selector : Selector to remove the socket from
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSelectorTCP_Clear(sfSelectorTCP* selector);
|
CSFML_API void sfSocketSelector_Clear(sfSocketSelector* selector);
|
||||||
CSFML_API void sfSelectorUDP_Clear(sfSelectorUDP* selector);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Wait and collect sockets which are ready for reading.
|
/// Wait and collect sockets which are ready for reading.
|
||||||
/// This functions will return either when at least one socket
|
/// This functions will return either when at least one socket
|
||||||
/// is ready, or when the given time is out
|
/// is ready, or when the given timeout is over
|
||||||
///
|
///
|
||||||
/// \param selector : Selector to check
|
/// \param selector : Selector to check
|
||||||
/// \param timeout : Maximum time to wait, in seconds (0 to disable timeout)
|
/// \param timeout : Maximum time to wait, in seconds (0 to disable timeout)
|
||||||
///
|
///
|
||||||
/// \return Number of sockets ready
|
/// \return sfTrue if there are sockets ready, sfFalse otherwise
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API unsigned int sfSelectorTCP_Wait(sfSelectorTCP* selector, float timeout);
|
CSFML_API sfBool sfSocketSelector_Wait(sfSocketSelector* selector, float timeout);
|
||||||
CSFML_API unsigned int sfSelectorUDP_Wait(sfSelectorUDP* selector, float timeout);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// After a call to Wait(), get the Index-th socket which is
|
/// Test a socket to know if it is ready to receive data
|
||||||
/// ready for reading. The total number of sockets ready
|
|
||||||
/// is the integer returned by the previous call to Wait()
|
|
||||||
///
|
///
|
||||||
/// \param selector : Selector to check
|
/// \param selector : Selector to check
|
||||||
/// \param index : Index of the socket to get
|
/// \param socket : Socket to test
|
||||||
///
|
///
|
||||||
/// \return The Index-th socket
|
/// \return sfTrue if the socket is ready to receive data
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketTCP* sfSelectorTCP_GetSocketReady(const sfSelectorTCP* selector, unsigned int index);
|
CSFML_API sfBool sfSocketSelector_IsTcpListenerReady(const sfSocketSelector* selector, sfTcpListener* socket);
|
||||||
CSFML_API sfSocketUDP* sfSelectorUDP_GetSocketReady(const sfSelectorUDP* selector, unsigned int index);
|
CSFML_API sfBool sfSocketSelector_IsTcpSocketReady(const sfSocketSelector* selector, sfTcpSocket* socket);
|
||||||
|
CSFML_API sfBool sfSocketSelector_IsUdpSocketReady(const sfSocketSelector* selector, sfUdpSocket* socket);
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SELECTOR_H
|
#endif // SFML_SOCKETSELECTOR_H
|
97
CSFML/include/SFML/Network/TcpListener.h
Normal file
97
CSFML/include/SFML/Network/TcpListener.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_TCPLISTENER_H
|
||||||
|
#define SFML_TCPLISTENER_H
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.h>
|
||||||
|
#include <SFML/Network/SocketStatus.h>
|
||||||
|
#include <SFML/Network/Types.h>
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct a new TCP socket
|
||||||
|
///
|
||||||
|
/// \return Pointer to the new socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfTcpListener* sfTcpListener_Create();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Destroy an existing TCP socket
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to destroy
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API void sfTcpListener_Destroy(sfTcpListener* socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the blocking state of a TCP socket.
|
||||||
|
/// The default behaviour of a socket is blocking
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to modify
|
||||||
|
/// \param blocking : Pass sfTrue to set the socket as blocking, or sfFalse for non-blocking
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API void sfTcpListener_SetBlocking(sfTcpListener* socket, sfBool blocking);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the blocking state of the socket
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \Return sfTrue if the socket is blocking, sfFalse otherwise
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfBool sfTcpListener_IsBlocking(const sfTcpListener* socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Listen to a specified port for incoming data or connections
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to use for listening
|
||||||
|
/// \param port : Port to listen to
|
||||||
|
///
|
||||||
|
/// \return Socket status
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfSocketStatus sfTcpListener_Listen(sfTcpListener* socket, unsigned short port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait for a connection (must be listening to a port).
|
||||||
|
/// This function is blocking, ie. it won't return before
|
||||||
|
/// a connection has been accepted
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to use for accepting
|
||||||
|
/// \param connected : Pointer to a socket pointer that will be filled with the connected client
|
||||||
|
///
|
||||||
|
/// \return Socket status
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfSocketStatus sfTcpListener_Accept(sfTcpListener* socket, sfTcpSocket** connected);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_TCPLISTENER_H
|
@ -22,8 +22,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETTCP_H
|
#ifndef SFML_TCPSOCKET_H
|
||||||
#define SFML_SOCKETTCP_H
|
#define SFML_TCPSOCKET_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
@ -40,17 +40,7 @@
|
|||||||
/// \return Pointer to the new socket
|
/// \return Pointer to the new socket
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketTCP* sfSocketTCP_Create();
|
CSFML_API sfTcpSocket* sfTcpSocket_Create();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Copy an existing TCP socket
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to copy
|
|
||||||
///
|
|
||||||
/// \return Copied object
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfSocketTCP* sfSocketTCP_Copy(sfSocketTCP* socket);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destroy an existing TCP socket
|
/// Destroy an existing TCP socket
|
||||||
@ -58,7 +48,7 @@ CSFML_API sfSocketTCP* sfSocketTCP_Copy(sfSocketTCP* socket);
|
|||||||
/// \param socket : Socket to destroy
|
/// \param socket : Socket to destroy
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSocketTCP_Destroy(sfSocketTCP* socket);
|
CSFML_API void sfTcpSocket_Destroy(sfTcpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Change the blocking state of a TCP socket.
|
/// Change the blocking state of a TCP socket.
|
||||||
@ -68,45 +58,68 @@ CSFML_API void sfSocketTCP_Destroy(sfSocketTCP* socket);
|
|||||||
/// \param blocking : Pass sfTrue to set the socket as blocking, or false for non-blocking
|
/// \param blocking : Pass sfTrue to set the socket as blocking, or false for non-blocking
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSocketTCP_SetBlocking(sfSocketTCP* socket, sfBool blocking);
|
CSFML_API void sfTcpSocket_SetBlocking(sfTcpSocket* socket, sfBool blocking);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the blocking state of the socket
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \Return sfTrue if the socket is blocking, sfFalse otherwise
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfBool sfTcpSocket_IsBlocking(const sfTcpSocket* socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port to which a socket is bound locally
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \return Port to which the socket is bound
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API unsigned short sfTcpSocket_GetLocalPort(const sfTcpSocket* socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the address of the connected peer of a socket
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \return Address of the remote peer
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfIpAddress sfTcpSocket_GetRemoteAddress(const sfTcpSocket* socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port of the connected peer to which a socket is connected
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \return Remote port to which the socket is connected
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API unsigned short sfTcpSocket_GetRemotePort(const sfTcpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Connect a TCP socket to another computer on a specified port
|
/// Connect a TCP socket to another computer on a specified port
|
||||||
///
|
///
|
||||||
/// \param socket : Socket to use for connecting
|
/// \param socket : Socket to connect
|
||||||
/// \param port : Port to use for transfers (warning : ports < 1024 are reserved)
|
|
||||||
/// \param host : IP Address of the host to connect to
|
/// \param host : IP Address of the host to connect to
|
||||||
|
/// \param port : Port to use for transfers (warning : ports < 1024 are reserved)
|
||||||
/// \param timeout : Maximum time to wait (0 to use no timeout)
|
/// \param timeout : Maximum time to wait (0 to use no timeout)
|
||||||
///
|
///
|
||||||
/// \return sfTrue if operation has been successful
|
/// \return sfTrue if operation has been successful
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketTCP_Connect(sfSocketTCP* socket, unsigned short port, sfIpAddress host, float timeout);
|
CSFML_API sfSocketStatus sfTcpSocket_Connect(sfTcpSocket* socket, sfIpAddress host, unsigned short port, float timeout);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Listen to a specified port for incoming data or connections
|
/// Disconnect a connect from its remote peer
|
||||||
///
|
///
|
||||||
/// \param socket : Socket to use for listening
|
/// \param socket : Socket to disconnect
|
||||||
/// \param port : Port to listen to
|
|
||||||
///
|
|
||||||
/// \return sfTrue if operation has been successful
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfBool sfSocketTCP_Listen(sfSocketTCP* socket, unsigned short port);
|
CSFML_API void sfTcpSocket_Disconnect(sfTcpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Wait for a connection (must be listening to a port).
|
|
||||||
/// This function is blocking, ie. it won't return before
|
|
||||||
/// a connection has been accepted
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to use for accepting
|
|
||||||
/// \param connected : Pointer to a socket pointer that will be filled with the connected client
|
|
||||||
/// \param address : Pointer to an address to fill with client infos
|
|
||||||
///
|
|
||||||
/// \return Socket status
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfSocketStatus sfSocketTCP_Accept(sfSocketTCP* socket, sfSocketTCP** connected, sfIpAddress* address);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send an array of bytes to the host (must be connected first)
|
/// Send an array of bytes to the host (must be connected first)
|
||||||
@ -118,7 +131,7 @@ CSFML_API sfSocketStatus sfSocketTCP_Accept(sfSocketTCP* socket, sfSocketTCP** c
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketTCP_Send(sfSocketTCP* socket, const char* data, size_t size);
|
CSFML_API sfSocketStatus sfTcpSocket_Send(sfTcpSocket* socket, const char* data, size_t size);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive an array of bytes from the host (must be connected first)
|
/// Receive an array of bytes from the host (must be connected first)
|
||||||
@ -131,7 +144,7 @@ CSFML_API sfSocketStatus sfSocketTCP_Send(sfSocketTCP* socket, const char* data,
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketTCP_Receive(sfSocketTCP* socket, char* data, size_t maxSize, size_t* sizeReceived);
|
CSFML_API sfSocketStatus sfTcpSocket_Receive(sfTcpSocket* socket, char* data, size_t maxSize, size_t* sizeReceived);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send a packet of data to the host (must be connected first)
|
/// Send a packet of data to the host (must be connected first)
|
||||||
@ -142,7 +155,7 @@ CSFML_API sfSocketStatus sfSocketTCP_Receive(sfSocketTCP* socket, char* data, si
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketTCP_SendPacket(sfSocketTCP* socket, sfPacket* packet);
|
CSFML_API sfSocketStatus sfTcpSocket_SendPacket(sfTcpSocket* socket, sfPacket* packet);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive a packet from the host (must be connected first)
|
/// Receive a packet from the host (must be connected first)
|
||||||
@ -153,28 +166,7 @@ CSFML_API sfSocketStatus sfSocketTCP_SendPacket(sfSocketTCP* socket, sfPacket* p
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketTCP_ReceivePacket(sfSocketTCP* socket, sfPacket* packet);
|
CSFML_API sfSocketStatus sfTcpSocket_ReceivePacket(sfTcpSocket* socket, sfPacket* packet);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the socket
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to close
|
|
||||||
///
|
|
||||||
/// \return True if the socket was successfully closed
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfBool sfSocketTCP_Close(sfSocketTCP* socket);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Check if a socket is in a valid state ; this function
|
|
||||||
/// can be called any time to check if the socket is OK
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to check
|
|
||||||
///
|
|
||||||
/// \return True if the socket is valid
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfBool sfSocketTCP_IsValid(const sfSocketTCP* socket);
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETTCP_H
|
#endif // SFML_TCPSOCKET_H
|
@ -34,10 +34,10 @@ typedef struct sfHttpRequest sfHttpRequest;
|
|||||||
typedef struct sfHttpResponse sfHttpResponse;
|
typedef struct sfHttpResponse sfHttpResponse;
|
||||||
typedef struct sfHttp sfHttp;
|
typedef struct sfHttp sfHttp;
|
||||||
typedef struct sfPacket sfPacket;
|
typedef struct sfPacket sfPacket;
|
||||||
typedef struct sfSelectorTCP sfSelectorTCP;
|
typedef struct sfSocketSelector sfSocketSelector;
|
||||||
typedef struct sfSelectorUDP sfSelectorUDP;
|
typedef struct sfTcpListener sfTcpListener;
|
||||||
typedef struct sfSocketTCP sfSocketTCP;
|
typedef struct sfTcpSocket sfTcpSocket;
|
||||||
typedef struct sfSocketUDP sfSocketUDP;
|
typedef struct sfUdpSocket sfUdpSocket;
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_NETWORK_TYPES_H
|
#endif // SFML_NETWORK_TYPES_H
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETUDP_H
|
#ifndef SFML_UDPSOCKET_H
|
||||||
#define SFML_SOCKETUDP_H
|
#define SFML_UDPSOCKET_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
@ -40,17 +40,7 @@
|
|||||||
/// \return Pointer to the new socket
|
/// \return Pointer to the new socket
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketUDP* sfSocketUDP_Create();
|
CSFML_API sfUdpSocket* sfUdpSocket_Create();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Copy an existing UDP socket
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to copy
|
|
||||||
///
|
|
||||||
/// \return Copied object
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfSocketUDP* sfSocketUDP_Copy(sfSocketUDP* socket);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destroy an existing UDP socket
|
/// Destroy an existing UDP socket
|
||||||
@ -58,7 +48,7 @@ CSFML_API sfSocketUDP* sfSocketUDP_Copy(sfSocketUDP* socket);
|
|||||||
/// \param socket : Socket to destroy
|
/// \param socket : Socket to destroy
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSocketUDP_Destroy(sfSocketUDP* socket);
|
CSFML_API void sfUdpSocket_Destroy(sfUdpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Change the blocking state of a UDP socket.
|
/// Change the blocking state of a UDP socket.
|
||||||
@ -68,7 +58,27 @@ CSFML_API void sfSocketUDP_Destroy(sfSocketUDP* socket);
|
|||||||
/// \param blocking : Pass sfTrue to set the socket as blocking, or false for non-blocking
|
/// \param blocking : Pass sfTrue to set the socket as blocking, or false for non-blocking
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API void sfSocketUDP_SetBlocking(sfSocketUDP* socket, sfBool blocking);
|
CSFML_API void sfUdpSocket_SetBlocking(sfUdpSocket* socket, sfBool blocking);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the blocking state of the socket
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \Return sfTrue if the socket is blocking, sfFalse otherwise
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API sfBool sfUdpSocket_IsBlocking(const sfUdpSocket* socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port to which a socket is bound locally
|
||||||
|
///
|
||||||
|
/// \param socket : Socket to read
|
||||||
|
///
|
||||||
|
/// \return Port to which the socket is bound
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
CSFML_API unsigned short sfUdpSocket_GetLocalPort(const sfUdpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Bind a socket to a specific port
|
/// Bind a socket to a specific port
|
||||||
@ -76,20 +86,18 @@ CSFML_API void sfSocketUDP_SetBlocking(sfSocketUDP* socket, sfBool blocking);
|
|||||||
/// \param socket : Socket to bind
|
/// \param socket : Socket to bind
|
||||||
/// \param port : Port to bind the socket to
|
/// \param port : Port to bind the socket to
|
||||||
///
|
///
|
||||||
/// \return True if operation has been successful
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfBool sfSocketUDP_Bind(sfSocketUDP* socket, unsigned short port);
|
CSFML_API sfSocketStatus sfUdpSocket_Bind(sfUdpSocket* socket, unsigned short port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Unbind a socket from its previous port, if any
|
/// Unbind a socket from its previous port, if any
|
||||||
///
|
///
|
||||||
/// \param socket : Socket to unbind
|
/// \param socket : Socket to unbind
|
||||||
///
|
///
|
||||||
/// \return sfTrue if operation has been successful
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfBool sfSocketUDP_Unbind(sfSocketUDP* socket);
|
CSFML_API void sfUdpSocket_Unbind(sfUdpSocket* socket);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send an array of bytes
|
/// Send an array of bytes
|
||||||
@ -103,7 +111,7 @@ CSFML_API sfBool sfSocketUDP_Unbind(sfSocketUDP* socket);
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketUDP_Send(sfSocketUDP* socket, const char* data, size_t size, sfIpAddress address, unsigned short port);
|
CSFML_API sfSocketStatus sfUdpSocket_Send(sfUdpSocket* socket, const char* data, size_t size, sfIpAddress address, unsigned short port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive an array of bytes.
|
/// Receive an array of bytes.
|
||||||
@ -120,7 +128,7 @@ CSFML_API sfSocketStatus sfSocketUDP_Send(sfSocketUDP* socket, const char* data,
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketUDP_Receive(sfSocketUDP* socket, char* data, size_t maxSize, size_t* sizeReceived, sfIpAddress* address, unsigned short* port);
|
CSFML_API sfSocketStatus sfUdpSocket_Receive(sfUdpSocket* socket, char* data, size_t maxSize, size_t* sizeReceived, sfIpAddress* address, unsigned short* port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send a packet of data
|
/// Send a packet of data
|
||||||
@ -133,7 +141,7 @@ CSFML_API sfSocketStatus sfSocketUDP_Receive(sfSocketUDP* socket, char* data, si
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketUDP_SendPacket(sfSocketUDP* socket, sfPacket* packet, sfIpAddress address, unsigned short port);
|
CSFML_API sfSocketStatus sfUdpSocket_SendPacket(sfUdpSocket* socket, sfPacket* packet, sfIpAddress address, unsigned short port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive a packet.
|
/// Receive a packet.
|
||||||
@ -148,28 +156,7 @@ CSFML_API sfSocketStatus sfSocketUDP_SendPacket(sfSocketUDP* socket, sfPacket* p
|
|||||||
/// \return Socket status
|
/// \return Socket status
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
CSFML_API sfSocketStatus sfSocketUDP_ReceivePacket(sfSocketUDP* socket, sfPacket* packet, sfIpAddress* address, unsigned short* port);
|
CSFML_API sfSocketStatus sfUdpSocket_ReceivePacket(sfUdpSocket* socket, sfPacket* packet, sfIpAddress* address, unsigned short* port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the socket
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to close
|
|
||||||
///
|
|
||||||
/// \return True if the socket was successfully closed
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfBool sfSocketUDP_Close(sfSocketUDP* socket);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Check if a socket is in a valid state ; this function
|
|
||||||
/// can be called any time to check if the socket is OK
|
|
||||||
///
|
|
||||||
/// \param socket : Socket to check
|
|
||||||
///
|
|
||||||
/// \return sfTrue if the socket is valid
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
CSFML_API sfBool sfSocketUDP_IsValid(sfSocketUDP* socket);
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETUDP_H
|
#endif // SFML_UDPSOCKET_H
|
@ -39,6 +39,7 @@ void sfFtpListingResponse_Destroy(sfFtpListingResponse* ftpListingResponse)
|
|||||||
delete ftpListingResponse;
|
delete ftpListingResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Convenience function to check if the response status code
|
/// Convenience function to check if the response status code
|
||||||
/// means a success
|
/// means a success
|
||||||
@ -48,6 +49,7 @@ sfBool sfFtpListingResponse_IsOk(const sfFtpListingResponse* ftpListingResponse)
|
|||||||
CSFML_CALL_RETURN(ftpListingResponse, IsOk(), sfFalse);
|
CSFML_CALL_RETURN(ftpListingResponse, IsOk(), sfFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the response status code
|
/// Get the response status code
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -58,6 +60,7 @@ sfFtpStatus sfFtpListingResponse_GetStatus(const sfFtpListingResponse* ftpListin
|
|||||||
return static_cast<sfFtpStatus>(ftpListingResponse->This.GetStatus());
|
return static_cast<sfFtpStatus>(ftpListingResponse->This.GetStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the full message contained in the response
|
/// Get the full message contained in the response
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -68,14 +71,18 @@ const char* sfFtpListingResponse_GetMessage(const sfFtpListingResponse* ftpListi
|
|||||||
return ftpListingResponse->This.GetMessage().c_str();
|
return ftpListingResponse->This.GetMessage().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the number of filenames in the listing
|
/// Get the number of filenames in the listing
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
size_t sfFtpListingResponse_GetCount(const sfFtpListingResponse* ftpListingResponse)
|
size_t sfFtpListingResponse_GetCount(const sfFtpListingResponse* ftpListingResponse)
|
||||||
{
|
{
|
||||||
CSFML_CALL_RETURN(ftpListingResponse, GetCount(), 0);
|
CSFML_CHECK_RETURN(ftpListingResponse, 0);
|
||||||
|
|
||||||
|
return ftpListingResponse->This.GetFilenames().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the Index-th filename in the directory
|
/// Get the Index-th filename in the directory
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -83,7 +90,7 @@ const char* sfFtpListingResponse_GetFilename(const sfFtpListingResponse* ftpList
|
|||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(ftpListingResponse, NULL);
|
CSFML_CHECK_RETURN(ftpListingResponse, NULL);
|
||||||
|
|
||||||
return ftpListingResponse->This.GetFilename(index).c_str();
|
return ftpListingResponse->This.GetFilenames()[index].c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +102,7 @@ void sfFtpDirectoryResponse_Destroy(sfFtpDirectoryResponse* ftpDirectoryResponse
|
|||||||
delete ftpDirectoryResponse;
|
delete ftpDirectoryResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Convenience function to check if the response status code
|
/// Convenience function to check if the response status code
|
||||||
/// means a success
|
/// means a success
|
||||||
@ -104,6 +112,7 @@ sfBool sfFtpDirectoryResponse_IsOk(const sfFtpDirectoryResponse* ftpDirectoryRes
|
|||||||
CSFML_CALL_RETURN(ftpDirectoryResponse, IsOk(), sfFalse);
|
CSFML_CALL_RETURN(ftpDirectoryResponse, IsOk(), sfFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the response status code
|
/// Get the response status code
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -114,6 +123,7 @@ sfFtpStatus sfFtpDirectoryResponse_GetStatus(const sfFtpDirectoryResponse* ftpDi
|
|||||||
return static_cast<sfFtpStatus>(ftpDirectoryResponse->This.GetStatus());
|
return static_cast<sfFtpStatus>(ftpDirectoryResponse->This.GetStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the full message contained in the response
|
/// Get the full message contained in the response
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -124,6 +134,7 @@ const char* sfFtpDirectoryResponse_GetMessage(const sfFtpDirectoryResponse* ftpD
|
|||||||
return ftpDirectoryResponse->This.GetMessage().c_str();
|
return ftpDirectoryResponse->This.GetMessage().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the directory returned in the response
|
/// Get the directory returned in the response
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -299,11 +310,11 @@ sfFtpResponse* sfFtp_ParentDirectory(sfFtp* ftp)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create a new directory
|
/// Create a new directory
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfFtpResponse* sfFtp_MakeDirectory(sfFtp* ftp, const char* name)
|
sfFtpResponse* sfFtp_CreateDirectory(sfFtp* ftp, const char* name)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(ftp, NULL);
|
CSFML_CHECK_RETURN(ftp, NULL);
|
||||||
|
|
||||||
return new sfFtpResponse(ftp->This.MakeDirectory(name ? name : ""));
|
return new sfFtpResponse(ftp->This.CreateDirectory(name ? name : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/Ftp.hpp>
|
#include <SFML/Network/Ftp.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -78,7 +79,14 @@ struct sfFtpListingResponse
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~sfFtpListingResponse()
|
||||||
|
{
|
||||||
|
for (std::vector<const char*>::iterator it = Filenames.begin(); it != Filenames.end(); ++it)
|
||||||
|
delete[] *it;
|
||||||
|
}
|
||||||
|
|
||||||
sf::Ftp::ListingResponse This;
|
sf::Ftp::ListingResponse This;
|
||||||
|
std::vector<const char*> Filenames;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,9 +73,9 @@ void sfHttpRequest_SetMethod(sfHttpRequest* httpRequest, sfHttpMethod method)
|
|||||||
/// Set the target URI of the request.
|
/// Set the target URI of the request.
|
||||||
/// This parameter is "/" by default
|
/// This parameter is "/" by default
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfHttpRequest_SetURI(sfHttpRequest* httpRequest, const char* URI)
|
void sfHttpRequest_SetUri(sfHttpRequest* httpRequest, const char* uri)
|
||||||
{
|
{
|
||||||
CSFML_CALL(httpRequest, SetURI(URI ? URI : ""));
|
CSFML_CALL(httpRequest, SetUri(uri ? uri : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,73 +25,118 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/Selector.h>
|
#include <SFML/Network/SocketSelector.h>
|
||||||
#include <SFML/Network/SelectorStruct.h>
|
#include <SFML/Network/SocketSelectorStruct.h>
|
||||||
|
#include <SFML/Network/TcpListenerStruct.h>
|
||||||
|
#include <SFML/Network/TcpSocketStruct.h>
|
||||||
|
#include <SFML/Network/UdpSocketStruct.h>
|
||||||
#include <SFML/Internal.h>
|
#include <SFML/Internal.h>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create a new selector
|
/// Create a new selector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSelectorTCP* sfSelectorTCP_Create() {return new sfSelectorTCP;}
|
sfSocketSelector* sfSocketSelector_Create()
|
||||||
sfSelectorUDP* sfSelectorUDP_Create() {return new sfSelectorUDP;}
|
{
|
||||||
|
return new sfSocketSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Copy an existing selector
|
/// Copy an existing selector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSelectorTCP* sfSelectorTCP_Copy(sfSelectorTCP* selector) {CSFML_CHECK_RETURN(selector, NULL); return new sfSelectorTCP(*selector);}
|
sfSocketSelector* sfSocketSelector_Copy(sfSocketSelector* selector)
|
||||||
sfSelectorUDP* sfSelectorUDP_Copy(sfSelectorUDP* selector) {CSFML_CHECK_RETURN(selector, NULL); return new sfSelectorUDP(*selector);}
|
{
|
||||||
|
CSFML_CHECK_RETURN(selector, NULL);
|
||||||
|
|
||||||
|
return new sfSocketSelector(*selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destroy an existing selector
|
/// Destroy an existing selector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSelectorTCP_Destroy(sfSelectorTCP* selector) {delete selector;}
|
void sfSocketSelector_Destroy(sfSocketSelector* selector)
|
||||||
void sfSelectorUDP_Destroy(sfSelectorUDP* selector) {delete selector;}
|
{
|
||||||
|
delete selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Add a socket to watch to a selector
|
/// Add a socket to watch to a selector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSelectorTCP_Add(sfSelectorTCP* selector, sfSocketTCP* socket) {CSFML_CALL(selector, Add(socket->This)); selector->Sockets[socket->This] = socket;}
|
void sfSocketSelector_AddTcpListener(sfSocketSelector* selector, sfTcpListener* socket)
|
||||||
void sfSelectorUDP_Add(sfSelectorUDP* selector, sfSocketUDP* socket) {CSFML_CALL(selector, Add(socket->This)); selector->Sockets[socket->This] = socket;}
|
{
|
||||||
|
CSFML_CHECK(socket);
|
||||||
|
CSFML_CALL(selector, Add(socket->This));
|
||||||
|
}
|
||||||
|
void sfSocketSelector_AddTcpSocket(sfSocketSelector* selector, sfTcpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CHECK(socket);
|
||||||
|
CSFML_CALL(selector, Add(socket->This));
|
||||||
|
}
|
||||||
|
void sfSocketSelector_AddUdpSocket(sfSocketSelector* selector, sfUdpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CHECK(socket);
|
||||||
|
CSFML_CALL(selector, Add(socket->This));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove a socket from a selector
|
/// Remove a socket from a selector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSelectorTCP_Remove(sfSelectorTCP* selector, sfSocketTCP* socket) {CSFML_CALL(selector, Remove(socket->This)); selector->Sockets.erase(socket->This);}
|
void sfSocketSelector_RemoveTcpListener(sfSocketSelector* selector, sfTcpListener* socket)
|
||||||
void sfSelectorUDP_Remove(sfSelectorUDP* selector, sfSocketUDP* socket) {CSFML_CALL(selector, Remove(socket->This)); selector->Sockets.erase(socket->This);}
|
{
|
||||||
|
CSFML_CHECK(socket);
|
||||||
|
CSFML_CALL(selector, Remove(socket->This));
|
||||||
|
}
|
||||||
|
void sfSocketSelector_RemoveTcpSocket(sfSocketSelector* selector, sfTcpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CHECK(socket);
|
||||||
|
CSFML_CALL(selector, Remove(socket->This));
|
||||||
|
}
|
||||||
|
void sfSocketSelector_RemoveUdpSocket(sfSocketSelector* selector, sfUdpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CHECK(socket);
|
||||||
|
CSFML_CALL(selector, Remove(socket->This));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove all sockets from a selector
|
/// Remove all sockets from a selector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSelectorTCP_Clear(sfSelectorTCP* selector) {CSFML_CALL(selector, Clear()); selector->Sockets.clear();}
|
void sfSocketSelector_Clear(sfSocketSelector* selector)
|
||||||
void sfSelectorUDP_Clear(sfSelectorUDP* selector) {CSFML_CALL(selector, Clear()); selector->Sockets.clear();}
|
{
|
||||||
|
CSFML_CALL(selector, Clear());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Wait and collect sockets which are ready for reading.
|
/// Wait and collect sockets which are ready for reading.
|
||||||
/// This functions will return either when at least one socket
|
/// This functions will return either when at least one socket
|
||||||
/// is ready, or when the given time is out
|
/// is ready, or when the given timeout is over
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int sfSelectorTCP_Wait(sfSelectorTCP* selector, float timeout) {CSFML_CALL_RETURN(selector, Wait(timeout), 0);}
|
sfBool sfSocketSelector_Wait(sfSocketSelector* selector, float timeout)
|
||||||
unsigned int sfSelectorUDP_Wait(sfSelectorUDP* selector, float timeout) {CSFML_CALL_RETURN(selector, Wait(timeout), 0);}
|
{
|
||||||
|
CSFML_CALL_RETURN(selector, Wait(timeout), sfFalse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// After a call to Wait(), get the Index-th socket which is
|
/// Test a socket to know if it is ready to receive data
|
||||||
/// ready for reading. The total number of sockets ready
|
|
||||||
/// is the integer returned by the previous call to Wait()
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketTCP* sfSelectorTCP_GetSocketReady(const sfSelectorTCP* selector, unsigned int index)
|
sfBool sfSocketSelector_IsTcpListenerReady(const sfSocketSelector* selector, sfTcpListener* socket)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(selector, NULL);
|
CSFML_CHECK_RETURN(socket, sfFalse);
|
||||||
return selector->Sockets.find(selector->This.GetSocketReady(index))->second;
|
CSFML_CALL_RETURN(selector, IsReady(socket->This), sfFalse);
|
||||||
}
|
}
|
||||||
sfSocketUDP* sfSelectorUDP_GetSocketReady(const sfSelectorUDP* selector, unsigned int index)
|
sfBool sfSocketSelector_IsTcpSocketReady(const sfSocketSelector* selector, sfTcpSocket* socket)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(selector, NULL);
|
CSFML_CHECK_RETURN(socket, sfFalse);
|
||||||
return selector->Sockets.find(selector->This.GetSocketReady(index))->second;
|
CSFML_CALL_RETURN(selector, IsReady(socket->This), sfFalse);
|
||||||
|
}
|
||||||
|
sfBool sfSocketSelector_IsUdpSocketReady(const sfSocketSelector* selector, sfUdpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CHECK_RETURN(socket, sfFalse);
|
||||||
|
CSFML_CALL_RETURN(selector, IsReady(socket->This), sfFalse);
|
||||||
}
|
}
|
@ -22,36 +22,22 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SELECTORSTRUCT_H
|
#ifndef SFML_SOCKETSELECTORSTRUCT_H
|
||||||
#define SFML_SELECTORSTRUCT_H
|
#define SFML_SOCKETSELECTORSTRUCT_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/Selector.hpp>
|
#include <SFML/Network/SocketSelector.hpp>
|
||||||
#include <SFML/Network/SocketTCPStruct.h>
|
|
||||||
#include <SFML/Network/SocketUDPStruct.h>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Internal structure of SelectorTCP
|
// Internal structure of sfSocketSelector
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
struct sfSelectorTCP
|
struct sfSocketSelector
|
||||||
{
|
{
|
||||||
sf::SelectorTCP This;
|
sf::SocketSelector This;
|
||||||
std::map<sf::SocketTCP, sfSocketTCP*> Sockets;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
#endif // SFML_SOCKETSELECTORSTRUCT_H
|
||||||
// Internal structure of sfSelectorUDP
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
struct sfSelectorUDP
|
|
||||||
{
|
|
||||||
sf::SelectorUDP This;
|
|
||||||
std::map<sf::SocketUDP, sfSocketUDP*> Sockets;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SELECTORSTRUCT_H
|
|
94
CSFML/src/SFML/Network/TcpListener.cpp
Normal file
94
CSFML/src/SFML/Network/TcpListener.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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/TcpListener.h>
|
||||||
|
#include <SFML/Network/TcpListenerStruct.h>
|
||||||
|
#include <SFML/Network/TcpSocketStruct.h>
|
||||||
|
#include <SFML/Internal.h>
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Construct a new TCP socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfTcpListener* sfTcpListener_Create()
|
||||||
|
{
|
||||||
|
return new sfTcpListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Destroy an existing TCP socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void sfTcpListener_Destroy(sfTcpListener* socket)
|
||||||
|
{
|
||||||
|
delete socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Change the blocking state of a TCP socket.
|
||||||
|
/// The default behaviour of a socket is blocking
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void sfTcpListener_SetBlocking(sfTcpListener* socket, sfBool blocking)
|
||||||
|
{
|
||||||
|
CSFML_CALL(socket, SetBlocking(blocking == sfTrue));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the blocking state of the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfBool sfTcpListener_IsBlocking(const sfTcpListener* socket)
|
||||||
|
{
|
||||||
|
CSFML_CALL_RETURN(socket, IsBlocking(), sfFalse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Listen to a specified port for incoming data or connections
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfSocketStatus sfTcpListener_Listen(sfTcpListener* socket, unsigned short port)
|
||||||
|
{
|
||||||
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
|
||||||
|
return static_cast<sfSocketStatus>(socket->This.Listen(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Wait for a connection (must be listening to a port).
|
||||||
|
/// This function is blocking, ie. it won't return before
|
||||||
|
/// a connection has been accepted
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfSocketStatus sfTcpListener_Accept(sfTcpListener* socket, sfTcpSocket** connected)
|
||||||
|
{
|
||||||
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
CSFML_CHECK_RETURN(connected, sfSocketError);
|
||||||
|
|
||||||
|
*connected = new sfTcpSocket;
|
||||||
|
return static_cast<sfSocketStatus>(socket->This.Accept((*connected)->This));
|
||||||
|
}
|
43
CSFML/src/SFML/Network/TcpListenerStruct.h
Normal file
43
CSFML/src/SFML/Network/TcpListenerStruct.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_TCPLISTENERSTRUCT_H
|
||||||
|
#define SFML_TCPLISTENERSTRUCT_H
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/TcpListener.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Internal structure of sfTcpListener
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct sfTcpListener
|
||||||
|
{
|
||||||
|
sf::TcpListener This;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_TCPLISTENERSTRUCT_H
|
@ -25,8 +25,8 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SocketTCP.h>
|
#include <SFML/Network/TcpSocket.h>
|
||||||
#include <SFML/Network/SocketTCPStruct.h>
|
#include <SFML/Network/TcpSocketStruct.h>
|
||||||
#include <SFML/Network/PacketStruct.h>
|
#include <SFML/Network/PacketStruct.h>
|
||||||
#include <SFML/Network/IpAddress.hpp>
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
#include <SFML/Internal.h>
|
#include <SFML/Internal.h>
|
||||||
@ -36,33 +36,18 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Construct a new TCP socket
|
/// Construct a new TCP socket
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketTCP* sfSocketTCP_Create()
|
sfTcpSocket* sfTcpSocket_Create()
|
||||||
{
|
{
|
||||||
return new sfSocketTCP;
|
return new sfTcpSocket;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Copy an existing TCP socket
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfSocketTCP* sfSocketTCP_Copy(sfSocketTCP* socket)
|
|
||||||
{
|
|
||||||
CSFML_CHECK_RETURN(socket, NULL);
|
|
||||||
|
|
||||||
return new sfSocketTCP(*socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destroy an existing TCP socket
|
/// Destroy an existing TCP socket
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSocketTCP_Destroy(sfSocketTCP* socket)
|
void sfTcpSocket_Destroy(sfTcpSocket* socket)
|
||||||
{
|
{
|
||||||
if (socket)
|
delete socket;
|
||||||
{
|
|
||||||
socket->This.Close();
|
|
||||||
delete socket;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,67 +55,80 @@ void sfSocketTCP_Destroy(sfSocketTCP* socket)
|
|||||||
/// Change the blocking state of a TCP socket.
|
/// Change the blocking state of a TCP socket.
|
||||||
/// The default behaviour of a socket is blocking
|
/// The default behaviour of a socket is blocking
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSocketTCP_SetBlocking(sfSocketTCP* socket, sfBool blocking)
|
void sfTcpSocket_SetBlocking(sfTcpSocket* socket, sfBool blocking)
|
||||||
{
|
{
|
||||||
CSFML_CALL(socket, SetBlocking(blocking == sfTrue));
|
CSFML_CALL(socket, SetBlocking(blocking == sfTrue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the blocking state of the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfBool sfTcpSocket_IsBlocking(const sfTcpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CALL_RETURN(socket, IsBlocking(), sfFalse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port to which a socket is bound locally
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short sfTcpSocket_GetLocalPort(const sfTcpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CALL_RETURN(socket, GetLocalPort(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the address of the connected peer of a socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfIpAddress sfTcpSocket_GetRemoteAddress(const sfTcpSocket* socket)
|
||||||
|
{
|
||||||
|
sfIpAddress result;
|
||||||
|
CSFML_CHECK_RETURN(socket, result);
|
||||||
|
|
||||||
|
sf::IpAddress address = socket->This.GetRemoteAddress();
|
||||||
|
strncpy(result.Address, address.ToString().c_str(), 16);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port of the connected peer to which a socket is connected
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short sfTcpSocket_GetRemotePort(const sfTcpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CALL_RETURN(socket, GetRemotePort(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Connect a TCP socket to another computer on a specified port
|
/// Connect a TCP socket to another computer on a specified port
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketTCP_Connect(sfSocketTCP* socket, unsigned short port, sfIpAddress host, float timeout)
|
sfSocketStatus sfTcpSocket_Connect(sfTcpSocket* socket, sfIpAddress host, unsigned short port, float timeout)
|
||||||
{
|
{
|
||||||
sf::IpAddress address(host.Address);
|
sf::IpAddress address(host.Address);
|
||||||
|
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
|
||||||
return static_cast<sfSocketStatus>(socket->This.Connect(port, address, timeout));
|
return static_cast<sfSocketStatus>(socket->This.Connect(address, port, timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Listen to a specified port for incoming data or connections
|
/// Disconnect a connect from its remote peer
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfBool sfSocketTCP_Listen(sfSocketTCP* socket, unsigned short port)
|
void sfTcpSocket_Disconnect(sfTcpSocket* socket)
|
||||||
{
|
{
|
||||||
CSFML_CALL_RETURN(socket, Listen(port), sfFalse);
|
CSFML_CALL(socket, Disconnect());
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Wait for a connection (must be listening to a port).
|
|
||||||
/// This function is blocking, ie. it won't return before
|
|
||||||
/// a connection has been accepted
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfSocketStatus sfSocketTCP_Accept(sfSocketTCP* socket, sfSocketTCP** connected, sfIpAddress* address)
|
|
||||||
{
|
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
|
||||||
CSFML_CHECK_RETURN(connected, sfSocketError);
|
|
||||||
|
|
||||||
// Call SFML internal function
|
|
||||||
sf::IpAddress clientAddress;
|
|
||||||
sf::SocketTCP client;
|
|
||||||
sf::Socket::Status status = socket->This.Accept(client, &clientAddress);
|
|
||||||
if (status != sf::Socket::Done)
|
|
||||||
return static_cast<sfSocketStatus>(status);
|
|
||||||
|
|
||||||
// Convert the client socket returned
|
|
||||||
*connected = sfSocketTCP_Create();
|
|
||||||
(*connected)->This = client;
|
|
||||||
|
|
||||||
// Convert the address if needed
|
|
||||||
if (address)
|
|
||||||
strncpy(address->Address, clientAddress.ToString().c_str(), 16);
|
|
||||||
|
|
||||||
return sfSocketDone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send an array of bytes to the host (must be connected first)
|
/// Send an array of bytes to the host (must be connected first)
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketTCP_Send(sfSocketTCP* socket, const char* data, size_t size)
|
sfSocketStatus sfTcpSocket_Send(sfTcpSocket* socket, const char* data, size_t size)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
|
||||||
@ -141,7 +139,7 @@ sfSocketStatus sfSocketTCP_Send(sfSocketTCP* socket, const char* data, size_t si
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive an array of bytes from the host (must be connected first)
|
/// Receive an array of bytes from the host (must be connected first)
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketTCP_Receive(sfSocketTCP* socket, char* data, size_t maxSize, size_t* sizeReceived)
|
sfSocketStatus sfTcpSocket_Receive(sfTcpSocket* socket, char* data, size_t maxSize, size_t* sizeReceived)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
|
||||||
@ -160,7 +158,7 @@ sfSocketStatus sfSocketTCP_Receive(sfSocketTCP* socket, char* data, size_t maxSi
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send a packet of data to the host (must be connected first)
|
/// Send a packet of data to the host (must be connected first)
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketTCP_SendPacket(sfSocketTCP* socket, sfPacket* packet)
|
sfSocketStatus sfTcpSocket_SendPacket(sfTcpSocket* socket, sfPacket* packet)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
CSFML_CHECK_RETURN(packet, sfSocketError);
|
CSFML_CHECK_RETURN(packet, sfSocketError);
|
||||||
@ -172,29 +170,10 @@ sfSocketStatus sfSocketTCP_SendPacket(sfSocketTCP* socket, sfPacket* packet)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive a packet from the host (must be connected first)
|
/// Receive a packet from the host (must be connected first)
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketTCP_ReceivePacket(sfSocketTCP* socket, sfPacket* packet)
|
sfSocketStatus sfTcpSocket_ReceivePacket(sfTcpSocket* socket, sfPacket* packet)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
CSFML_CHECK_RETURN(packet, sfSocketError);
|
CSFML_CHECK_RETURN(packet, sfSocketError);
|
||||||
|
|
||||||
return static_cast<sfSocketStatus>(socket->This.Receive(packet->This));
|
return static_cast<sfSocketStatus>(socket->This.Receive(packet->This));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the socket
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfBool sfSocketTCP_Close(sfSocketTCP* socket)
|
|
||||||
{
|
|
||||||
CSFML_CALL_RETURN(socket, Close(), sfFalse);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Check if a socket is in a valid state ; this function
|
|
||||||
/// can be called any time to check if the socket is OK
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfBool sfSocketTCP_IsValid(const sfSocketTCP* socket)
|
|
||||||
{
|
|
||||||
CSFML_CALL_RETURN(socket, IsValid(), sfFalse);
|
|
||||||
}
|
|
@ -22,22 +22,22 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETTCPSTRUCT_H
|
#ifndef SFML_TCPSOCKETSTRUCT_H
|
||||||
#define SFML_SOCKETTCPSTRUCT_H
|
#define SFML_TCPSOCKETSTRUCT_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SocketTCP.hpp>
|
#include <SFML/Network/TcpSocket.hpp>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Internal structure of sfSocketTCP
|
// Internal structure of sfTcpSocket
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
struct sfSocketTCP
|
struct sfTcpSocket
|
||||||
{
|
{
|
||||||
sf::SocketTCP This;
|
sf::TcpSocket This;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETTCPSTRUCT_H
|
#endif // SFML_TCPSOCKETSTRUCT_H
|
@ -25,8 +25,8 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SocketUDP.h>
|
#include <SFML/Network/UdpSocket.h>
|
||||||
#include <SFML/Network/SocketUDPStruct.h>
|
#include <SFML/Network/UdpSocketStruct.h>
|
||||||
#include <SFML/Network/PacketStruct.h>
|
#include <SFML/Network/PacketStruct.h>
|
||||||
#include <SFML/Network/IpAddress.hpp>
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
#include <SFML/Internal.h>
|
#include <SFML/Internal.h>
|
||||||
@ -36,33 +36,18 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Construct a new UDP socket
|
/// Construct a new UDP socket
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketUDP* sfSocketUDP_Create()
|
sfUdpSocket* sfUdpSocket_Create()
|
||||||
{
|
{
|
||||||
return new sfSocketUDP;
|
return new sfUdpSocket;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Copy an existing UDP socket
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfSocketUDP* sfSocketUDP_Copy(sfSocketUDP* socket)
|
|
||||||
{
|
|
||||||
CSFML_CHECK_RETURN(socket, NULL);
|
|
||||||
|
|
||||||
return new sfSocketUDP(*socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destroy an existing UDP socket
|
/// Destroy an existing UDP socket
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSocketUDP_Destroy(sfSocketUDP* socket)
|
void sfUdpSocket_Destroy(sfUdpSocket* socket)
|
||||||
{
|
{
|
||||||
if (socket)
|
delete socket;
|
||||||
{
|
|
||||||
socket->This.Close();
|
|
||||||
delete socket;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,34 +55,53 @@ void sfSocketUDP_Destroy(sfSocketUDP* socket)
|
|||||||
/// Change the blocking state of a UDP socket.
|
/// Change the blocking state of a UDP socket.
|
||||||
/// The default behaviour of a socket is blocking
|
/// The default behaviour of a socket is blocking
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void sfSocketUDP_SetBlocking(sfSocketUDP* socket, sfBool blocking)
|
void sfUdpSocket_SetBlocking(sfUdpSocket* socket, sfBool blocking)
|
||||||
{
|
{
|
||||||
CSFML_CALL(socket, SetBlocking(blocking == sfTrue));
|
CSFML_CALL(socket, SetBlocking(blocking == sfTrue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the blocking state of the socket
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
sfBool sfUdpSocket_IsBlocking(const sfUdpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CALL_RETURN(socket, IsBlocking(), sfFalse);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Get the port to which the socket is bound locally
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short sfUdpSocket_GetLocalPort(const sfUdpSocket* socket)
|
||||||
|
{
|
||||||
|
CSFML_CALL_RETURN(socket, GetLocalPort(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Bind a socket to a specific port
|
/// Bind a socket to a specific port
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfBool sfSocketUDP_Bind(sfSocketUDP* socket, unsigned short port)
|
sfSocketStatus sfUdpSocket_Bind(sfUdpSocket* socket, unsigned short port)
|
||||||
{
|
{
|
||||||
CSFML_CALL_RETURN(socket, Bind(port), sfFalse);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
|
||||||
|
return static_cast<sfSocketStatus>(socket->This.Bind(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Unbind a socket from its previous port, if any
|
/// Unbind a socket from its previous port, if any
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfBool sfSocketUDP_Unbind(sfSocketUDP* socket)
|
void sfUdpSocket_Unbind(sfUdpSocket* socket)
|
||||||
{
|
{
|
||||||
CSFML_CALL_RETURN(socket, Unbind(), sfFalse);
|
CSFML_CALL(socket, Unbind());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send an array of bytes
|
/// Send an array of bytes
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketUDP_Send(sfSocketUDP* socket, const char* data, size_t size, sfIpAddress address, unsigned short port)
|
sfSocketStatus sfUdpSocket_Send(sfUdpSocket* socket, const char* data, size_t size, sfIpAddress address, unsigned short port)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError)
|
CSFML_CHECK_RETURN(socket, sfSocketError)
|
||||||
|
|
||||||
@ -113,7 +117,7 @@ sfSocketStatus sfSocketUDP_Send(sfSocketUDP* socket, const char* data, size_t si
|
|||||||
/// This function is blocking, ie. it won't return before some
|
/// This function is blocking, ie. it won't return before some
|
||||||
/// bytes have been received
|
/// bytes have been received
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketUDP_Receive(sfSocketUDP* socket, char* data, size_t maxSize, size_t* sizeReceived, sfIpAddress* address, unsigned short* port)
|
sfSocketStatus sfUdpSocket_Receive(sfUdpSocket* socket, char* data, size_t maxSize, size_t* sizeReceived, sfIpAddress* address, unsigned short* port)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
|
|
||||||
@ -142,7 +146,7 @@ sfSocketStatus sfSocketUDP_Receive(sfSocketUDP* socket, char* data, size_t maxSi
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send a packet of data
|
/// Send a packet of data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketUDP_SendPacket(sfSocketUDP* socket, sfPacket* packet, sfIpAddress address, unsigned short port)
|
sfSocketStatus sfUdpSocket_SendPacket(sfUdpSocket* socket, sfPacket* packet, sfIpAddress address, unsigned short port)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
CSFML_CHECK_RETURN(packet, sfSocketError);
|
CSFML_CHECK_RETURN(packet, sfSocketError);
|
||||||
@ -159,7 +163,7 @@ sfSocketStatus sfSocketUDP_SendPacket(sfSocketUDP* socket, sfPacket* packet, sfI
|
|||||||
/// This function is blocking, ie. it won't return before a
|
/// This function is blocking, ie. it won't return before a
|
||||||
/// packet is received
|
/// packet is received
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sfSocketStatus sfSocketUDP_ReceivePacket(sfSocketUDP* socket, sfPacket* packet, sfIpAddress* address, unsigned short* port)
|
sfSocketStatus sfUdpSocket_ReceivePacket(sfUdpSocket* socket, sfPacket* packet, sfIpAddress* address, unsigned short* port)
|
||||||
{
|
{
|
||||||
CSFML_CHECK_RETURN(socket, sfSocketError);
|
CSFML_CHECK_RETURN(socket, sfSocketError);
|
||||||
CSFML_CHECK_RETURN(packet, sfSocketError);
|
CSFML_CHECK_RETURN(packet, sfSocketError);
|
||||||
@ -178,22 +182,3 @@ sfSocketStatus sfSocketUDP_ReceivePacket(sfSocketUDP* socket, sfPacket* packet,
|
|||||||
|
|
||||||
return sfSocketDone;
|
return sfSocketDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the socket
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfBool sfSocketUDP_Close(sfSocketUDP* socket)
|
|
||||||
{
|
|
||||||
CSFML_CALL_RETURN(socket, Close(), sfFalse);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Check if a socket is in a valid state ; this function
|
|
||||||
/// can be called any time to check if the socket is OK
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
sfBool sfSocketUDP_IsValid(const sfSocketUDP* socket)
|
|
||||||
{
|
|
||||||
CSFML_CALL_RETURN(socket, IsValid(), sfFalse);
|
|
||||||
}
|
|
@ -22,22 +22,22 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETUDPSTRUCT_H
|
#ifndef SFML_UDPSOCKETSTRUCT_H
|
||||||
#define SFML_SOCKETUDPSTRUCT_H
|
#define SFML_UDPSOCKETSTRUCT_H
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SocketUDP.hpp>
|
#include <SFML/Network/UdpSocket.hpp>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Internal structure of sfSocketUDP
|
// Internal structure of sfUdpSocket
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
struct sfSocketUDP
|
struct sfUdpSocket
|
||||||
{
|
{
|
||||||
sf::SocketUDP This;
|
sf::UdpSocket This;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETUDPSTRUCT_H
|
#endif // SFML_UDPSOCKETSTRUCT_H
|
@ -26,7 +26,7 @@ EXPORTS
|
|||||||
sfFtp_GetDirectoryListing
|
sfFtp_GetDirectoryListing
|
||||||
sfFtp_ChangeDirectory
|
sfFtp_ChangeDirectory
|
||||||
sfFtp_ParentDirectory
|
sfFtp_ParentDirectory
|
||||||
sfFtp_MakeDirectory
|
sfFtp_CreateDirectory
|
||||||
sfFtp_DeleteDirectory
|
sfFtp_DeleteDirectory
|
||||||
sfFtp_RenameFile
|
sfFtp_RenameFile
|
||||||
sfFtp_DeleteFile
|
sfFtp_DeleteFile
|
||||||
@ -36,7 +36,7 @@ EXPORTS
|
|||||||
sfHttpRequest_Destroy
|
sfHttpRequest_Destroy
|
||||||
sfHttpRequest_SetField
|
sfHttpRequest_SetField
|
||||||
sfHttpRequest_SetMethod
|
sfHttpRequest_SetMethod
|
||||||
sfHttpRequest_SetURI
|
sfHttpRequest_SetUri
|
||||||
sfHttpRequest_SetHttpVersion
|
sfHttpRequest_SetHttpVersion
|
||||||
sfHttpRequest_SetBody
|
sfHttpRequest_SetBody
|
||||||
sfHttpResponse_Destroy
|
sfHttpResponse_Destroy
|
||||||
@ -58,29 +58,36 @@ EXPORTS
|
|||||||
sfIpAddress_GetPublicAddress
|
sfIpAddress_GetPublicAddress
|
||||||
sfIpAddress_LocalHost
|
sfIpAddress_LocalHost
|
||||||
sfIpAddress_None
|
sfIpAddress_None
|
||||||
sfSocketTCP_Create
|
sfTcpListener_Create
|
||||||
sfSocketTCP_Destroy
|
sfTcpListener_Destroy
|
||||||
sfSocketTCP_SetBlocking
|
sfTcpListener_SetBlocking
|
||||||
sfSocketTCP_Connect
|
sfTcpListener_IsBlocking
|
||||||
sfSocketTCP_Listen
|
sfTcpListener_Listen
|
||||||
sfSocketTCP_Accept
|
sfTcpListener_Accept
|
||||||
sfSocketTCP_Send
|
sfTcpSocket_Create
|
||||||
sfSocketTCP_Receive
|
sfTcpSocket_Destroy
|
||||||
sfSocketTCP_SendPacket
|
sfTcpSocket_SetBlocking
|
||||||
sfSocketTCP_ReceivePacket
|
sfTcpSocket_IsBlocking
|
||||||
sfSocketTCP_Close
|
sfTcpSocket_GetLocalPort
|
||||||
sfSocketTCP_IsValid
|
sfTcpSocket_GetRemoteAddress
|
||||||
sfSocketUDP_Create
|
sfTcpSocket_GetRemotePort
|
||||||
sfSocketUDP_Destroy
|
sfTcpSocket_Connect
|
||||||
sfSocketUDP_SetBlocking
|
sfTcpSocket_Disconnect
|
||||||
sfSocketUDP_Bind
|
sfTcpSocket_Send
|
||||||
sfSocketUDP_Unbind
|
sfTcpSocket_Receive
|
||||||
sfSocketUDP_Send
|
sfTcpSocket_SendPacket
|
||||||
sfSocketUDP_Receive
|
sfTcpSocket_ReceivePacket
|
||||||
sfSocketUDP_SendPacket
|
sfUdpSocket_Create
|
||||||
sfSocketUDP_ReceivePacket
|
sfUdpSocket_Destroy
|
||||||
sfSocketUDP_Close
|
sfUdpSocket_SetBlocking
|
||||||
sfSocketUDP_IsValid
|
sfUdpSocket_IsBlocking
|
||||||
|
sfUdpSocket_GetLocalPort
|
||||||
|
sfUdpSocket_Bind
|
||||||
|
sfUdpSocket_Unbind
|
||||||
|
sfUdpSocket_Send
|
||||||
|
sfUdpSocket_Receive
|
||||||
|
sfUdpSocket_SendPacket
|
||||||
|
sfUdpSocket_ReceivePacket
|
||||||
sfPacket_Create
|
sfPacket_Create
|
||||||
sfPacket_Copy
|
sfPacket_Copy
|
||||||
sfPacket_Destroy
|
sfPacket_Destroy
|
||||||
@ -112,19 +119,17 @@ EXPORTS
|
|||||||
sfPacket_WriteDouble
|
sfPacket_WriteDouble
|
||||||
sfPacket_WriteString
|
sfPacket_WriteString
|
||||||
sfPacket_WriteWideString
|
sfPacket_WriteWideString
|
||||||
sfSelectorTCP_Create
|
sfSocketSelector_Create
|
||||||
sfSelectorTCP_Copy
|
sfSocketSelector_Copy
|
||||||
sfSelectorTCP_Destroy
|
sfSocketSelector_Destroy
|
||||||
sfSelectorTCP_Add
|
sfSocketSelector_AddTcpListener
|
||||||
sfSelectorTCP_Remove
|
sfSocketSelector_AddTcpSocket
|
||||||
sfSelectorTCP_Clear
|
sfSocketSelector_AddUdpSocket
|
||||||
sfSelectorTCP_Wait
|
sfSocketSelector_RemoveTcpListener
|
||||||
sfSelectorTCP_GetSocketReady
|
sfSocketSelector_RemoveTcpSocket
|
||||||
sfSelectorUDP_Create
|
sfSocketSelector_RemoveUdpSocket
|
||||||
sfSelectorUDP_Copy
|
sfSocketSelector_Clear
|
||||||
sfSelectorUDP_Destroy
|
sfSocketSelector_Wait
|
||||||
sfSelectorUDP_Add
|
sfSocketSelector_IsTcpListenerReady
|
||||||
sfSelectorUDP_Remove
|
sfSocketSelector_IsTcpSocketReady
|
||||||
sfSelectorUDP_Clear
|
sfSocketSelector_IsUdpSocketReady
|
||||||
sfSelectorUDP_Wait
|
|
||||||
sfSelectorUDP_GetSocketReady
|
|
||||||
|
@ -26,7 +26,7 @@ EXPORTS
|
|||||||
sfFtp_GetDirectoryListing
|
sfFtp_GetDirectoryListing
|
||||||
sfFtp_ChangeDirectory
|
sfFtp_ChangeDirectory
|
||||||
sfFtp_ParentDirectory
|
sfFtp_ParentDirectory
|
||||||
sfFtp_MakeDirectory
|
sfFtp_CreateDirectory
|
||||||
sfFtp_DeleteDirectory
|
sfFtp_DeleteDirectory
|
||||||
sfFtp_RenameFile
|
sfFtp_RenameFile
|
||||||
sfFtp_DeleteFile
|
sfFtp_DeleteFile
|
||||||
@ -36,7 +36,7 @@ EXPORTS
|
|||||||
sfHttpRequest_Destroy
|
sfHttpRequest_Destroy
|
||||||
sfHttpRequest_SetField
|
sfHttpRequest_SetField
|
||||||
sfHttpRequest_SetMethod
|
sfHttpRequest_SetMethod
|
||||||
sfHttpRequest_SetURI
|
sfHttpRequest_SetUri
|
||||||
sfHttpRequest_SetHttpVersion
|
sfHttpRequest_SetHttpVersion
|
||||||
sfHttpRequest_SetBody
|
sfHttpRequest_SetBody
|
||||||
sfHttpResponse_Destroy
|
sfHttpResponse_Destroy
|
||||||
@ -58,31 +58,36 @@ EXPORTS
|
|||||||
sfIpAddress_GetPublicAddress
|
sfIpAddress_GetPublicAddress
|
||||||
sfIpAddress_LocalHost
|
sfIpAddress_LocalHost
|
||||||
sfIpAddress_None
|
sfIpAddress_None
|
||||||
sfSocketTCP_Create
|
sfTcpListener_Create
|
||||||
sfSocketTCP_Copy
|
sfTcpListener_Destroy
|
||||||
sfSocketTCP_Destroy
|
sfTcpListener_SetBlocking
|
||||||
sfSocketTCP_SetBlocking
|
sfTcpListener_IsBlocking
|
||||||
sfSocketTCP_Connect
|
sfTcpListener_Listen
|
||||||
sfSocketTCP_Listen
|
sfTcpListener_Accept
|
||||||
sfSocketTCP_Accept
|
sfTcpSocket_Create
|
||||||
sfSocketTCP_Send
|
sfTcpSocket_Destroy
|
||||||
sfSocketTCP_Receive
|
sfTcpSocket_SetBlocking
|
||||||
sfSocketTCP_SendPacket
|
sfTcpSocket_IsBlocking
|
||||||
sfSocketTCP_ReceivePacket
|
sfTcpSocket_GetLocalPort
|
||||||
sfSocketTCP_Close
|
sfTcpSocket_GetRemoteAddress
|
||||||
sfSocketTCP_IsValid
|
sfTcpSocket_GetRemotePort
|
||||||
sfSocketUDP_Create
|
sfTcpSocket_Connect
|
||||||
sfSocketUDP_Copy
|
sfTcpSocket_Disconnect
|
||||||
sfSocketUDP_Destroy
|
sfTcpSocket_Send
|
||||||
sfSocketUDP_SetBlocking
|
sfTcpSocket_Receive
|
||||||
sfSocketUDP_Bind
|
sfTcpSocket_SendPacket
|
||||||
sfSocketUDP_Unbind
|
sfTcpSocket_ReceivePacket
|
||||||
sfSocketUDP_Send
|
sfUdpSocket_Create
|
||||||
sfSocketUDP_Receive
|
sfUdpSocket_Destroy
|
||||||
sfSocketUDP_SendPacket
|
sfUdpSocket_SetBlocking
|
||||||
sfSocketUDP_ReceivePacket
|
sfUdpSocket_IsBlocking
|
||||||
sfSocketUDP_Close
|
sfUdpSocket_GetLocalPort
|
||||||
sfSocketUDP_IsValid
|
sfUdpSocket_Bind
|
||||||
|
sfUdpSocket_Unbind
|
||||||
|
sfUdpSocket_Send
|
||||||
|
sfUdpSocket_Receive
|
||||||
|
sfUdpSocket_SendPacket
|
||||||
|
sfUdpSocket_ReceivePacket
|
||||||
sfPacket_Create
|
sfPacket_Create
|
||||||
sfPacket_Copy
|
sfPacket_Copy
|
||||||
sfPacket_Destroy
|
sfPacket_Destroy
|
||||||
@ -114,19 +119,17 @@ EXPORTS
|
|||||||
sfPacket_WriteDouble
|
sfPacket_WriteDouble
|
||||||
sfPacket_WriteString
|
sfPacket_WriteString
|
||||||
sfPacket_WriteWideString
|
sfPacket_WriteWideString
|
||||||
sfSelectorTCP_Create
|
sfSocketSelector_Create
|
||||||
sfSelectorTCP_Copy
|
sfSocketSelector_Copy
|
||||||
sfSelectorTCP_Destroy
|
sfSocketSelector_Destroy
|
||||||
sfSelectorTCP_Add
|
sfSocketSelector_AddTcpListener
|
||||||
sfSelectorTCP_Remove
|
sfSocketSelector_AddTcpSocket
|
||||||
sfSelectorTCP_Clear
|
sfSocketSelector_AddUdpSocket
|
||||||
sfSelectorTCP_Wait
|
sfSocketSelector_RemoveTcpListener
|
||||||
sfSelectorTCP_GetSocketReady
|
sfSocketSelector_RemoveTcpSocket
|
||||||
sfSelectorUDP_Create
|
sfSocketSelector_RemoveUdpSocket
|
||||||
sfSelectorUDP_Copy
|
sfSocketSelector_Clear
|
||||||
sfSelectorUDP_Destroy
|
sfSocketSelector_Wait
|
||||||
sfSelectorUDP_Add
|
sfSocketSelector_IsTcpListenerReady
|
||||||
sfSelectorUDP_Remove
|
sfSocketSelector_IsTcpSocketReady
|
||||||
sfSelectorUDP_Clear
|
sfSocketSelector_IsUdpSocketReady
|
||||||
sfSelectorUDP_Wait
|
|
||||||
sfSelectorUDP_GetSocketReady
|
|
||||||
|
@ -116,21 +116,24 @@
|
|||||||
<Unit filename="..\..\include\SFML\Network\Http.hpp" />
|
<Unit filename="..\..\include\SFML\Network\Http.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\IpAddress.hpp" />
|
<Unit filename="..\..\include\SFML\Network\IpAddress.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Packet.hpp" />
|
<Unit filename="..\..\include\SFML\Network\Packet.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Selector.hpp" />
|
<Unit filename="..\..\include\SFML\Network\Socket.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Selector.inl" />
|
<Unit filename="..\..\include\SFML\Network\SocketHandle.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SelectorBase.hpp" />
|
<Unit filename="..\..\include\SFML\Network\SocketSelector.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SocketHelper.hpp" />
|
<Unit filename="..\..\include\SFML\Network\TcpListener.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SocketTCP.hpp" />
|
<Unit filename="..\..\include\SFML\Network\TcpSocket.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\SocketUDP.hpp" />
|
<Unit filename="..\..\include\SFML\Network\UdpSocket.hpp" />
|
||||||
<Unit filename="..\..\include\SFML\Network\Win32\SocketHelper.hpp" />
|
|
||||||
<Unit filename="..\..\src\SFML\Network\Ftp.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Ftp.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Http.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Http.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\IpAddress.cpp" />
|
<Unit filename="..\..\src\SFML\Network\IpAddress.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Packet.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Packet.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SelectorBase.cpp" />
|
<Unit filename="..\..\src\SFML\Network\Socket.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SocketTCP.cpp" />
|
<Unit filename="..\..\src\SFML\Network\SocketImpl.hpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\SocketUDP.cpp" />
|
<Unit filename="..\..\src\SFML\Network\SocketSelector.cpp" />
|
||||||
<Unit filename="..\..\src\SFML\Network\Win32\SocketHelper.cpp" />
|
<Unit filename="..\..\src\SFML\Network\TcpListener.cpp" />
|
||||||
|
<Unit filename="..\..\src\SFML\Network\TcpSocket.cpp" />
|
||||||
|
<Unit filename="..\..\src\SFML\Network\UdpSocket.cpp" />
|
||||||
|
<Unit filename="..\..\src\SFML\Network\Win32\SocketImpl.cpp" />
|
||||||
|
<Unit filename="..\..\src\SFML\Network\Win32\SocketImpl.hpp" />
|
||||||
<Extensions>
|
<Extensions>
|
||||||
<code_completion />
|
<code_completion />
|
||||||
<envvars />
|
<envvars />
|
||||||
|
@ -344,11 +344,11 @@
|
|||||||
Name="Win32"
|
Name="Win32"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\Win32\SocketHelper.cpp"
|
RelativePath="..\..\src\SFML\Network\Win32\SocketImpl.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Win32\SocketHelper.hpp"
|
RelativePath="..\..\src\SFML\Network\Win32\SocketImpl.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -385,39 +385,51 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Selector.hpp"
|
RelativePath="..\..\src\SFML\Network\Socket.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Selector.inl"
|
RelativePath="..\..\include\SFML\Network\Socket.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SelectorBase.cpp"
|
RelativePath="..\..\include\SFML\Network\SocketHandle.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SelectorBase.hpp"
|
RelativePath="..\..\src\SFML\Network\SocketImpl.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketHelper.hpp"
|
RelativePath="..\..\src\SFML\Network\SocketSelector.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketTCP.cpp"
|
RelativePath="..\..\include\SFML\Network\SocketSelector.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketTCP.hpp"
|
RelativePath="..\..\src\SFML\Network\TcpListener.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketUDP.cpp"
|
RelativePath="..\..\include\SFML\Network\TcpListener.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketUDP.hpp"
|
RelativePath="..\..\src\SFML\Network\TcpSocket.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\TcpSocket.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\UdpSocket.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\UdpSocket.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
|
@ -343,11 +343,11 @@
|
|||||||
Name="Win32"
|
Name="Win32"
|
||||||
>
|
>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\Win32\SocketHelper.cpp"
|
RelativePath="..\..\src\SFML\Network\Win32\SocketImpl.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Win32\SocketHelper.hpp"
|
RelativePath="..\..\src\SFML\Network\Win32\SocketImpl.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
@ -384,39 +384,51 @@
|
|||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Selector.hpp"
|
RelativePath="..\..\src\SFML\Network\Socket.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\Selector.inl"
|
RelativePath="..\..\include\SFML\Network\Socket.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SelectorBase.cpp"
|
RelativePath="..\..\include\SFML\Network\SocketHandle.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SelectorBase.hpp"
|
RelativePath="..\..\src\SFML\Network\SocketImpl.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketHelper.hpp"
|
RelativePath="..\..\src\SFML\Network\SocketSelector.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketTCP.cpp"
|
RelativePath="..\..\include\SFML\Network\SocketSelector.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketTCP.hpp"
|
RelativePath="..\..\src\SFML\Network\TcpListener.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\SFML\Network\SocketUDP.cpp"
|
RelativePath="..\..\include\SFML\Network\TcpListener.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\include\SFML\Network\SocketUDP.hpp"
|
RelativePath="..\..\src\SFML\Network\TcpSocket.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\TcpSocket.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\SFML\Network\UdpSocket.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\include\SFML\Network\UdpSocket.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Files>
|
</Files>
|
||||||
|
@ -34,9 +34,10 @@
|
|||||||
#include <SFML/Network/Http.hpp>
|
#include <SFML/Network/Http.hpp>
|
||||||
#include <SFML/Network/IpAddress.hpp>
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
#include <SFML/Network/Packet.hpp>
|
#include <SFML/Network/Packet.hpp>
|
||||||
#include <SFML/Network/Selector.hpp>
|
#include <SFML/Network/SocketSelector.hpp>
|
||||||
#include <SFML/Network/SocketTCP.hpp>
|
#include <SFML/Network/TcpListener.hpp>
|
||||||
#include <SFML/Network/SocketUDP.hpp>
|
#include <SFML/Network/TcpSocket.hpp>
|
||||||
|
#include <SFML/Network/UdpSocket.hpp>
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_NETWORK_HPP
|
#endif // SFML_NETWORK_HPP
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/NonCopyable.hpp>
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
#include <SFML/Network/SocketTCP.hpp>
|
#include <SFML/Network/TcpSocket.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -39,17 +39,16 @@ namespace sf
|
|||||||
class IpAddress;
|
class IpAddress;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class provides methods for manipulating the FTP
|
/// \li A FTP client
|
||||||
/// 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
|
class SFML_API Ftp : NonCopyable
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Enumeration of transfer modes
|
/// \brief Enumeration of transfer modes
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
enum TransferMode
|
enum TransferMode
|
||||||
{
|
{
|
||||||
@ -59,17 +58,16 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class wraps a FTP response, which is basically :
|
/// \brief Define a FTP response
|
||||||
/// - a status code
|
///
|
||||||
/// - a message
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API Response
|
class SFML_API Response
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Enumerate all the valid status codes returned in
|
/// \brief Status codes possibly returned by a FTP response
|
||||||
/// a FTP response
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
enum Status
|
enum Status
|
||||||
{
|
{
|
||||||
@ -134,25 +132,30 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
/// \param code : Response status code
|
/// This constructor is used by the FTP client to build
|
||||||
/// \param message : Response message
|
/// the response.
|
||||||
|
///
|
||||||
|
/// \param code Response status code
|
||||||
|
/// \param message Response message
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response(Status code = InvalidResponse, const std::string& message = "");
|
Response(Status code = InvalidResponse, const std::string& message = "");
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Convenience function to check if the response status code
|
/// \brief Check if the status code means a success
|
||||||
/// means a success
|
|
||||||
///
|
///
|
||||||
/// \return True if status is success (code < 400)
|
/// This function is defined for convenience, it is
|
||||||
|
/// equivalent to testing if the status code is < 400.
|
||||||
|
///
|
||||||
|
/// \return True if the status is a success, false if it is a failure
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool IsOk() const;
|
bool IsOk() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the response status code
|
/// \brief Get the status code of the response
|
||||||
///
|
///
|
||||||
/// \return Status code
|
/// \return Status code
|
||||||
///
|
///
|
||||||
@ -160,7 +163,7 @@ public :
|
|||||||
Status GetStatus() const;
|
Status GetStatus() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the full message contained in the response
|
/// \brief Get the full message contained in the response
|
||||||
///
|
///
|
||||||
/// \return The response message
|
/// \return The response message
|
||||||
///
|
///
|
||||||
@ -177,22 +180,23 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Specialization of FTP response returning a directory
|
/// \brief Specialization of FTP response returning a directory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API DirectoryResponse : public Response
|
class SFML_API DirectoryResponse : public Response
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
/// \param response : Source response
|
/// \param response Source response
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
DirectoryResponse(Response response);
|
DirectoryResponse(const Response& response);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the directory returned in the response
|
/// \brief Get the directory returned in the response
|
||||||
///
|
///
|
||||||
/// \return Directory name
|
/// \return Directory name
|
||||||
///
|
///
|
||||||
@ -209,38 +213,29 @@ public :
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Specialization of FTP response returning a filename lisiting
|
/// \brief Specialization of FTP response returning a
|
||||||
|
/// filename lisiting
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API ListingResponse : public Response
|
class SFML_API ListingResponse : public Response
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
/// \param response : Source response
|
/// \param response Source response
|
||||||
/// \param data : Data containing the raw listing
|
/// \param data Data containing the raw listing
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
ListingResponse(Response response, const std::vector<char>& data);
|
ListingResponse(const Response& response, const std::vector<char>& data);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the number of filenames in the listing
|
/// \brief Return the array of filenames
|
||||||
///
|
///
|
||||||
/// \return Total number of filenames
|
/// \return Array containing the requested filenames
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::size_t GetCount() const;
|
const std::vector<std::string>& GetFilenames() 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 :
|
private :
|
||||||
|
|
||||||
@ -252,25 +247,52 @@ public :
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Destructor -- close the connection with the server
|
/// \brief Destructor
|
||||||
|
///
|
||||||
|
/// Automatically closes the connection with the server if
|
||||||
|
/// it is still opened.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
~Ftp();
|
~Ftp();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Connect to the specified FTP server
|
/// \brief Connect to the specified FTP server
|
||||||
///
|
///
|
||||||
/// \param server : FTP server to connect to
|
/// The port has a default value of 21, which is the standard
|
||||||
/// \param port : Port used for connection (21 by default, standard FTP port)
|
/// port used by the FTP protocol. You shouldn't use a different
|
||||||
/// \param timeout : Maximum time to wait, in seconds (0 by default, means no timeout)
|
/// value, unless you really know what you do.
|
||||||
|
/// This function tries to connect to the server so it may take
|
||||||
|
/// a while to complete, especially if the server is not
|
||||||
|
/// reachable. To avoid blocking your application for too long,
|
||||||
|
/// you can use a timeout. The default value, 0, means that the
|
||||||
|
/// system timeout will be used (which is usually pretty long).
|
||||||
|
///
|
||||||
|
/// \param server Name or address of the FTP server to connect to
|
||||||
|
/// \param port Port used for the connection
|
||||||
|
/// \param timeout Maximum time to wait, in seconds
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see Disconnect
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response Connect(const IpAddress& server, unsigned short port = 21, float timeout = 0.f);
|
Response Connect(const IpAddress& server, unsigned short port = 21, float timeout = 0.f);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Log in using anonymous account
|
/// \brief Close the connection with the server
|
||||||
|
///
|
||||||
|
/// \return Server response to the request
|
||||||
|
///
|
||||||
|
/// \see Connect
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Response Disconnect();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Log in using an anonymous account
|
||||||
|
///
|
||||||
|
/// Logging in is mandatory after connecting to the server.
|
||||||
|
/// Users that are not logged in cannot perform any operation.
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
@ -278,10 +300,13 @@ public :
|
|||||||
Response Login();
|
Response Login();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Log in using a username and a password
|
/// \brief Log in using a username and a password
|
||||||
///
|
///
|
||||||
/// \param name : User name
|
/// Logging in is mandatory after connecting to the server.
|
||||||
/// \param password : Password
|
/// Users that are not logged in cannot perform any operation.
|
||||||
|
///
|
||||||
|
/// \param name User name
|
||||||
|
/// \param password Password
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
@ -289,15 +314,10 @@ public :
|
|||||||
Response Login(const std::string& name, const std::string& password);
|
Response Login(const std::string& name, const std::string& password);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Close the connection with FTP server
|
/// \brief Send a null command to keep the connection alive
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// This command is useful because the server may close the
|
||||||
///
|
/// connection automatically if no command is sent.
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Response Disconnect();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Send a null command just to prevent from being disconnected
|
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
@ -305,31 +325,46 @@ public :
|
|||||||
Response KeepAlive();
|
Response KeepAlive();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the current working directory
|
/// \brief Get the current working directory
|
||||||
|
///
|
||||||
|
/// The working directory is the root path for subsequent
|
||||||
|
/// operations involving directories and/or filenames.
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see GetDirectoryListing, ChangeDirectory, ParentDirectory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
DirectoryResponse GetWorkingDirectory();
|
DirectoryResponse GetWorkingDirectory();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the contents of the given directory
|
/// \brief Get the contents of the given directory
|
||||||
/// (subdirectories and files)
|
|
||||||
///
|
///
|
||||||
/// \param directory : Directory to list ("" by default, the current one)
|
/// This function retrieves the sub-directories and files
|
||||||
|
/// contained in the given directory. It is not recursive.
|
||||||
|
/// The \a directory parameter is relative to the current
|
||||||
|
/// working directory.
|
||||||
|
///
|
||||||
|
/// \param directory Directory to list
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see GetWorkingDirectory, ChangeDirectory, ParentDirectory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
ListingResponse GetDirectoryListing(const std::string& directory = "");
|
ListingResponse GetDirectoryListing(const std::string& directory = "");
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Change the current working directory
|
/// \brief Change the current working directory
|
||||||
///
|
///
|
||||||
/// \param directory : New directory, relative to the current one
|
/// The new directory must be relative to the current one.
|
||||||
|
///
|
||||||
|
/// \param directory New working directory
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see GetWorkingDirectory, GetDirectoryListing, ParentDirectory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response ChangeDirectory(const std::string& directory);
|
Response ChangeDirectory(const std::string& directory);
|
||||||
|
|
||||||
@ -338,81 +373,127 @@ public :
|
|||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see GetWorkingDirectory, GetDirectoryListing, ChangeDirectory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response ParentDirectory();
|
Response ParentDirectory();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create a new directory
|
/// \brief Create a new directory
|
||||||
///
|
///
|
||||||
/// \param name : Name of the directory to create
|
/// The new directory is created as a child of the current
|
||||||
|
/// working directory.
|
||||||
|
///
|
||||||
|
/// \param name Name of the directory to create
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see DeleteDirectory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response MakeDirectory(const std::string& name);
|
Response CreateDirectory(const std::string& name);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove an existing directory
|
/// \brief Remove an existing directory
|
||||||
///
|
///
|
||||||
/// \param Name : Name of the directory to remove
|
/// The directory to remove must be relative to the
|
||||||
|
/// current working directory.
|
||||||
|
/// Use this function with caution, the directory will
|
||||||
|
/// be removed permanently!
|
||||||
|
///
|
||||||
|
/// \param Name Name of the directory to remove
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see CreateDirectory
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response DeleteDirectory(const std::string& name);
|
Response DeleteDirectory(const std::string& name);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Rename a file
|
/// \brief Rename an existing file
|
||||||
///
|
///
|
||||||
/// \param file : File to rename
|
/// The filenames must be relative to the current working
|
||||||
/// \param newName : New name
|
/// directory.
|
||||||
|
///
|
||||||
|
/// \param file File to rename
|
||||||
|
/// \param newName New name of the file
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see DeleteFile
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response RenameFile(const std::string& file, const std::string& newName);
|
Response RenameFile(const std::string& file, const std::string& newName);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove an existing file
|
/// \brief Remove an existing file
|
||||||
///
|
///
|
||||||
/// \param name : File to remove
|
/// The file name must be relative to the current working
|
||||||
|
/// directory.
|
||||||
|
/// Use this function with caution, the file will be
|
||||||
|
/// removed permanently!
|
||||||
|
///
|
||||||
|
/// \param name File to remove
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see RenameFile
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response DeleteFile(const std::string& name);
|
Response DeleteFile(const std::string& name);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Download a file from the server
|
/// \brief Download a file from the server
|
||||||
///
|
///
|
||||||
/// \param distantFile : Path of the distant file to download
|
/// The filename of the distant file is relative to the
|
||||||
/// \param destPath : Where to put to file on the local computer
|
/// current working directory of the server, and the local
|
||||||
/// \param mode : Transfer mode
|
/// destination path is relative to the current directory
|
||||||
|
/// of your application.
|
||||||
|
/// If you want to watch the progress (to update a progress bar
|
||||||
|
/// for example) or have the ability to stop or pause the download,
|
||||||
|
/// you can use the fourth parameter to pass your progress handler.
|
||||||
|
///
|
||||||
|
/// \param remoteFile Filename of the distant file to download
|
||||||
|
/// \param localPath Where to put to file on the local computer
|
||||||
|
/// \param mode Transfer mode
|
||||||
|
/// \param handler Object that will be notified of the download progress
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
|
/// \see Upload
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response Download(const std::string& distantFile, const std::string& destPath, TransferMode mode = Binary);
|
Response Download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Upload a file to the server
|
/// \brief Upload a file to the server
|
||||||
///
|
///
|
||||||
/// \param localFile : Path of the local file to upload
|
/// The name of the local file is relative to the current
|
||||||
/// \param destPath : Where to put to file on the server
|
/// working directory of your application, and the
|
||||||
/// \param mode : Transfer mode
|
/// remote path is relative to the current directory of the
|
||||||
|
/// FTP server.
|
||||||
|
/// If you want to watch the progress (to update a progress bar
|
||||||
|
/// for example) or have the ability to stop or pause the upload,
|
||||||
|
/// you can use the fourth parameter to pass your progress handler.
|
||||||
|
///
|
||||||
|
/// \param localFile Path of the local file to upload
|
||||||
|
/// \param remotePath Where to put to file on the server
|
||||||
|
/// \param mode Transfer mode
|
||||||
|
/// \param handler Object that will be notified of the upload progress
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response Upload(const std::string& localFile, const std::string& destPath, TransferMode mode = Binary);
|
Response Upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary);
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send a command to the FTP server
|
/// \brief Send a command to the FTP server
|
||||||
///
|
///
|
||||||
/// \param command : Command to send
|
/// \param command Command to send
|
||||||
/// \param parameter : Command parameter
|
/// \param parameter Command parameter
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
@ -420,8 +501,10 @@ private :
|
|||||||
Response SendCommand(const std::string& command, const std::string& parameter = "");
|
Response SendCommand(const std::string& command, const std::string& parameter = "");
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Receive a response from the server
|
/// \brief Receive a response from the server
|
||||||
/// (usually after a command has been sent)
|
///
|
||||||
|
/// This function must be called after each call to
|
||||||
|
/// SendCommand that expects a response.
|
||||||
///
|
///
|
||||||
/// \return Server response to the request
|
/// \return Server response to the request
|
||||||
///
|
///
|
||||||
@ -429,8 +512,9 @@ private :
|
|||||||
Response GetResponse();
|
Response GetResponse();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Utility class for exchanging datas with the server
|
/// \brief Utility class for exchanging datas with the server
|
||||||
/// on the data channel
|
/// on the data channel
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class DataChannel;
|
class DataChannel;
|
||||||
|
|
||||||
@ -439,10 +523,72 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SocketTCP myCommandSocket; ///< Socket holding the control connection with the server
|
TcpSocket myCommandSocket; ///< Socket holding the control connection with the server
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_FTP_HPP
|
#endif // SFML_FTP_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::Ftp
|
||||||
|
///
|
||||||
|
/// sf::Ftp is a very simple FTP client that allows you
|
||||||
|
/// to communicate with a FTP server. The FTP protocol allows
|
||||||
|
/// you to manipulate a remote file system (list files,
|
||||||
|
/// upload, download, create, remove, ...).
|
||||||
|
///
|
||||||
|
/// Using the FTP client consists of 4 parts:
|
||||||
|
/// \li Connecting to the FTP server
|
||||||
|
/// \li Logging in (either as a registered user or anonymously)
|
||||||
|
/// \li Sending commands to the server
|
||||||
|
/// \li Disconnecting (this part can be done implicitely by the destructor)
|
||||||
|
///
|
||||||
|
/// Every command returns a FTP response, which contains the
|
||||||
|
/// status code as well as a message from the server. Some
|
||||||
|
/// commands such as GetWorkingDirectory and GetDirectoryListing
|
||||||
|
/// return additional data, and use a class derived from
|
||||||
|
/// sf::Ftp::Response to provide this data.
|
||||||
|
///
|
||||||
|
/// All commands, especially Upload and Download, may take some
|
||||||
|
/// time to complete. This is important to know if you don't want
|
||||||
|
/// to block your application while the server is completing
|
||||||
|
/// the task.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \code
|
||||||
|
/// // Create a new FTP client
|
||||||
|
/// sf::Ftp ftp;
|
||||||
|
///
|
||||||
|
/// // Connect to the server
|
||||||
|
/// sf::Ftp::Response response = ftp.Connect("ftp://ftp.myserver.com");
|
||||||
|
/// if (response.IsOk())
|
||||||
|
/// std::cout << "Connected" << std::endl;
|
||||||
|
///
|
||||||
|
/// // Log in
|
||||||
|
/// response = ftp.Login("laurent", "dF6Zm89D");
|
||||||
|
/// if (response.IsOk())
|
||||||
|
/// std::cout << "Logged in" << std::endl;
|
||||||
|
///
|
||||||
|
/// // Print the working directory
|
||||||
|
/// sf::Ftp::DirectoryResponse directory = ftp.GetWorkingDirectory();
|
||||||
|
/// if (directory.IsOk())
|
||||||
|
/// std::cout << "Working directory: " << directory.GetDirectory() << std::endl;
|
||||||
|
///
|
||||||
|
/// // Create a new directory
|
||||||
|
/// response = ftp.CreateDirectory("files");
|
||||||
|
/// if (response.IsOk())
|
||||||
|
/// std::cout << "Created new directory" << std::endl;
|
||||||
|
///
|
||||||
|
/// // Upload a file to this new directory
|
||||||
|
/// response = ftp.Upload("local-path/file.txt", "files", sf::Ftp::Ascii);
|
||||||
|
/// if (response.IsOk())
|
||||||
|
/// std::cout << "File uploaded" << std::endl;
|
||||||
|
///
|
||||||
|
/// // Disconnect from the server (optional)
|
||||||
|
/// ftp.Disconnect();
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/NonCopyable.hpp>
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
#include <SFML/Network/IpAddress.hpp>
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
#include <SFML/Network/SocketTCP.hpp>
|
#include <SFML/Network/TcpSocket.hpp>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -38,25 +38,24 @@
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class provides methods for manipulating the HTTP
|
/// \brief A HTTP client
|
||||||
/// protocol (described in RFC 1945).
|
///
|
||||||
/// It can connect to a website, get its files, send requests, etc.
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API Http : NonCopyable
|
class SFML_API Http : NonCopyable
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class wraps an HTTP request, which is basically :
|
/// \brief Define a HTTP request
|
||||||
/// - 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
|
class SFML_API Request
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Enumerate the available HTTP methods for a request
|
/// \brief Enumerate the available HTTP methods for a request
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
enum Method
|
enum Method
|
||||||
{
|
{
|
||||||
@ -66,58 +65,76 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
/// \param method : Method to use for the request
|
/// This constructor creates a GET request, with the root
|
||||||
/// \param URI : Target URI
|
/// URI ("/") and an empty body.
|
||||||
/// \param body : Content of the request's body
|
///
|
||||||
|
/// \param uri Target URI
|
||||||
|
/// \param method Method to use for the request
|
||||||
|
/// \param body Content of the request's body
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Request(Method method = Get, const std::string& URI = "/", const std::string& body = "");
|
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "");
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the value of a field; the field is added if it doesn't exist
|
/// \brief Set the value of a field
|
||||||
///
|
///
|
||||||
/// \param field : Name of the field to set (case-insensitive)
|
/// The field is created if it doesn't exist. The name of
|
||||||
/// \param value : Value of the field
|
/// the field is case insensitive.
|
||||||
|
/// By default, a request doesn't contain any field (but the
|
||||||
|
/// mandatory fields are added later by the HTTP client when
|
||||||
|
/// sending the request).
|
||||||
|
///
|
||||||
|
/// \param field Name of the field to set
|
||||||
|
/// \param value Value of the field
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SetField(const std::string& field, const std::string& value);
|
void SetField(const std::string& field, const std::string& value);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the request method.
|
/// \brief Set the request method
|
||||||
/// This parameter is Http::Request::Get by default
|
|
||||||
///
|
///
|
||||||
/// \param method : Method to use for the request
|
/// See the Method enumeration for a complete list of all
|
||||||
|
/// the availale methods.
|
||||||
|
/// The method is Http::Request::Get by default.
|
||||||
|
///
|
||||||
|
/// \param method Method to use for the request
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SetMethod(Method method);
|
void SetMethod(Method method);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the target URI of the request.
|
/// \brief Set the requested URI
|
||||||
/// This parameter is "/" by default
|
|
||||||
///
|
///
|
||||||
/// \param URI : URI to request, local to the host
|
/// The URI is the resource (usually a web page or a file)
|
||||||
|
/// that you want to get or post.
|
||||||
|
/// The URI is "/" (the root page) by default.
|
||||||
|
///
|
||||||
|
/// \param uri URI to request, relative to the host
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SetURI(const std::string& URI);
|
void SetUri(const std::string& uri);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the HTTP version of the request.
|
/// \brief Set the HTTP version fo the request
|
||||||
/// This parameter is 1.0 by default
|
|
||||||
///
|
///
|
||||||
/// \param major : Major version number
|
/// The HTTP version is 1.0 by default.
|
||||||
/// \param minor : Minor version number
|
///
|
||||||
|
/// \param major Major HTTP version number
|
||||||
|
/// \param minor Minor HTTP version number
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SetHttpVersion(unsigned int major, unsigned int minor);
|
void SetHttpVersion(unsigned int major, unsigned int minor);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the body of the request. This parameter is optional and
|
/// \brief Set the body of the request
|
||||||
/// makes sense only for POST requests.
|
|
||||||
/// This parameter is empty by default
|
|
||||||
///
|
///
|
||||||
/// \param body : Content of the request body
|
/// The body of a request is optional and only makes sense
|
||||||
|
/// for POST requests. It is ignored for all other methods.
|
||||||
|
/// The body is empty by default.
|
||||||
|
///
|
||||||
|
/// \param body Content of the body
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SetBody(const std::string& body);
|
void SetBody(const std::string& body);
|
||||||
@ -127,19 +144,24 @@ public :
|
|||||||
friend class Http;
|
friend class Http;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the string representation of the request header
|
/// \brief Prepare the final request to send to the server
|
||||||
///
|
///
|
||||||
/// \return String containing the request
|
/// This is used internally by Http before sending the
|
||||||
|
/// request to the web server.
|
||||||
|
///
|
||||||
|
/// \return String containing the request, ready to be sent
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::string ToString() const;
|
std::string Prepare() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Check if the given field has been defined
|
/// \brief Check if the request defines a field
|
||||||
///
|
///
|
||||||
/// \param field : Name of the field to check (case-insensitive)
|
/// This function uses case-insensitive comparisons.
|
||||||
///
|
///
|
||||||
/// \return True if the field exists
|
/// \param field Name of the field to test
|
||||||
|
///
|
||||||
|
/// \return True if the field exists, false otherwise
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool HasField(const std::string& field) const;
|
bool HasField(const std::string& field) const;
|
||||||
@ -152,7 +174,7 @@ public :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
FieldTable myFields; ///< Fields of the header
|
FieldTable myFields; ///< Fields of the header associated to their value
|
||||||
Method myMethod; ///< Method to use for the request
|
Method myMethod; ///< Method to use for the request
|
||||||
std::string myURI; ///< Target URI of the request
|
std::string myURI; ///< Target URI of the request
|
||||||
unsigned int myMajorVersion; ///< Major HTTP version
|
unsigned int myMajorVersion; ///< Major HTTP version
|
||||||
@ -161,17 +183,16 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class wraps an HTTP response, which is basically :
|
/// \brief Define a HTTP response
|
||||||
/// - 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
|
class SFML_API Response
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Enumerate all the valid status codes returned in
|
/// \brief Enumerate all the valid status codes for a response
|
||||||
/// a HTTP response
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
enum Status
|
enum Status
|
||||||
{
|
{
|
||||||
@ -210,15 +231,21 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
/// Constructs an empty response.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Response();
|
Response();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the value of a field
|
/// \brief Get the value of a field
|
||||||
///
|
///
|
||||||
/// \param field : Name of the field to get (case-insensitive)
|
/// If the field \a field is not found in the response header,
|
||||||
|
/// the empty string is returned. This function uses
|
||||||
|
/// case-insensitive comparisons.
|
||||||
|
///
|
||||||
|
/// \param field Name of the field to get
|
||||||
///
|
///
|
||||||
/// \return Value of the field, or empty string if not found
|
/// \return Value of the field, or empty string if not found
|
||||||
///
|
///
|
||||||
@ -226,35 +253,46 @@ public :
|
|||||||
const std::string& GetField(const std::string& field) const;
|
const std::string& GetField(const std::string& field) const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the header's status code
|
/// \brief Get the response status code
|
||||||
///
|
///
|
||||||
/// \return Header's status code
|
/// The status code should be the first thing to be checked
|
||||||
|
/// after receiving a response, it defines whether it is a
|
||||||
|
/// success, a failure or anything else (see the Status
|
||||||
|
/// enumeration).
|
||||||
|
///
|
||||||
|
/// \return Status code of the response
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Status GetStatus() const;
|
Status GetStatus() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the major HTTP version number of the response
|
/// \brief Get the major HTTP version number of the response
|
||||||
///
|
///
|
||||||
/// \return Major version number
|
/// \return Major HTTP version number
|
||||||
|
///
|
||||||
|
/// \see GetMinorHttpVersion
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int GetMajorHttpVersion() const;
|
unsigned int GetMajorHttpVersion() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the major HTTP version number of the response
|
/// \brief Get the minor HTTP version number of the response
|
||||||
///
|
///
|
||||||
/// \return Major version number
|
/// \return Minor HTTP version number
|
||||||
|
///
|
||||||
|
/// \see GetMajorHttpVersion
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int GetMinorHttpVersion() const;
|
unsigned int GetMinorHttpVersion() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the body of the response. The body can contain :
|
/// \brief Get the body of the response
|
||||||
/// - the requested page (for GET requests)
|
///
|
||||||
/// - a response from the server (for POST requests)
|
/// The body of a response may contain:
|
||||||
/// - nothing (for HEAD requests)
|
/// \li the requested page (for GET requests)
|
||||||
/// - an error message (in case of an error)
|
/// \li a response from the server (for POST requests)
|
||||||
|
/// \li nothing (for HEAD requests)
|
||||||
|
/// \li an error message (in case of an error)
|
||||||
///
|
///
|
||||||
/// \return The response body
|
/// \return The response body
|
||||||
///
|
///
|
||||||
@ -266,12 +304,15 @@ public :
|
|||||||
friend class Http;
|
friend class Http;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Construct the header from a response string
|
/// \brief Construct the header from a response string
|
||||||
///
|
///
|
||||||
/// \param data : Content of the response's header to parse
|
/// This function is used by Http to build the response
|
||||||
|
/// of a request.
|
||||||
|
///
|
||||||
|
/// \param data Content of the response to parse
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void FromString(const std::string& data);
|
void Parse(const std::string& data);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Types
|
// Types
|
||||||
@ -289,39 +330,58 @@ public :
|
|||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Http();
|
Http();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Construct the Http instance with the target host
|
/// \brief Construct the HTTP client with the target host
|
||||||
///
|
///
|
||||||
/// \param host : Web server to connect to
|
/// This is equivalent to calling SetHost(host, port).
|
||||||
/// \param port : Port to use for connection (0 by default -- use the standard port of the protocol used)
|
/// The port has a default value of 0, which means that the
|
||||||
|
/// HTTP client will use the right port according to the
|
||||||
|
/// protocol used (80 for HTTP, 443 for HTTPS). You should
|
||||||
|
/// leave it like this unless you really need a port other
|
||||||
|
/// than the standard one, or use an unknown protocol.
|
||||||
|
///
|
||||||
|
/// \param host Web server to connect to
|
||||||
|
/// \param port Port to use for connection
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Http(const std::string& host, unsigned short port = 0);
|
Http(const std::string& host, unsigned short port = 0);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the target host
|
/// \brief Set the target host
|
||||||
///
|
///
|
||||||
/// \param host : Web server to connect to
|
/// This function just stores the host address and port, it
|
||||||
/// \param port : Port to use for connection (0 by default -- use the standard port of the protocol used)
|
/// doesn't actually connect to it until you send a request.
|
||||||
|
/// The port has a default value of 0, which means that the
|
||||||
|
/// HTTP client will use the right port according to the
|
||||||
|
/// protocol used (80 for HTTP, 443 for HTTPS). You should
|
||||||
|
/// leave it like this unless you really need a port other
|
||||||
|
/// than the standard one, or use an unknown protocol.
|
||||||
|
///
|
||||||
|
/// \param host Web server to connect to
|
||||||
|
/// \param port Port to use for connection
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SetHost(const std::string& host, unsigned short port = 0);
|
void SetHost(const std::string& host, unsigned short port = 0);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Send a HTTP request and return the server's response.
|
/// \brief 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 request : Request to send
|
/// You must have a valid host before sending a request (see SetHost).
|
||||||
/// \param timeout : Maximum time to wait, in seconds (0 by default, means no timeout)
|
/// Any missing mandatory header field in the request 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, or use a timeout to limit the time to wait. A value
|
||||||
|
/// of 0 means that the client will use the system defaut timeout
|
||||||
|
/// (which is usually pretty long).
|
||||||
|
///
|
||||||
|
/// \param request Request to send
|
||||||
|
/// \param timeout Maximum time to wait, in seconds
|
||||||
///
|
///
|
||||||
/// \return Server's response
|
/// \return Server's response
|
||||||
///
|
///
|
||||||
@ -333,7 +393,7 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SocketTCP myConnection; ///< Connection to the host
|
TcpSocket myConnection; ///< Connection to the host
|
||||||
IpAddress myHost; ///< Web host address
|
IpAddress myHost; ///< Web host address
|
||||||
std::string myHostName; ///< Web host name
|
std::string myHostName; ///< Web host name
|
||||||
unsigned short myPort; ///< Port used for connection with host
|
unsigned short myPort; ///< Port used for connection with host
|
||||||
@ -343,3 +403,62 @@ private :
|
|||||||
|
|
||||||
|
|
||||||
#endif // SFML_HTTP_HPP
|
#endif // SFML_HTTP_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::Http
|
||||||
|
///
|
||||||
|
/// sf::Http is a very simple HTTP client that allows you
|
||||||
|
/// to communicate with a web server. You can retrieve
|
||||||
|
/// web pages, send data to an interactive resource,
|
||||||
|
/// download a remote file, etc.
|
||||||
|
///
|
||||||
|
/// The HTTP client is split into 3 classes:
|
||||||
|
/// \li sf::Http::Request
|
||||||
|
/// \li sf::Http::Response
|
||||||
|
/// \li sf::Http
|
||||||
|
///
|
||||||
|
/// sf::Http::Request builds the request that will be
|
||||||
|
/// sent to the server. A request is made of:
|
||||||
|
/// \li a method (what you want to do)
|
||||||
|
/// \li a target URI (usually the name of the web page or file)
|
||||||
|
/// \li one or more header fields (options that you can pass to the server)
|
||||||
|
/// \li an optional body (for POST requests)
|
||||||
|
///
|
||||||
|
/// sf::Http::Response parse the response from the web server
|
||||||
|
/// and provides getters to read them. The response contains:
|
||||||
|
/// \li a status code
|
||||||
|
/// \li header fields (that may be answers to the ones that you requested)
|
||||||
|
/// \li a body, which contains the contents of the requested resource
|
||||||
|
///
|
||||||
|
/// sf::Http provides a simple function, SendRequest, to send a
|
||||||
|
/// sf::Http::Request and return the corresponding sf::Http::Response
|
||||||
|
/// from the server.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \code
|
||||||
|
/// // Create a new HTTP client
|
||||||
|
/// sf::Http http;
|
||||||
|
///
|
||||||
|
/// // We'll work on http://www.sfml-dev.org
|
||||||
|
/// http.SetHost("http://www.sfml-dev.org");
|
||||||
|
///
|
||||||
|
/// // Prepare a request to get the 'features.php' page
|
||||||
|
/// sf::Http::Request request("features.php");
|
||||||
|
///
|
||||||
|
/// // Send the request
|
||||||
|
/// sf::Http::Response response = http.SendRequest(request);
|
||||||
|
///
|
||||||
|
/// // Check the status code and display the result
|
||||||
|
/// sf::Http::Response::Status status = response.GetStatus();
|
||||||
|
/// if (status == sf::Http::Response::Ok)
|
||||||
|
/// {
|
||||||
|
/// std::cout << response.GetBody() << std::endl;
|
||||||
|
/// }
|
||||||
|
/// else
|
||||||
|
/// {
|
||||||
|
/// std::cout << "Error " << status << std::endl;
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -105,7 +105,7 @@ public :
|
|||||||
/// \see ToInteger
|
/// \see ToInteger
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IpAddress(Uint32 address);
|
explicit IpAddress(Uint32 address);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get a string representation of the address
|
/// \brief Get a string representation of the address
|
||||||
|
@ -36,77 +36,133 @@
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
class String;
|
class String;
|
||||||
|
class TcpSocket;
|
||||||
|
class UdpSocket;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Packet wraps data to send / to receive through the network
|
/// \brief Utility class to build blocks of data to transfer
|
||||||
|
/// over the network
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API Packet
|
class SFML_API Packet
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
/// Creates an empty packet.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet();
|
Packet();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Virtual destructor
|
/// \brief Virtual destructor
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual ~Packet();
|
virtual ~Packet();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Append data to the end of the packet
|
/// \brief Append data to the end of the packet
|
||||||
///
|
///
|
||||||
/// \param data : Pointer to the bytes to append
|
/// \param data Pointer to the sequence of bytes to append
|
||||||
/// \param sizeInBytes : Number of bytes to append
|
/// \param sizeInBytes Number of bytes to append
|
||||||
|
///
|
||||||
|
/// \see Clear
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Append(const void* data, std::size_t sizeInBytes);
|
void Append(const void* data, std::size_t sizeInBytes);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Clear the packet data
|
/// \brief Clear the packet
|
||||||
|
///
|
||||||
|
/// After calling Clear, the packet is empty.
|
||||||
|
///
|
||||||
|
/// \see Append
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get a pointer to the data contained in the packet
|
/// \brief Get a pointer to the data contained in the packet
|
||||||
/// Warning : the returned pointer may be invalid after you
|
///
|
||||||
/// append data to the packet
|
/// Warning: the returned pointer may become invalid after
|
||||||
|
/// you append data to the packet, therefore it should never
|
||||||
|
/// be stored.
|
||||||
|
/// The return pointer is NULL if the packet is empty.
|
||||||
///
|
///
|
||||||
/// \return Pointer to the data
|
/// \return Pointer to the data
|
||||||
///
|
///
|
||||||
|
/// \see GetDataSize
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const char* GetData() const;
|
const char* GetData() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the size of the data contained in the packet
|
/// \brief Get the size of the data contained in the packet
|
||||||
|
///
|
||||||
|
/// This function returns the number of bytes pointed to by
|
||||||
|
/// what GetData returns.
|
||||||
///
|
///
|
||||||
/// \return Data size, in bytes
|
/// \return Data size, in bytes
|
||||||
///
|
///
|
||||||
|
/// \see GetData
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::size_t GetDataSize() const;
|
std::size_t GetDataSize() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Tell if the reading position has reached the end of the packet
|
/// \brief Tell if the reading position has reached the
|
||||||
|
/// end of the packet
|
||||||
///
|
///
|
||||||
/// \return True if all data have been read into the packet
|
/// This function is useful to know if there is some data
|
||||||
|
/// left to be read, without actually reading it.
|
||||||
|
///
|
||||||
|
/// \return True if all data was read, false otherwise
|
||||||
|
///
|
||||||
|
/// \see operator bool
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool EndOfPacket() const;
|
bool EndOfPacket() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Return the validity of packet
|
/// \brief Test the validity of the packet, for reading
|
||||||
|
///
|
||||||
|
/// This operator allows to test the packet as a boolean
|
||||||
|
/// variable, to check if a reading operation was successful.
|
||||||
|
///
|
||||||
|
/// A packet will be in an invalid state if it has no more
|
||||||
|
/// data to read.
|
||||||
|
///
|
||||||
|
/// This behaviour is the same as standard C++ streams.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \begincode
|
||||||
|
/// float x;
|
||||||
|
/// packet >> x;
|
||||||
|
/// if (packet)
|
||||||
|
/// {
|
||||||
|
/// // ok, x was extracted successfully
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // -- or --
|
||||||
|
///
|
||||||
|
/// float x;
|
||||||
|
/// if (packet >> x)
|
||||||
|
/// {
|
||||||
|
/// // ok, x was extracted successfully
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
///
|
///
|
||||||
/// \return True if last data extraction from packet was successful
|
/// \return True if last data extraction from packet was successful
|
||||||
///
|
///
|
||||||
|
/// \see EndOfPacket
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Operator >> overloads to extract data from the packet
|
/// Overloads of operator >> to read data from the packet
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet& operator >>(bool& data);
|
Packet& operator >>(bool& data);
|
||||||
@ -125,7 +181,7 @@ public :
|
|||||||
Packet& operator >>(String& data);
|
Packet& operator >>(String& data);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Operator << overloads to put data into the packet
|
/// Overloads of operator << to write data into the packet
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet& operator <<(bool data);
|
Packet& operator <<(bool data);
|
||||||
@ -145,37 +201,57 @@ public :
|
|||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
||||||
friend class SocketTCP;
|
friend class TcpSocket;
|
||||||
friend class SocketUDP;
|
friend class UdpSocket;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Check if the packet can extract a given size of bytes
|
/// \brief Check if the packet can extract a given number of bytes
|
||||||
///
|
///
|
||||||
/// \param size : Size to check
|
/// This function updates accordingly the state of the packet.
|
||||||
///
|
///
|
||||||
/// \return True if Size bytes can be read from the packet's data
|
/// \param size Size to check
|
||||||
|
///
|
||||||
|
/// \return True if \a size bytes can be read from the packet
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool CheckSize(std::size_t size);
|
bool CheckSize(std::size_t size);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Called before the packet is sent to the network
|
/// \brief Called before the packet is sent over the network
|
||||||
///
|
///
|
||||||
/// \param dataSize : Variable to fill with the size of data to send
|
/// This function can be defined by derived classes to
|
||||||
|
/// transform the data before it is sent; this can be
|
||||||
|
/// used for compression, encryption, etc.
|
||||||
|
/// The function must return a pointer to the modified data,
|
||||||
|
/// as well as the number of bytes pointed.
|
||||||
|
/// The default implementation provides the packet's data
|
||||||
|
/// without transforming it.
|
||||||
|
///
|
||||||
|
/// \param size Variable to fill with the size of data to send
|
||||||
///
|
///
|
||||||
/// \return Pointer to the array of bytes to send
|
/// \return Pointer to the array of bytes to send
|
||||||
///
|
///
|
||||||
|
/// \see OnReceive
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual const char* OnSend(std::size_t& dataSize);
|
virtual const char* OnSend(std::size_t& size);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Called after the packet has been received from the network
|
/// \brief Called after the packet is received over the network
|
||||||
///
|
///
|
||||||
/// \param data : Pointer to the array of received bytes
|
/// This function can be defined by derived classes to
|
||||||
/// \param dataSize : Size of the array of bytes
|
/// transform the data after it is received; this can be
|
||||||
|
/// used for uncompression, decryption, etc.
|
||||||
|
/// The function receives a pointer to the received data,
|
||||||
|
/// and must fill the packet with the transformed bytes.
|
||||||
|
/// The default implementation fills the packet directly
|
||||||
|
/// without transforming the data.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the received bytes
|
||||||
|
/// \param size Number of bytes
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void OnReceive(const char* data, std::size_t dataSize);
|
virtual void OnReceive(const char* data, std::size_t size);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
@ -189,3 +265,122 @@ private :
|
|||||||
|
|
||||||
|
|
||||||
#endif // SFML_PACKET_HPP
|
#endif // SFML_PACKET_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::Packet
|
||||||
|
///
|
||||||
|
/// Packets provide a safe and easy way to serialize data,
|
||||||
|
/// in order to send it over the network using sockets
|
||||||
|
/// (sf::TcpSocket, sf::UdpSocket).
|
||||||
|
///
|
||||||
|
/// Packets solve 2 fundamental problems that arise when
|
||||||
|
/// transfering data over the network:
|
||||||
|
/// \li data is interpreted correctly according to the endianness
|
||||||
|
/// \li the bounds of the packet are preserved (one send == one receive)
|
||||||
|
///
|
||||||
|
/// The sf::Packet class provides both input and output modes.
|
||||||
|
/// It is designed to follow the behaviour of standard C++ streams,
|
||||||
|
/// using operators >> and << to extract and insert data.
|
||||||
|
///
|
||||||
|
/// It is recommended to use only fixed-size types (like sf::Int32, etc.),
|
||||||
|
/// to avoid possible differences between the sender and the receiver.
|
||||||
|
/// Indeed, the native C++ types may have different sizes on two platforms
|
||||||
|
/// and your data may be corrupted if that happens.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \begincode
|
||||||
|
/// sf::Uint32 x = 24;
|
||||||
|
/// std::string s = "hello";
|
||||||
|
/// double d = 5.89;
|
||||||
|
///
|
||||||
|
/// // Group the variables to send into a packet
|
||||||
|
/// sf::Packet packet;
|
||||||
|
/// packet << x << s << d;
|
||||||
|
///
|
||||||
|
/// // Send it over the network (socket is a valid sf::TcpSocket)
|
||||||
|
/// socket.Send(packet);
|
||||||
|
///
|
||||||
|
/// -----------------------------------------------------------------
|
||||||
|
///
|
||||||
|
/// // Receive the packet at the other end
|
||||||
|
/// sf::Packet packet;
|
||||||
|
/// socket.Receive(packet);
|
||||||
|
///
|
||||||
|
/// // Extract the variables contained in the packet
|
||||||
|
/// sf::Uint32 x;
|
||||||
|
/// std::string s;
|
||||||
|
/// double d;
|
||||||
|
/// if (packet >> x >> s >> d)
|
||||||
|
/// {
|
||||||
|
/// // Data extracted successfully...
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// Packets have built-in operator >> and << overloads for
|
||||||
|
/// standard types:
|
||||||
|
/// \li bool
|
||||||
|
/// \li fixed-size integer types (sf::Int8/16/32, sf::Uint8/16/32)
|
||||||
|
/// \li floating point numbers (float, double)
|
||||||
|
/// \li string types (char*, wchar_t*, std::string, std::wstring, sf::String)
|
||||||
|
///
|
||||||
|
/// Like standard streams, it is also possible to define your own
|
||||||
|
/// overloads of operators >> and << in order to handle your
|
||||||
|
/// custom types.
|
||||||
|
///
|
||||||
|
/// \begincode
|
||||||
|
/// struct MyStruct
|
||||||
|
/// {
|
||||||
|
/// float number;
|
||||||
|
/// sf::Int8 integer;
|
||||||
|
/// std::string str;
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// sf::Packet& operator <<(sf::Packet& packet, const MyStruct& m)
|
||||||
|
/// {
|
||||||
|
/// return packet << m.number << m.integer << m.str;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// sf::Packet& operator >>(sf::Packet& packet, MyStruct& m)
|
||||||
|
/// {
|
||||||
|
/// return packet >> m.number >> m.integer >> m.str;
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// Packets also provide an extra feature that allows to apply
|
||||||
|
/// custom transformations to the data before it is sent,
|
||||||
|
/// and after it is received. This is typically used to
|
||||||
|
/// handle automatic compression or encryption of the data.
|
||||||
|
/// This is achieved by inheriting from sf::Packet, and overriding
|
||||||
|
/// the OnSend and OnReceive functions.
|
||||||
|
///
|
||||||
|
/// Here is an example:
|
||||||
|
/// \begincode
|
||||||
|
/// class ZipPacket : public sf::Packet
|
||||||
|
/// {
|
||||||
|
/// virtual const char* OnSend(std::size_t& size)
|
||||||
|
/// {
|
||||||
|
/// const char* srcData = GetData();
|
||||||
|
/// std::size_t srcSize = GetDataSize();
|
||||||
|
///
|
||||||
|
/// return MySuperZipFunction(srcData, srcSize, &size);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// virtual void OnReceive(const char* data, std::size_t size)
|
||||||
|
/// {
|
||||||
|
/// std::size_t dstSize;
|
||||||
|
/// const char* dstData = MySuperUnzipFunction(data, size, &dstSize);
|
||||||
|
///
|
||||||
|
/// Append(dstData, dstSize);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // Use like regular packets:
|
||||||
|
/// ZipPacket packet;
|
||||||
|
/// packet << x << s << d;
|
||||||
|
/// ...
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// \see sf::TcpSocket, sf::UdpSocket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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) const;
|
|
||||||
|
|
||||||
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
|
|
@ -1,97 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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) const
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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) const;
|
|
||||||
|
|
||||||
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
|
|
234
include/SFML/Network/Socket.hpp
Normal file
234
include/SFML/Network/Socket.hpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_SOCKET_HPP
|
||||||
|
#define SFML_SOCKET_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/SocketHandle.hpp>
|
||||||
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class SocketSelector;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Base class for all the socket types
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API Socket : NonCopyable
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Status codes that may be 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
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Some special values used by sockets
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
AnyPort = 0 ///< Special value that tells the system to pick any available port
|
||||||
|
};
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Destructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual ~Socket();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the blocking state of the socket
|
||||||
|
///
|
||||||
|
/// In blocking mode, calls will not return until they have
|
||||||
|
/// completed their task. For example, a call to Receive in
|
||||||
|
/// blocking mode won't return until some data was actually
|
||||||
|
/// received.
|
||||||
|
/// In non-blocking mode, calls will always return immediately,
|
||||||
|
/// using the return code to signal whether there was data
|
||||||
|
/// available or not.
|
||||||
|
/// By default, all sockets are blocking.
|
||||||
|
///
|
||||||
|
/// \param blocking True to set the socket as blocking, false for non-blocking
|
||||||
|
///
|
||||||
|
/// \see IsBlocking
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SetBlocking(bool blocking);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Tell whether the socket is blocking or non-blocking mode
|
||||||
|
///
|
||||||
|
/// \return True if the socket is blocking, false otherwise
|
||||||
|
///
|
||||||
|
/// \see SetBlocking
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IsBlocking() const;
|
||||||
|
|
||||||
|
protected :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Types of protocols that the socket can use
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Tcp, ///< TCP protocol
|
||||||
|
Udp ///< UDP protocol
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Structure holding the data of a pending packet
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
struct PendingPacket
|
||||||
|
{
|
||||||
|
PendingPacket();
|
||||||
|
|
||||||
|
Uint32 Size; ///< Data of packet size
|
||||||
|
std::size_t SizeReceived; ///< Number of size bytes received so far
|
||||||
|
std::vector<char> Data; ///< Data of the packet
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
/// This constructor can only be accessed by derived classes.
|
||||||
|
///
|
||||||
|
/// \param type Type of the socket (TCP or UDP)
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket(Type type);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Return the internal handle of the socket
|
||||||
|
///
|
||||||
|
/// The returned handle may be invalid if the socket
|
||||||
|
/// was not created yet (or already destroyed).
|
||||||
|
/// This function can only be accessed by derived classes.
|
||||||
|
///
|
||||||
|
/// \return The internal (OS-specific) handle of the socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHandle GetHandle() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Create the internal representation of the socket
|
||||||
|
///
|
||||||
|
/// This function can only be accessed by derived classes.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Create();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Create the internal representation of the socket
|
||||||
|
/// from a socket handle
|
||||||
|
///
|
||||||
|
/// This function can only be accessed by derived classes.
|
||||||
|
///
|
||||||
|
/// \param handle OS-specific handle of the socket to wrap
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Create(SocketHandle handle);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Close the socket gracefully
|
||||||
|
///
|
||||||
|
/// This function can only be accessed by derived classes.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
PendingPacket myPendingPacket; ///< Temporary data of the packet currently being received
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
friend class SocketSelector;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Type myType; ///< Type of the socket (TCP or UDP)
|
||||||
|
SocketHandle mySocket; ///< Socket descriptor
|
||||||
|
bool myIsBlocking; ///< Current blocking mode of the socket
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKET_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::Socket
|
||||||
|
///
|
||||||
|
/// This class mainly defines internal stuff to be used by
|
||||||
|
/// derived classes.
|
||||||
|
///
|
||||||
|
/// The only public features that it defines, and which
|
||||||
|
/// is therefore common to all the socket classes, is the
|
||||||
|
/// blocking state. All sockets can be set as blocking or
|
||||||
|
/// non-blocking.
|
||||||
|
///
|
||||||
|
/// In blocking mode, socket functions will hang until
|
||||||
|
/// the operation completes, which means that the entire
|
||||||
|
/// program (well, in fact the current thread if you use
|
||||||
|
/// multiple ones) will be stuck waiting for your socket
|
||||||
|
/// operation to complete.
|
||||||
|
///
|
||||||
|
/// In non-blocking mode, all the socket functions will
|
||||||
|
/// return immediately. If the socket is not ready to complete
|
||||||
|
/// the requested operation, the function simply returns
|
||||||
|
/// the proper status code (Socket::NotReady).
|
||||||
|
///
|
||||||
|
/// The default mode, which is blocking, is the one that is
|
||||||
|
/// generally used, in combination with threads or selectors.
|
||||||
|
/// The non-blocking mode is rather used in real-time
|
||||||
|
/// applications that run an endless loop that can poll
|
||||||
|
/// the socket often enough, and cannot afford blocking
|
||||||
|
/// this loop.
|
||||||
|
///
|
||||||
|
/// \see sf::TcpListener, sf::TcpSocket, sf::UdpSocket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
@ -22,43 +22,36 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETHELPER_HPP
|
#ifndef SFML_SOCKETHANDLE_HPP
|
||||||
#define SFML_SOCKETHELPER_HPP
|
#define SFML_SOCKETHANDLE_HPP
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Config.hpp>
|
#include <SFML/Config.hpp>
|
||||||
|
|
||||||
|
#if defined(SFML_SYSTEM_WINDOWS)
|
||||||
|
#include <BaseTsd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
namespace Socket
|
////////////////////////////////////////////////////////////
|
||||||
{
|
// Define the low-level socket handle type, specific to
|
||||||
////////////////////////////////////////////////////////////
|
// each platform
|
||||||
/// Enumeration of status returned by socket functions
|
////////////////////////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////
|
#if defined(SFML_SYSTEM_WINDOWS)
|
||||||
enum Status
|
|
||||||
{
|
typedef UINT_PTR SocketHandle;
|
||||||
Done, ///< The socket has sent / received the data
|
|
||||||
NotReady, ///< The socket is not ready to send / receive data yet
|
#else
|
||||||
Disconnected, ///< The TCP socket has been disconnected
|
|
||||||
Error ///< An unexpected error happened
|
typedef int SocketHandle;
|
||||||
};
|
|
||||||
}
|
#endif
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
#ifdef SFML_SYSTEM_WINDOWS
|
#endif // SFML_SOCKETHANDLE_HPP
|
||||||
|
|
||||||
#include <SFML/Network/Win32/SocketHelper.hpp>
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <SFML/Network/Unix/SocketHelper.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETHELPER_HPP
|
|
251
include/SFML/Network/SocketSelector.hpp
Normal file
251
include/SFML/Network/SocketSelector.hpp
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_SOCKETSELECTOR_HPP
|
||||||
|
#define SFML_SOCKETSELECTOR_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Config.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class Socket;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Multiplexer that allows to read from multiple sockets
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API SocketSelector
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketSelector();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Copy constructor
|
||||||
|
///
|
||||||
|
/// \param copy Instance to copy
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketSelector(const SocketSelector& copy);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Destructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
~SocketSelector();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Add a new socket to the selector
|
||||||
|
///
|
||||||
|
/// This function keeps a weak reference to the socket,
|
||||||
|
/// so you have to make sure that the socket is not destroyed
|
||||||
|
/// while it is stored in the selector.
|
||||||
|
///
|
||||||
|
/// \param socket Reference to the socket to add
|
||||||
|
///
|
||||||
|
/// \see Remove, Clear
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Add(Socket& socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Remove a socket from the selector
|
||||||
|
///
|
||||||
|
/// This function doesn't destroy the socket, it simply
|
||||||
|
/// removes the reference that the selector has to it.
|
||||||
|
///
|
||||||
|
/// \param socket Reference to the socket to remove
|
||||||
|
///
|
||||||
|
/// \see Add, Clear
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Remove(Socket& socket);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Remove all the sockets stored in the selector
|
||||||
|
///
|
||||||
|
/// This function doesn't destroy any instance, it simply
|
||||||
|
/// removes all the references that the selector has to
|
||||||
|
/// external sockets.
|
||||||
|
///
|
||||||
|
/// \see Add, Remove
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Wait until one or more sockets are ready to receive
|
||||||
|
///
|
||||||
|
/// This function returns as soon as at least one socket has
|
||||||
|
/// some data available to be received. To know which sockets are
|
||||||
|
/// ready, use the IsReady function.
|
||||||
|
/// If you use a timeout and no socket is ready before the timeout
|
||||||
|
/// is over, the function returns false.
|
||||||
|
///
|
||||||
|
/// \return True if there are sockets ready, false otherwise
|
||||||
|
///
|
||||||
|
/// \see IsReady
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Wait(float timeout = 0.f);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Test a socket to know if it is ready to receive data
|
||||||
|
///
|
||||||
|
/// This function must be used after a call to Wait, to know
|
||||||
|
/// which sockets are ready to receive data. If a socket is
|
||||||
|
/// ready, a call to Receive will never block because we know
|
||||||
|
/// that there is data available to read.
|
||||||
|
/// Note that if this function returns true for a TcpListener,
|
||||||
|
/// this means that it is ready to accept a new connection.
|
||||||
|
///
|
||||||
|
/// \return True if the socket is ready to read, false otherwise
|
||||||
|
///
|
||||||
|
/// \see IsReady
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool IsReady(Socket& socket) const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Overload of assignment operator
|
||||||
|
///
|
||||||
|
/// \param right Instance to assign
|
||||||
|
///
|
||||||
|
/// \return Reference to self
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketSelector& operator =(const SocketSelector& right);
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
struct SocketSelectorImpl;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Member data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketSelectorImpl* myImpl; ///< Opaque pointer to the implementation (which requires OS-specific types)
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_SOCKETSELECTOR_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::SocketSelector
|
||||||
|
///
|
||||||
|
/// Socket selectors provide a way to wait until some data is
|
||||||
|
/// available on a set of sockets, instead of just one. This
|
||||||
|
/// is convenient when you have multiple sockets that may
|
||||||
|
/// possibly receive data, but you don't know which one will
|
||||||
|
/// be ready first. In particular, it avoids to use a thread
|
||||||
|
/// for each socket; with selectors, a single thread can handle
|
||||||
|
/// all the sockets.
|
||||||
|
///
|
||||||
|
/// All types of sockets can be used in a selector:
|
||||||
|
/// \li sf::TcpListener
|
||||||
|
/// \li sf::TcpSocket
|
||||||
|
/// \li sf::UdpSocket
|
||||||
|
///
|
||||||
|
/// A selector doesn't store its own copies of the sockets
|
||||||
|
/// (socket classes are not copyable anyway), it simply keeps
|
||||||
|
/// a reference to the original sockets that you pass to the
|
||||||
|
/// Add function. Therefore, you can't use the selector as a
|
||||||
|
/// socket container, you must store them oustide and make sure
|
||||||
|
/// that they are alive as long as they are used in the selector.
|
||||||
|
///
|
||||||
|
/// Using a selector is simple:
|
||||||
|
/// \li populate the selector with all the sockets that you want to observe
|
||||||
|
/// \li make it wait until there is data available on any of the sockets
|
||||||
|
/// \li test each socket to find out which ones are ready
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \code
|
||||||
|
/// // Create a socket to listen to new connections
|
||||||
|
/// sf::TcpListener listener;
|
||||||
|
/// listener.Listen(55001);
|
||||||
|
///
|
||||||
|
/// // Create a list to store the future clients
|
||||||
|
/// std::list<sf::TcpSocket*> clients;
|
||||||
|
///
|
||||||
|
/// // Create a selector
|
||||||
|
/// sf::SocketSelector selector;
|
||||||
|
///
|
||||||
|
/// // Add the listener to the selector
|
||||||
|
/// selector.Add(listener);
|
||||||
|
///
|
||||||
|
/// // Endless loop that waits for new connections
|
||||||
|
/// while (running)
|
||||||
|
/// {
|
||||||
|
/// // Make the selector wait for data on any socket
|
||||||
|
/// if (selector.Wait())
|
||||||
|
/// {
|
||||||
|
/// // Test the listener
|
||||||
|
/// if (selector.IsReady(listener))
|
||||||
|
/// {
|
||||||
|
/// // The listener is ready: there is a pending connection
|
||||||
|
/// sf::TcpSocket* client = new sf::TcpSocket;
|
||||||
|
/// if (listener.accept(*client) == sf::Socket::Done)
|
||||||
|
/// {
|
||||||
|
/// // Add the new client to the clients list
|
||||||
|
/// clients.push_back(client);
|
||||||
|
///
|
||||||
|
/// // Add the new client to the selector so that we will
|
||||||
|
/// // be notified when he sends something
|
||||||
|
/// selector.Add(*client);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// else
|
||||||
|
/// {
|
||||||
|
/// // The listener socket is not ready, test all other sockets (the clients)
|
||||||
|
/// for (std::list<sf::TcpSocket*>::iterator it = clients.begin(); it != clients.end(); ++it)
|
||||||
|
/// {
|
||||||
|
/// sf::TcpSocket& client = **it;
|
||||||
|
/// if (selector.IsReady(client))
|
||||||
|
/// {
|
||||||
|
/// // The client has sent some data, we can receive it
|
||||||
|
/// sf::Packet packet;
|
||||||
|
/// if (client.Receive(packet) == sf::Socket::Done)
|
||||||
|
/// {
|
||||||
|
/// ...
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// \see sf::Socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
@ -1,227 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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 host : 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& host, 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
|
|
||||||
///
|
|
||||||
/// \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 sizeInBytes : Number of bytes to send
|
|
||||||
///
|
|
||||||
/// \return Status code
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status Send(const char* data, std::size_t sizeInBytes);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// 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 packet : Packet to send
|
|
||||||
///
|
|
||||||
/// \return Status code
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status Send(Packet& packet);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Receive a packet from the host (must be connected first).
|
|
||||||
/// This function will block if the socket is blocking
|
|
||||||
///
|
|
||||||
/// \param packet : Packet to fill with received data
|
|
||||||
///
|
|
||||||
/// \return Status code
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status Receive(Packet& packet);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// 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
|
|
||||||
Uint32 myPendingHeader; ///< Data of the current pending packet header, if any
|
|
||||||
Uint32 myPendingHeaderSize; ///< Size of the current pending packet header, if any
|
|
||||||
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any
|
|
||||||
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any
|
|
||||||
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace sf
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETTCP_HPP
|
|
@ -1,228 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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 sizeInBytes : 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 sizeInBytes, 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
|
|
||||||
/// \param port : Port on which the remote computer sent the data
|
|
||||||
///
|
|
||||||
/// \return Status code
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status Receive(char* data, std::size_t maxSize, std::size_t& sizeReceived, IpAddress& address, unsigned short& port);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Send a packet of data
|
|
||||||
///
|
|
||||||
/// \param packet : 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& packet, const IpAddress& address, unsigned short port);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Receive a packet.
|
|
||||||
/// This function will block if the socket is blocking
|
|
||||||
///
|
|
||||||
/// \param packet : Packet to fill with received data
|
|
||||||
/// \param Address : Address of the computer which sent the packet
|
|
||||||
/// \param Port : Port on which the remote computer sent the data
|
|
||||||
///
|
|
||||||
/// \return Status code
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status Receive(Packet& packet, IpAddress& address, unsigned short& port);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// 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
|
|
||||||
Uint32 myPendingHeader; ///< Data of the current pending packet header, if any
|
|
||||||
Uint32 myPendingHeaderSize; ///< Size of the current pending packet header, if any
|
|
||||||
std::vector<char> myPendingPacket; ///< Data of the current pending packet, if any
|
|
||||||
Int32 myPendingPacketSize; ///< Size of the current pending packet, if any
|
|
||||||
bool myIsBlocking; ///< Is the socket blocking or non-blocking ?
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace sf
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETUDP_HPP
|
|
131
include/SFML/Network/TcpListener.hpp
Normal file
131
include/SFML/Network/TcpListener.hpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_TCPLISTENER_HPP
|
||||||
|
#define SFML_TCPLISTENER_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Socket.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class TcpSocket;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Socket that listens to new TCP connections
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API TcpListener : public Socket
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
TcpListener();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Start listening for connections
|
||||||
|
///
|
||||||
|
/// This functions makes the socket listen to the specified
|
||||||
|
/// port, waiting for new connections.
|
||||||
|
/// If the socket was previously listening to another port,
|
||||||
|
/// it will be stopped first and bound to the new port.
|
||||||
|
///
|
||||||
|
/// \param port Port to listen for new connections
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Accept, Close
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Listen(unsigned short port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Accept a new connection
|
||||||
|
///
|
||||||
|
/// If the socket is in blocking mode, this function will
|
||||||
|
/// not return until a connection is actually received.
|
||||||
|
///
|
||||||
|
/// \param socket Socket that will hold the new connection
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Listen
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Accept(TcpSocket& socket);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_TCPLISTENER_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::TcpListener
|
||||||
|
///
|
||||||
|
/// A listener socket is a special type of socket that listens to
|
||||||
|
/// a given port and waits for connections on that port.
|
||||||
|
/// This is all it can do.
|
||||||
|
///
|
||||||
|
/// When a new connection is received, the socket returns a
|
||||||
|
/// new instance of sf::TcpSocket that is properly
|
||||||
|
/// initialized and can be used to communicate with the
|
||||||
|
/// new client.
|
||||||
|
///
|
||||||
|
/// Listener sockets are specific to the TCP protocol,
|
||||||
|
/// UDP sockets are connectionless and can therefore communicate
|
||||||
|
/// directly. As a consequence, a listener socket will always
|
||||||
|
/// return the new connections as sf::TcpSocket instances.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \code
|
||||||
|
/// // Create a listener socket and make it wait for new
|
||||||
|
/// // connections on port 55001
|
||||||
|
/// sf::TcpListener listener;
|
||||||
|
/// listener.Listen(55001);
|
||||||
|
///
|
||||||
|
/// // Endless loop that waits for new connections
|
||||||
|
/// while (running)
|
||||||
|
/// {
|
||||||
|
/// sf::TcpSocket client;
|
||||||
|
/// if (listener.accept(client) == sf::Socket::Done)
|
||||||
|
/// {
|
||||||
|
/// // A new client just connected!
|
||||||
|
/// std::cout << "New connection received from " << client.GetRemoteAddress() << std::endl;
|
||||||
|
/// DoSomethingWith(client);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// \see sf::TcpSocket, sf::Socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
271
include/SFML/Network/TcpSocket.hpp
Normal file
271
include/SFML/Network/TcpSocket.hpp
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_TCPSOCKET_HPP
|
||||||
|
#define SFML_TCPSOCKET_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Socket.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class TcpListener;
|
||||||
|
class IpAddress;
|
||||||
|
class Packet;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Specialized socket using the TCP protocol
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API TcpSocket : public Socket
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
TcpSocket();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the port to which the socket is bound locally
|
||||||
|
///
|
||||||
|
/// If the socket is not connected, this function returns 0.
|
||||||
|
///
|
||||||
|
/// \return Port to which the socket is bound
|
||||||
|
///
|
||||||
|
/// \see Connect, GetRemotePort
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short GetLocalPort() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the address of the connected peer
|
||||||
|
///
|
||||||
|
/// It the socket is not connected, this function returns
|
||||||
|
/// sf::IpAddress::None.
|
||||||
|
///
|
||||||
|
/// \return Address of the remote peer
|
||||||
|
///
|
||||||
|
/// \see GetRemotePort
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IpAddress GetRemoteAddress() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the port of the connected peer to which
|
||||||
|
/// the socket is connected
|
||||||
|
///
|
||||||
|
/// If the socket is not connected, this function returns 0.
|
||||||
|
///
|
||||||
|
/// \return Remote port to which the socket is connected
|
||||||
|
///
|
||||||
|
/// \see GetRemoteAddress
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short GetRemotePort() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Connect the socket to a remote peer
|
||||||
|
///
|
||||||
|
/// In blocking mode, this function may take a while, especially
|
||||||
|
/// if the remote peer is not reachable. The last parameter allows
|
||||||
|
/// you to stop trying to connect after a given timeout.
|
||||||
|
/// If the socket was previously connected, it is first disconnected.
|
||||||
|
///
|
||||||
|
/// \param remoteAddress Address of the remote peer
|
||||||
|
/// \param remotePort Port of the remote peer
|
||||||
|
/// \param timeout Optional maximum time to wait, in seconds
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Disconnect
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Connect(const IpAddress& remoteAddress, unsigned short remotePort, float timeout = 0.f);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Disconnect the connect from its remote peer
|
||||||
|
///
|
||||||
|
/// This function gracefully closes the connection. If the
|
||||||
|
/// socket is not connected, this function has no effect.
|
||||||
|
///
|
||||||
|
/// \see Connect
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Disconnect();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Send raw data to the remote peer
|
||||||
|
///
|
||||||
|
/// This function will fail if the socket is not connected.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the sequence of bytes to send
|
||||||
|
/// \param size Number of bytes to send
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Receive
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Send(const char* data, std::size_t size);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Receive raw data from the remote peer
|
||||||
|
///
|
||||||
|
/// In blocking mode, this function will wait until some
|
||||||
|
/// bytes are actually received.
|
||||||
|
/// This function will fail if the socket is not connected.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the array to fill with the received bytes
|
||||||
|
/// \param size Maximum number of bytes that can be received
|
||||||
|
/// \param received This variable is filled with the actual number of bytes received
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Send
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Receive(char* data, std::size_t size, std::size_t& received);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Send a formatted packet of data to the remote peer
|
||||||
|
///
|
||||||
|
/// This function will fail if the socket is not connected.
|
||||||
|
///
|
||||||
|
/// \param packet Packet to send
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Receive
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Send(Packet& packet);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Receive a formatted packet of data from the remote peer
|
||||||
|
///
|
||||||
|
/// In blocking mode, this function will wait until the whole packet
|
||||||
|
/// has been received.
|
||||||
|
/// This function will fail if the socket is not connected.
|
||||||
|
///
|
||||||
|
/// \param packet Packet to fill with the received data
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Send
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Receive(Packet& packet);
|
||||||
|
|
||||||
|
friend class TcpListener;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_TCPSOCKET_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::TcpSocket
|
||||||
|
///
|
||||||
|
/// TCP is a connected protocol, which means that a TCP
|
||||||
|
/// socket can only communicate with the host it is connected
|
||||||
|
/// to. It can't send or receive anything if it is not connected.
|
||||||
|
///
|
||||||
|
/// The TCP protocol is reliable but adds a slight overhead.
|
||||||
|
/// It ensures that your data will always be received in order
|
||||||
|
/// and without errors (no data corrupted, lost or duplicated).
|
||||||
|
///
|
||||||
|
/// When a socket is connected to a remote host, you can
|
||||||
|
/// retrieve informations about this host with the
|
||||||
|
/// GetRemoteAddress and GetRemotePort functions. You can
|
||||||
|
/// also get the local port to which the socket is bound
|
||||||
|
/// (which is automatically chosen when the socket is connected),
|
||||||
|
/// with the GetLocalPort function.
|
||||||
|
///
|
||||||
|
/// Sending and receiving data can use either the low-level
|
||||||
|
/// or the high-level functions. The low-level functions
|
||||||
|
/// process a raw sequence of bytes, and cannot ensure that
|
||||||
|
/// one call to Send will exactly match one call to Receive
|
||||||
|
/// at the other end of the socket.
|
||||||
|
///
|
||||||
|
/// The high-level interface uses packets (see sf::Packet),
|
||||||
|
/// which are easier to use and provide more safety regarding
|
||||||
|
/// the data that is exchanged. You can look at the sf::Packet
|
||||||
|
/// class to get more details about how they work.
|
||||||
|
///
|
||||||
|
/// The socket is automatically disconnected when it is destroyed,
|
||||||
|
/// but if you want to explicitely close the connection while
|
||||||
|
/// the socket instance is still alive, you can call Disconnect.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \code
|
||||||
|
/// // ----- The client -----
|
||||||
|
///
|
||||||
|
/// // Create a socket and connect it to 192.168.1.50 on port 55001
|
||||||
|
/// sf::TcpSocket socket;
|
||||||
|
/// socket.Connect("192.168.1.50", 55001);
|
||||||
|
///
|
||||||
|
/// // Send a message to the connected host
|
||||||
|
/// std::string message = "Hi, I am a client";
|
||||||
|
/// socket.Send(message.c_str(), message.size() + 1);
|
||||||
|
///
|
||||||
|
/// // Receive an answer from the server
|
||||||
|
/// char buffer[1024];
|
||||||
|
/// std::size_t received = 0;
|
||||||
|
/// socket.Receive(buffer, sizeof(buffer), received);
|
||||||
|
/// std::cout << "The server said: " << buffer << std::endl;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // ----- The server -----
|
||||||
|
///
|
||||||
|
/// // Create a listener to wait for incoming connections on port 55001
|
||||||
|
/// sf::TcpListener listener;
|
||||||
|
/// listener.Listen(55001);
|
||||||
|
///
|
||||||
|
/// // Wait for a connection
|
||||||
|
/// sf::TcpSocket socket;
|
||||||
|
/// listener.Accept(socket);
|
||||||
|
/// std::cout << "New client connected: " << socket.GetRemoteAddress() << std::endl;
|
||||||
|
///
|
||||||
|
/// // Receive a message from the client
|
||||||
|
/// char buffer[1024];
|
||||||
|
/// std::size_t received = 0;
|
||||||
|
/// socket.Receive(buffer, sizeof(buffer), received);
|
||||||
|
/// std::cout << "The client said: " << buffer << std::endl;
|
||||||
|
///
|
||||||
|
/// // Send an answer
|
||||||
|
/// std::string message = "Welcome, client";
|
||||||
|
/// socket.Send(message.c_str(), message.size() + 1);
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// \see sf::Socket, sf::UdpSocket, sf::Packet
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
242
include/SFML/Network/UdpSocket.hpp
Normal file
242
include/SFML/Network/UdpSocket.hpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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_UDPSOCKET_HPP
|
||||||
|
#define SFML_UDPSOCKET_HPP
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Headers
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Socket.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
class IpAddress;
|
||||||
|
class Packet;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Specialized socket using the UDP protocol
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
class SFML_API UdpSocket : public Socket
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Default constructor
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
UdpSocket();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get the port to which the socket is bound locally
|
||||||
|
///
|
||||||
|
/// If the socket is not bound to a port, this function
|
||||||
|
/// returns 0.
|
||||||
|
///
|
||||||
|
/// \return Port to which the socket is bound
|
||||||
|
///
|
||||||
|
/// \see Bind
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short GetLocalPort() const;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Bind the socket to a specific port
|
||||||
|
///
|
||||||
|
/// Binding the socket to a port is necessary for being
|
||||||
|
/// able to receive data on that port.
|
||||||
|
/// You can use the special value Socket::AnyPort to tell the
|
||||||
|
/// system to automatically pick an available port, and then
|
||||||
|
/// call GetLocalPort to retrieve the chosen port.
|
||||||
|
///
|
||||||
|
/// \param port Port to bind the socket to
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Unbind, GetLocalPort
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Bind(unsigned short port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Unbind the socket from the local port to which it is bound
|
||||||
|
///
|
||||||
|
/// The port that the socket was previously using is immediately
|
||||||
|
/// available after this function is called. If the
|
||||||
|
/// socket is not bound to a port, this function has no effect.
|
||||||
|
///
|
||||||
|
/// \see Bind
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Unbind();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Send raw data to a remote peer
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the sequence of bytes to send
|
||||||
|
/// \param size Number of bytes to send
|
||||||
|
/// \param remoteAddress Address of the receiver
|
||||||
|
/// \param remotePort Port of the receiver to send the data to
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Receive
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Send(const char* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Receive raw data from a remote peer
|
||||||
|
///
|
||||||
|
/// In blocking mode, this function will wait until some
|
||||||
|
/// bytes are actually received.
|
||||||
|
///
|
||||||
|
/// \param data Pointer to the array to fill with the received bytes
|
||||||
|
/// \param size Maximum number of bytes that can be received
|
||||||
|
/// \param received This variable is filled with the actual number of bytes received
|
||||||
|
/// \param remoteAddress Address of the peer that sent the data
|
||||||
|
/// \param remotePort Port of the peer that sent the data
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Send
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Receive(char* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Send a formatted packet of data to a remote peer
|
||||||
|
///
|
||||||
|
/// \param packet Packet to send
|
||||||
|
/// \param remoteAddress Address of the receiver
|
||||||
|
/// \param remotePort Port of the receiver to send the data to
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Receive
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Receive a formatted packet of data from a remote peer
|
||||||
|
///
|
||||||
|
/// In blocking mode, this function will wait until the whole packet
|
||||||
|
/// has been received.
|
||||||
|
///
|
||||||
|
/// \param packet Packet to fill with the received data
|
||||||
|
/// \param remoteAddress Address of the peer that sent the data
|
||||||
|
/// \param remotePort Port of the peer that sent the data
|
||||||
|
///
|
||||||
|
/// \return Status code
|
||||||
|
///
|
||||||
|
/// \see Send
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Status Receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SFML_UDPSOCKET_HPP
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \class sf::UdpSocket
|
||||||
|
///
|
||||||
|
/// A UDP socket is a connectionless socket. Instead of
|
||||||
|
/// connecting once to a remote host, like TCP sockets,
|
||||||
|
/// it can send to and receive from any host at any time.
|
||||||
|
///
|
||||||
|
/// The UDP protocol is lightweight but unreliable. Unreliable
|
||||||
|
/// means that the data may be corrupted, duplicated, lost or
|
||||||
|
/// arrive out of order. UDP is generally used for real-time
|
||||||
|
/// communication (audio or video streaming, real-time games,
|
||||||
|
/// etc.) where speed is crucial and corrupted data
|
||||||
|
/// doesn't matter much.
|
||||||
|
///
|
||||||
|
/// Sending and receiving data can use either the low-level
|
||||||
|
/// or the high-level functions. The low-level functions
|
||||||
|
/// process a raw sequence of bytes, and cannot ensure that
|
||||||
|
/// one call to Send will exactly match one call to Receive
|
||||||
|
/// at the other end of the socket.
|
||||||
|
///
|
||||||
|
/// The high-level interface uses packets (see sf::Packet),
|
||||||
|
/// which are easier to use and provide more safety regarding
|
||||||
|
/// the data that is exchanged. You can look at the sf::Packet
|
||||||
|
/// class to get more details about how they work.
|
||||||
|
///
|
||||||
|
/// If the socket is bound to a port, it is automatically
|
||||||
|
/// unbound from it when the socket is destroyed. However,
|
||||||
|
/// you can unbind the socket explicitely with the Unbind
|
||||||
|
/// function if necessary, to stop receiving messages or
|
||||||
|
/// make the port available for other sockets.
|
||||||
|
///
|
||||||
|
/// Usage example:
|
||||||
|
/// \code
|
||||||
|
/// // ----- The client -----
|
||||||
|
///
|
||||||
|
/// // Create a socket and bind it to the port 55001
|
||||||
|
/// sf::UdpSocket socket;
|
||||||
|
/// socket.Bind(55001);
|
||||||
|
///
|
||||||
|
/// // Send a message to 192.168.1.50 on port 55002
|
||||||
|
/// std::string message = "Hi, I am " + sf::IpAddress::GetLocalAddress().ToString();
|
||||||
|
/// socket.Send(message.c_str(), message.size() + 1, "192.168.1.50", 55002);
|
||||||
|
///
|
||||||
|
/// // Receive an answer (most likely from 192.168.1.50, but could be anyone else)
|
||||||
|
/// char buffer[1024];
|
||||||
|
/// std::size_t received = 0;
|
||||||
|
/// sf::IpAddress sender;
|
||||||
|
/// unsigned short port;
|
||||||
|
/// socket.Receive(buffer, sizeof(buffer), received, sender, port);
|
||||||
|
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // ----- The server -----
|
||||||
|
///
|
||||||
|
/// // Create a socket and bind it to the port 55002
|
||||||
|
/// sf::UdpSocket socket;
|
||||||
|
/// socket.Bind(55002);
|
||||||
|
///
|
||||||
|
/// // Receive a message from anyone
|
||||||
|
/// char buffer[1024];
|
||||||
|
/// std::size_t received = 0;
|
||||||
|
/// sf::IpAddress sender;
|
||||||
|
/// unsigned short port;
|
||||||
|
/// socket.Receive(buffer, sizeof(buffer), received, sender, port);
|
||||||
|
/// std::cout << sender.ToString() << " said: " << buffer << std::endl;
|
||||||
|
///
|
||||||
|
/// // Send an answer
|
||||||
|
/// std::string message = "Welcome " + sender.ToString();
|
||||||
|
/// socket.Send(message.c_str(), message.size() + 1, sender, port);
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// \see sf::Socket, sf::TcpSocket, sf::Packet
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
@ -90,7 +90,7 @@ int main()
|
|||||||
|
|
||||||
case 1 :
|
case 1 :
|
||||||
{
|
{
|
||||||
// Print current server directory
|
// Print the current server directory
|
||||||
sf::Ftp::DirectoryResponse response = server.GetWorkingDirectory();
|
sf::Ftp::DirectoryResponse response = server.GetWorkingDirectory();
|
||||||
std::cout << response << std::endl;
|
std::cout << response << std::endl;
|
||||||
std::cout << "Current directory is " << response.GetDirectory() << std::endl;
|
std::cout << "Current directory is " << response.GetDirectory() << std::endl;
|
||||||
@ -99,11 +99,12 @@ int main()
|
|||||||
|
|
||||||
case 2 :
|
case 2 :
|
||||||
{
|
{
|
||||||
// Print content of current server directory
|
// Print the contents of the current server directory
|
||||||
sf::Ftp::ListingResponse response = server.GetDirectoryListing();
|
sf::Ftp::ListingResponse response = server.GetDirectoryListing();
|
||||||
std::cout << response << std::endl;
|
std::cout << response << std::endl;
|
||||||
for (std::size_t i = 0; i < response.GetCount(); ++i)
|
std::vector<std::string> filenames = response.GetFilenames();
|
||||||
std::cout << response.GetFilename(i) << std::endl;
|
for (std::vector<std::string>::const_iterator it = filenames.begin(); it != filenames.end(); ++it)
|
||||||
|
std::cout << *it << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ int main()
|
|||||||
std::string directory;
|
std::string directory;
|
||||||
std::cout << "Name of the directory to create: ";
|
std::cout << "Name of the directory to create: ";
|
||||||
std::cin >> directory;
|
std::cin >> directory;
|
||||||
std::cout << server.MakeDirectory(directory) << std::endl;
|
std::cout << server.CreateDirectory(directory) << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,14 +6,10 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
void RunTcpServer(unsigned short Port);
|
||||||
// Function prototypes
|
void RunTcpClient(unsigned short Port);
|
||||||
// (I'm too lazy to put them into separate headers...)
|
void RunUdpServer(unsigned short Port);
|
||||||
////////////////////////////////////////////////////////////
|
void RunUdpClient(unsigned short Port);
|
||||||
void DoClientTCP(unsigned short Port);
|
|
||||||
void DoClientUDP(unsigned short Port);
|
|
||||||
void DoServerTCP(unsigned short Port);
|
|
||||||
void DoServerUDP(unsigned short Port);
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -24,34 +20,34 @@ void DoServerUDP(unsigned short Port);
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Choose a random port for opening sockets (ports < 1024 are reserved)
|
// Choose an arbitrary port for opening sockets
|
||||||
const unsigned short port = 2435;
|
const unsigned short port = 50001;
|
||||||
|
|
||||||
// TCP or UDP ?
|
// TCP, UDP or connected UDP ?
|
||||||
char protocol;
|
char protocol;
|
||||||
std::cout << "Do you want to use TCP ('t') or UDP ('u') ? ";
|
std::cout << "Do you want to use TCP (t) or UDP (u) ? ";
|
||||||
std::cin >> protocol;
|
std::cin >> protocol;
|
||||||
|
|
||||||
// Client or server ?
|
// Client or server ?
|
||||||
char who;
|
char who;
|
||||||
std::cout << "Do you want to be a server ('s') or a client ('c') ? ";
|
std::cout << "Do you want to be a server (s) or a client (c) ? ";
|
||||||
std::cin >> who;
|
std::cin >> who;
|
||||||
|
|
||||||
if (who == 's')
|
if (protocol == 't')
|
||||||
{
|
{
|
||||||
// Run as a server
|
// Test the TCP protocol
|
||||||
if (protocol == 't')
|
if (who == 's')
|
||||||
DoServerTCP(port);
|
RunTcpServer(port);
|
||||||
else
|
else
|
||||||
DoServerUDP(port);
|
RunTcpClient(port);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Run as a client
|
// Test the unconnected UDP protocol
|
||||||
if (protocol == 't')
|
if (who == 's')
|
||||||
DoClientTCP(port);
|
RunUdpServer(port);
|
||||||
else
|
else
|
||||||
DoClientUDP(port);
|
RunUdpClient(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until the user presses 'enter' key
|
// Wait until the user presses 'enter' key
|
||||||
|
@ -7,87 +7,75 @@
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create a client and connect it to a running server
|
/// Launch a server, wait for an incoming connection,
|
||||||
|
/// send a message and wait for the answer.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void DoClientTCP(unsigned short port)
|
void RunTcpServer(unsigned short port)
|
||||||
{
|
{
|
||||||
// Ask for server address
|
// Create a server socket to accept new connections
|
||||||
sf::IpAddress serverAddress;
|
sf::TcpListener listener;
|
||||||
do
|
|
||||||
{
|
|
||||||
std::cout << "Type address or name of the server to connect to : ";
|
|
||||||
std::cin >> serverAddress;
|
|
||||||
}
|
|
||||||
while (serverAddress == sf::IpAddress::None);
|
|
||||||
|
|
||||||
// Create a TCP socket for communicating with server
|
// Listen to the given port for incoming connections
|
||||||
sf::SocketTCP client;
|
if (listener.Listen(port) != sf::Socket::Done)
|
||||||
|
|
||||||
// Connect to the specified server
|
|
||||||
if (client.Connect(port, serverAddress) != sf::Socket::Done)
|
|
||||||
return;
|
|
||||||
std::cout << "Connected to server " << serverAddress << std::endl;
|
|
||||||
|
|
||||||
// Receive a message from the client
|
|
||||||
char message[128];
|
|
||||||
std::size_t received;
|
|
||||||
if (client.Receive(message, sizeof(message), received) != sf::Socket::Done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Show it
|
|
||||||
std::cout << "Message received from server : \"" << message << "\"" << std::endl;
|
|
||||||
|
|
||||||
// Define a message to send back to the server
|
|
||||||
char toSend[] = "Hi, I'm a client !";
|
|
||||||
|
|
||||||
// Send the message
|
|
||||||
if (client.Send(toSend, sizeof(toSend)) != sf::Socket::Done)
|
|
||||||
return;
|
|
||||||
std::cout << "Message sent to server : \"" << toSend << "\"" << std::endl;
|
|
||||||
|
|
||||||
// Close the socket when we're done
|
|
||||||
client.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Launch a server and wait for incoming connections
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void DoServerTCP(unsigned short port)
|
|
||||||
{
|
|
||||||
// Create a TCP socket for communicating with clients
|
|
||||||
sf::SocketTCP server;
|
|
||||||
|
|
||||||
// Listen to a port for incoming connections
|
|
||||||
if (!server.Listen(port))
|
|
||||||
return;
|
return;
|
||||||
std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl;
|
std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl;
|
||||||
|
|
||||||
// Wait for a connection
|
// Wait for a connection
|
||||||
sf::IpAddress clientAddress;
|
sf::TcpSocket socket;
|
||||||
sf::SocketTCP client;
|
if (listener.Accept(socket) != sf::Socket::Done)
|
||||||
if (server.Accept(client, &clientAddress) != sf::Socket::Done)
|
|
||||||
return;
|
return;
|
||||||
std::cout << "Client connected : " << clientAddress << std::endl;
|
std::cout << "Client connected: " << socket.GetRemoteAddress() << std::endl;
|
||||||
|
|
||||||
// Send a message to the client
|
// Send a message to the connected client
|
||||||
char toSend[] = "Hi, I'm the server";
|
const char out[] = "Hi, I'm the server";
|
||||||
if (client.Send(toSend, sizeof(toSend)) != sf::Socket::Done)
|
if (socket.Send(out, sizeof(out)) != sf::Socket::Done)
|
||||||
return;
|
return;
|
||||||
std::cout << "Message sent to the client : \"" << toSend << "\"" << std::endl;
|
std::cout << "Message sent to the client: \"" << out << "\"" << std::endl;
|
||||||
|
|
||||||
// Receive a message back from the client
|
// Receive a message back from the client
|
||||||
char message[128];
|
char in[128];
|
||||||
std::size_t received;
|
std::size_t received;
|
||||||
if (client.Receive(message, sizeof(message), received) != sf::Socket::Done)
|
if (socket.Receive(in, sizeof(in), received) != sf::Socket::Done)
|
||||||
return;
|
return;
|
||||||
|
std::cout << "Answer received from the client: \"" << in << "\"" << std::endl;
|
||||||
// Show the message
|
}
|
||||||
std::cout << "Message received from the client : \"" << message << "\"" << std::endl;
|
|
||||||
|
|
||||||
// Close the sockets when we're done
|
////////////////////////////////////////////////////////////
|
||||||
client.Close();
|
/// Create a client, connect it to a server, display the
|
||||||
server.Close();
|
/// welcome message and send an answer.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void RunTcpClient(unsigned short port)
|
||||||
|
{
|
||||||
|
// Ask for the server address
|
||||||
|
sf::IpAddress server;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::cout << "Type the address or name of the server to connect to: ";
|
||||||
|
std::cin >> server;
|
||||||
|
}
|
||||||
|
while (server == sf::IpAddress::None);
|
||||||
|
|
||||||
|
// Create a socket for communicating with the server
|
||||||
|
sf::TcpSocket socket;
|
||||||
|
|
||||||
|
// Connect to the server
|
||||||
|
if (socket.Connect(server, port) != sf::Socket::Done)
|
||||||
|
return;
|
||||||
|
std::cout << "Connected to server " << server << std::endl;
|
||||||
|
|
||||||
|
// Receive a message from the server
|
||||||
|
char in[128];
|
||||||
|
std::size_t received;
|
||||||
|
if (socket.Receive(in, sizeof(in), received) != sf::Socket::Done)
|
||||||
|
return;
|
||||||
|
std::cout << "Message received from the server: \"" << in << "\"" << std::endl;
|
||||||
|
|
||||||
|
// Send an answer to the server
|
||||||
|
const char out[] = "Hi, I'm a client";
|
||||||
|
if (socket.Send(out, sizeof(out)) != sf::Socket::Done)
|
||||||
|
return;
|
||||||
|
std::cout << "Message sent to the server: \"" << out << "\"" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -7,59 +7,66 @@
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create a client and send a message to a running server
|
/// Launch a server, wait for a message, send an answer.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void DoClientUDP(unsigned short port)
|
void RunUdpServer(unsigned short port)
|
||||||
{
|
{
|
||||||
// Ask for server address
|
// Create a socket to receive a message from anyone
|
||||||
sf::IpAddress serverAddress;
|
sf::UdpSocket socket;
|
||||||
|
|
||||||
|
// Listen to messages on the specified port
|
||||||
|
if (socket.Bind(port) != sf::Socket::Done)
|
||||||
|
return;
|
||||||
|
std::cout << "Server is listening to port " << port << ", waiting for a message... " << std::endl;
|
||||||
|
|
||||||
|
// Wait for a message
|
||||||
|
char in[128];
|
||||||
|
std::size_t received;
|
||||||
|
sf::IpAddress sender;
|
||||||
|
unsigned short senderPort;
|
||||||
|
if (socket.Receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done)
|
||||||
|
return;
|
||||||
|
std::cout << "Message received from client " << sender << ": \"" << in << "\"" << std::endl;
|
||||||
|
|
||||||
|
// Send an answer to the client
|
||||||
|
const char out[] = "Hi, I'm the server";
|
||||||
|
if (socket.Send(out, sizeof(out), sender, senderPort) != sf::Socket::Done)
|
||||||
|
return;
|
||||||
|
std::cout << "Message sent to the client: \"" << out << "\"" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Send a message to the server, wait for the answer
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void RunUdpClient(unsigned short port)
|
||||||
|
{
|
||||||
|
// Ask for the server address
|
||||||
|
sf::IpAddress server;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
std::cout << "Type address or name of the server to send the message to : ";
|
std::cout << "Type the address or name of the server to connect to: ";
|
||||||
std::cin >> serverAddress;
|
std::cin >> server;
|
||||||
}
|
}
|
||||||
while (serverAddress == sf::IpAddress::None);
|
while (server == sf::IpAddress::None);
|
||||||
|
|
||||||
// Create a UDP socket for communicating with server
|
// Create a socket for communicating with the server
|
||||||
sf::SocketUDP client;
|
sf::UdpSocket socket;
|
||||||
|
|
||||||
// Send a message to the server
|
// Send a message to the server
|
||||||
char message[] = "Hi, I'm a client !";
|
const char out[] = "Hi, I'm a client";
|
||||||
if (client.Send(message, sizeof(message), serverAddress, port) != sf::Socket::Done)
|
if (socket.Send(out, sizeof(out), server, port) != sf::Socket::Done)
|
||||||
return;
|
return;
|
||||||
std::cout << "Message sent to server : \"" << message << "\"" << std::endl;
|
std::cout << "Message sent to the server: \"" << out << "\"" << std::endl;
|
||||||
|
|
||||||
// Close the socket when we're done
|
// Receive an answer from anyone (but most likely from the server)
|
||||||
client.Close();
|
char in[128];
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Launch a server and wait for incoming messages
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void DoServerUDP(unsigned short port)
|
|
||||||
{
|
|
||||||
// Create a UDP socket for communicating with clients
|
|
||||||
sf::SocketUDP server;
|
|
||||||
|
|
||||||
// Bind it to the specified port
|
|
||||||
if (!server.Bind(port))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Receive a message from anyone
|
|
||||||
sf::IpAddress clientAddress;
|
|
||||||
unsigned short clientPort;
|
|
||||||
char message[128];
|
|
||||||
std::size_t received;
|
std::size_t received;
|
||||||
if (server.Receive(message, sizeof(message), received, clientAddress, clientPort) != sf::Socket::Done)
|
sf::IpAddress sender;
|
||||||
|
unsigned short senderPort;
|
||||||
|
if (socket.Receive(in, sizeof(in), received, sender, senderPort) != sf::Socket::Done)
|
||||||
return;
|
return;
|
||||||
|
std::cout << "Message received from " << sender << ": \"" << in << "\"" << std::endl;
|
||||||
// Display it
|
|
||||||
std::cout << "Message received from " << clientAddress << " on port " << clientPort
|
|
||||||
<< ": \"" << message << "\"" << std::endl;
|
|
||||||
|
|
||||||
// Close the socket when we're done
|
|
||||||
server.Close();
|
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,35 @@ public :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Constructor
|
/// Constructor
|
||||||
///
|
///
|
||||||
/// \param Socket : Socket that holds the connection with the server
|
/// \param host Remote host to which send the recording data
|
||||||
|
/// \param port Port of the remote host
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
NetworkRecorder(sf::SocketTCP socket) :
|
NetworkRecorder(const sf::IpAddress& host, unsigned short port) :
|
||||||
mySocket(socket)
|
myHost(host),
|
||||||
|
myPort(port)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// /see SoundRecorder::OnStart
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual bool OnStart()
|
||||||
|
{
|
||||||
|
if (mySocket.Connect(myHost, myPort) == sf::Socket::Done)
|
||||||
|
{
|
||||||
|
std::cout << "Connected to server " << myHost << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// /see SoundRecorder::ProcessSamples
|
/// /see SoundRecorder::ProcessSamples
|
||||||
///
|
///
|
||||||
@ -48,10 +66,27 @@ private :
|
|||||||
return mySocket.Send(packet) == sf::Socket::Done;
|
return mySocket.Send(packet) == sf::Socket::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// /see SoundRecorder::OnStop
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void OnStop()
|
||||||
|
{
|
||||||
|
// Send a "end-of-stream" packet
|
||||||
|
sf::Packet packet;
|
||||||
|
packet << endOfStream;
|
||||||
|
mySocket.Send(packet);
|
||||||
|
|
||||||
|
// Close the socket
|
||||||
|
mySocket.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sf::SocketTCP mySocket; ///< Socket used to communicate with the server
|
sf::IpAddress myHost; ///< Address of the remote host
|
||||||
|
unsigned short myPort; ///< Remote port
|
||||||
|
sf::TcpSocket mySocket; ///< Socket used to communicate with the server
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -70,41 +105,25 @@ void DoClient(unsigned short port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ask for server address
|
// Ask for server address
|
||||||
sf::IpAddress serverAddress;
|
sf::IpAddress server;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
std::cout << "Type address or name of the server to connect to : ";
|
std::cout << "Type address or name of the server to connect to : ";
|
||||||
std::cin >> serverAddress;
|
std::cin >> server;
|
||||||
}
|
}
|
||||||
while (serverAddress == sf::IpAddress::None);
|
while (server == sf::IpAddress::None);
|
||||||
|
|
||||||
// Create a TCP socket for communicating with server
|
// Create an instance of our custom recorder
|
||||||
sf::SocketTCP socket;
|
NetworkRecorder recorder(server, port);
|
||||||
|
|
||||||
// Connect to the specified server
|
|
||||||
if (socket.Connect(port, serverAddress) != sf::Socket::Done)
|
|
||||||
return;
|
|
||||||
std::cout << "Connected to server " << serverAddress << std::endl;
|
|
||||||
|
|
||||||
// Wait for user input...
|
// Wait for user input...
|
||||||
std::cin.ignore(10000, '\n');
|
std::cin.ignore(10000, '\n');
|
||||||
std::cout << "Press enter to start recording audio";
|
std::cout << "Press enter to start recording audio";
|
||||||
std::cin.ignore(10000, '\n');
|
std::cin.ignore(10000, '\n');
|
||||||
|
|
||||||
// Create a instance of our custom recorder
|
|
||||||
NetworkRecorder recorder(socket);
|
|
||||||
|
|
||||||
// Start capturing audio data
|
// Start capturing audio data
|
||||||
recorder.Start(44100);
|
recorder.Start(44100);
|
||||||
std::cout << "Recording... press enter to stop";
|
std::cout << "Recording... press enter to stop";
|
||||||
std::cin.ignore(10000, '\n');
|
std::cin.ignore(10000, '\n');
|
||||||
recorder.Stop();
|
recorder.Stop();
|
||||||
|
|
||||||
// Send a "end-of-stream" packet
|
|
||||||
sf::Packet packet;
|
|
||||||
packet << endOfStream;
|
|
||||||
socket.Send(packet);
|
|
||||||
|
|
||||||
// Close the socket when we're done
|
|
||||||
socket.Close();
|
|
||||||
}
|
}
|
||||||
|
@ -32,17 +32,6 @@ public :
|
|||||||
Initialize(1, 44100);
|
Initialize(1, 44100);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Destructor
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
~NetworkAudioStream()
|
|
||||||
{
|
|
||||||
// Close the sockets
|
|
||||||
myClient.Close();
|
|
||||||
myListener.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Run the server, stream audio data from the client
|
/// Run the server, stream audio data from the client
|
||||||
///
|
///
|
||||||
@ -52,14 +41,14 @@ public :
|
|||||||
if (!myHasFinished)
|
if (!myHasFinished)
|
||||||
{
|
{
|
||||||
// Listen to the given port for incoming connections
|
// Listen to the given port for incoming connections
|
||||||
if (!myListener.Listen(port))
|
if (myListener.Listen(port) != sf::Socket::Done)
|
||||||
return;
|
return;
|
||||||
std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl;
|
std::cout << "Server is listening to port " << port << ", waiting for connections... " << std::endl;
|
||||||
|
|
||||||
// Wait for a connection
|
// Wait for a connection
|
||||||
sf::IpAddress clientAddress;
|
if (myListener.Accept(myClient) != sf::Socket::Done)
|
||||||
myListener.Accept(myClient, &clientAddress);
|
return;
|
||||||
std::cout << "Client connected : " << clientAddress << std::endl;
|
std::cout << "Client connected: " << myClient.GetRemoteAddress() << std::endl;
|
||||||
|
|
||||||
// Start playback
|
// Start playback
|
||||||
Play();
|
Play();
|
||||||
@ -149,7 +138,7 @@ private :
|
|||||||
else if (id == endOfStream)
|
else if (id == endOfStream)
|
||||||
{
|
{
|
||||||
// End of stream reached : we stop receiving audio data
|
// End of stream reached : we stop receiving audio data
|
||||||
std::cout << "Audio data has been 100% received !" << std::endl;
|
std::cout << "Audio data has been 100% received!" << std::endl;
|
||||||
myHasFinished = true;
|
myHasFinished = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -164,8 +153,8 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
sf::SocketTCP myListener;
|
sf::TcpListener myListener;
|
||||||
sf::SocketTCP myClient;
|
sf::TcpSocket myClient;
|
||||||
sf::Mutex myMutex;
|
sf::Mutex myMutex;
|
||||||
std::vector<sf::Int16> mySamples;
|
std::vector<sf::Int16> mySamples;
|
||||||
std::vector<sf::Int16> myTempBuffer;
|
std::vector<sf::Int16> myTempBuffer;
|
||||||
|
@ -36,35 +36,19 @@
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Utility class for exchanging stuff with the server
|
|
||||||
// on the data channel
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
class Ftp::DataChannel : NonCopyable
|
class Ftp::DataChannel : NonCopyable
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
DataChannel(Ftp& owner);
|
DataChannel(Ftp& owner);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Destructor
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
~DataChannel();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Open the data channel using the specified mode and port
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Open(Ftp::TransferMode mode);
|
Ftp::Response Open(Ftp::TransferMode mode);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Send data on the data channel
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Send(const std::vector<char>& data);
|
void Send(const std::vector<char>& data);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
// Receive data on the data channel until it is closed
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Receive(std::vector<char>& data);
|
void Receive(std::vector<char>& data);
|
||||||
|
|
||||||
@ -74,12 +58,10 @@ private :
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp& myFtp; ///< Reference to the owner Ftp instance
|
Ftp& myFtp; ///< Reference to the owner Ftp instance
|
||||||
SocketTCP myDataSocket; ///< Socket used for data transfers
|
TcpSocket myDataSocket; ///< Socket used for data transfers
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Default constructor
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response::Response(Status code, const std::string& message) :
|
Ftp::Response::Response(Status code, const std::string& message) :
|
||||||
myStatus (code),
|
myStatus (code),
|
||||||
@ -89,9 +71,6 @@ myMessage(message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Convenience function to check if the response status code
|
|
||||||
/// means a success
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Ftp::Response::IsOk() const
|
bool Ftp::Response::IsOk() const
|
||||||
{
|
{
|
||||||
@ -99,8 +78,6 @@ bool Ftp::Response::IsOk() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the response status code
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response::Status Ftp::Response::GetStatus() const
|
Ftp::Response::Status Ftp::Response::GetStatus() const
|
||||||
{
|
{
|
||||||
@ -108,8 +85,6 @@ Ftp::Response::Status Ftp::Response::GetStatus() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the full message contained in the response
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const std::string& Ftp::Response::GetMessage() const
|
const std::string& Ftp::Response::GetMessage() const
|
||||||
{
|
{
|
||||||
@ -118,23 +93,19 @@ const std::string& Ftp::Response::GetMessage() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
Ftp::DirectoryResponse::DirectoryResponse(const Ftp::Response& response) :
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Ftp::DirectoryResponse::DirectoryResponse(Ftp::Response response) :
|
|
||||||
Ftp::Response(response)
|
Ftp::Response(response)
|
||||||
{
|
{
|
||||||
if (IsOk())
|
if (IsOk())
|
||||||
{
|
{
|
||||||
// Extract the directory from the server response
|
// Extract the directory from the server response
|
||||||
std::string::size_type begin = response.GetMessage().find('"', 0);
|
std::string::size_type begin = GetMessage().find('"', 0);
|
||||||
std::string::size_type end = response.GetMessage().find('"', begin + 1);
|
std::string::size_type end = GetMessage().find('"', begin + 1);
|
||||||
myDirectory = response.GetMessage().substr(begin + 1, end - begin - 1);
|
myDirectory = GetMessage().substr(begin + 1, end - begin - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the directory returned in the response
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const std::string& Ftp::DirectoryResponse::GetDirectory() const
|
const std::string& Ftp::DirectoryResponse::GetDirectory() const
|
||||||
{
|
{
|
||||||
@ -143,9 +114,7 @@ const std::string& Ftp::DirectoryResponse::GetDirectory() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
Ftp::ListingResponse::ListingResponse(const Ftp::Response& response, const std::vector<char>& data) :
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Ftp::ListingResponse::ListingResponse(Ftp::Response response, const std::vector<char>& data) :
|
|
||||||
Ftp::Response(response)
|
Ftp::Response(response)
|
||||||
{
|
{
|
||||||
if (IsOk())
|
if (IsOk())
|
||||||
@ -163,25 +132,12 @@ Ftp::Response(response)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the number of filenames in the listing
|
const std::vector<std::string>& Ftp::ListingResponse::GetFilenames() const
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::size_t Ftp::ListingResponse::GetCount() const
|
|
||||||
{
|
{
|
||||||
return myFilenames.size();
|
return myFilenames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// 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()
|
Ftp::~Ftp()
|
||||||
{
|
{
|
||||||
@ -189,13 +145,11 @@ Ftp::~Ftp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Connect to the specified FTP server
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::Connect(const IpAddress& server, unsigned short port, float timeout)
|
Ftp::Response Ftp::Connect(const IpAddress& server, unsigned short port, float timeout)
|
||||||
{
|
{
|
||||||
// Connect to the server
|
// Connect to the server
|
||||||
if (myCommandSocket.Connect(port, server, timeout) != Socket::Done)
|
if (myCommandSocket.Connect(server, port, timeout) != Socket::Done)
|
||||||
return Response(Response::ConnectionFailed);
|
return Response(Response::ConnectionFailed);
|
||||||
|
|
||||||
// Get the response to the connection
|
// Get the response to the connection
|
||||||
@ -203,8 +157,6 @@ Ftp::Response Ftp::Connect(const IpAddress& server, unsigned short port, float t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Log in using anonymous account
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::Login()
|
Ftp::Response Ftp::Login()
|
||||||
{
|
{
|
||||||
@ -212,8 +164,6 @@ Ftp::Response Ftp::Login()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Log in using a username and a password
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::Login(const std::string& name, const std::string& password)
|
Ftp::Response Ftp::Login(const std::string& name, const std::string& password)
|
||||||
{
|
{
|
||||||
@ -225,22 +175,18 @@ Ftp::Response Ftp::Login(const std::string& name, const std::string& password)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the connection with FTP server
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::Disconnect()
|
Ftp::Response Ftp::Disconnect()
|
||||||
{
|
{
|
||||||
// Send the exit command
|
// Send the exit command
|
||||||
Response response = SendCommand("QUIT");
|
Response response = SendCommand("QUIT");
|
||||||
if (response.IsOk())
|
if (response.IsOk())
|
||||||
myCommandSocket.Close();
|
myCommandSocket.Disconnect();
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Send a null command just to prevent from being disconnected
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::KeepAlive()
|
Ftp::Response Ftp::KeepAlive()
|
||||||
{
|
{
|
||||||
@ -248,8 +194,6 @@ Ftp::Response Ftp::KeepAlive()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the current working directory
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::DirectoryResponse Ftp::GetWorkingDirectory()
|
Ftp::DirectoryResponse Ftp::GetWorkingDirectory()
|
||||||
{
|
{
|
||||||
@ -257,9 +201,6 @@ Ftp::DirectoryResponse Ftp::GetWorkingDirectory()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the contents of the given directory
|
|
||||||
/// (subdirectories and files)
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::ListingResponse Ftp::GetDirectoryListing(const std::string& directory)
|
Ftp::ListingResponse Ftp::GetDirectoryListing(const std::string& directory)
|
||||||
{
|
{
|
||||||
@ -285,8 +226,6 @@ Ftp::ListingResponse Ftp::GetDirectoryListing(const std::string& directory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Change the current working directory
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::ChangeDirectory(const std::string& directory)
|
Ftp::Response Ftp::ChangeDirectory(const std::string& directory)
|
||||||
{
|
{
|
||||||
@ -294,8 +233,6 @@ Ftp::Response Ftp::ChangeDirectory(const std::string& directory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Go to the parent directory of the current one
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::ParentDirectory()
|
Ftp::Response Ftp::ParentDirectory()
|
||||||
{
|
{
|
||||||
@ -304,16 +241,12 @@ Ftp::Response Ftp::ParentDirectory()
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create a new directory
|
Ftp::Response Ftp::CreateDirectory(const std::string& name)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Ftp::Response Ftp::MakeDirectory(const std::string& name)
|
|
||||||
{
|
{
|
||||||
return SendCommand("MKD", name);
|
return SendCommand("MKD", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Remove an existing directory
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::DeleteDirectory(const std::string& name)
|
Ftp::Response Ftp::DeleteDirectory(const std::string& name)
|
||||||
{
|
{
|
||||||
@ -321,8 +254,6 @@ Ftp::Response Ftp::DeleteDirectory(const std::string& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Rename a file
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::RenameFile(const std::string& file, const std::string& newName)
|
Ftp::Response Ftp::RenameFile(const std::string& file, const std::string& newName)
|
||||||
{
|
{
|
||||||
@ -334,8 +265,6 @@ Ftp::Response Ftp::RenameFile(const std::string& file, const std::string& newNam
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Remove an existing file
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::DeleteFile(const std::string& name)
|
Ftp::Response Ftp::DeleteFile(const std::string& name)
|
||||||
{
|
{
|
||||||
@ -344,9 +273,7 @@ Ftp::Response Ftp::DeleteFile(const std::string& name)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Download a file from the server
|
Ftp::Response Ftp::Download(const std::string& remoteFile, const std::string& localPath, TransferMode mode)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Ftp::Response Ftp::Download(const std::string& distantFile, const std::string& destPath, TransferMode mode)
|
|
||||||
{
|
{
|
||||||
// Open a data channel using the given transfer mode
|
// Open a data channel using the given transfer mode
|
||||||
DataChannel data(*this);
|
DataChannel data(*this);
|
||||||
@ -354,7 +281,7 @@ Ftp::Response Ftp::Download(const std::string& distantFile, const std::string& d
|
|||||||
if (response.IsOk())
|
if (response.IsOk())
|
||||||
{
|
{
|
||||||
// Tell the server to start the transfer
|
// Tell the server to start the transfer
|
||||||
response = SendCommand("RETR", distantFile);
|
response = SendCommand("RETR", remoteFile);
|
||||||
if (response.IsOk())
|
if (response.IsOk())
|
||||||
{
|
{
|
||||||
// Receive the file data
|
// Receive the file data
|
||||||
@ -366,13 +293,13 @@ Ftp::Response Ftp::Download(const std::string& distantFile, const std::string& d
|
|||||||
if (response.IsOk())
|
if (response.IsOk())
|
||||||
{
|
{
|
||||||
// Extract the filename from the file path
|
// Extract the filename from the file path
|
||||||
std::string filename = distantFile;
|
std::string filename = remoteFile;
|
||||||
std::string::size_type pos = filename.find_last_of("/\\");
|
std::string::size_type pos = filename.find_last_of("/\\");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
filename = filename.substr(pos + 1);
|
filename = filename.substr(pos + 1);
|
||||||
|
|
||||||
// Make sure the destination path ends with a slash
|
// Make sure the destination path ends with a slash
|
||||||
std::string path = destPath;
|
std::string path = localPath;
|
||||||
if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/'))
|
if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/'))
|
||||||
path += "/";
|
path += "/";
|
||||||
|
|
||||||
@ -392,9 +319,7 @@ Ftp::Response Ftp::Download(const std::string& distantFile, const std::string& d
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Upload a file to the server
|
Ftp::Response Ftp::Upload(const std::string& localFile, const std::string& remotePath, TransferMode mode)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Ftp::Response Ftp::Upload(const std::string& localFile, const std::string& destPath, TransferMode mode)
|
|
||||||
{
|
{
|
||||||
// Get the contents of the file to send
|
// Get the contents of the file to send
|
||||||
std::ifstream file(localFile.c_str(), std::ios_base::binary);
|
std::ifstream file(localFile.c_str(), std::ios_base::binary);
|
||||||
@ -415,7 +340,7 @@ Ftp::Response Ftp::Upload(const std::string& localFile, const std::string& destP
|
|||||||
filename = filename.substr(pos + 1);
|
filename = filename.substr(pos + 1);
|
||||||
|
|
||||||
// Make sure the destination path ends with a slash
|
// Make sure the destination path ends with a slash
|
||||||
std::string path = destPath;
|
std::string path = remotePath;
|
||||||
if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/'))
|
if (!path.empty() && (path[path.size() - 1] != '\\') && (path[path.size() - 1] != '/'))
|
||||||
path += "/";
|
path += "/";
|
||||||
|
|
||||||
@ -440,8 +365,6 @@ Ftp::Response Ftp::Upload(const std::string& localFile, const std::string& destP
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Send a command to the FTP server
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::SendCommand(const std::string& command, const std::string& parameter)
|
Ftp::Response Ftp::SendCommand(const std::string& command, const std::string& parameter)
|
||||||
{
|
{
|
||||||
@ -461,9 +384,6 @@ Ftp::Response Ftp::SendCommand(const std::string& command, const std::string& pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Receive a response from the server
|
|
||||||
/// (usually after a command has been sent)
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::Response Ftp::GetResponse()
|
Ftp::Response Ftp::GetResponse()
|
||||||
{
|
{
|
||||||
@ -596,8 +516,6 @@ Ftp::Response Ftp::GetResponse()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Constructor
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Ftp::DataChannel::DataChannel(Ftp& owner) :
|
Ftp::DataChannel::DataChannel(Ftp& owner) :
|
||||||
myFtp(owner)
|
myFtp(owner)
|
||||||
@ -606,18 +524,6 @@ 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)
|
Ftp::Response Ftp::DataChannel::Open(Ftp::TransferMode mode)
|
||||||
{
|
{
|
||||||
@ -653,7 +559,7 @@ Ftp::Response Ftp::DataChannel::Open(Ftp::TransferMode mode)
|
|||||||
static_cast<Uint8>(data[3]));
|
static_cast<Uint8>(data[3]));
|
||||||
|
|
||||||
// Connect the data channel to the server
|
// Connect the data channel to the server
|
||||||
if (myDataSocket.Connect(port, address) == Socket::Done)
|
if (myDataSocket.Connect(address, port) == Socket::Done)
|
||||||
{
|
{
|
||||||
// Translate the transfer mode to the corresponding FTP parameter
|
// Translate the transfer mode to the corresponding FTP parameter
|
||||||
std::string modeStr;
|
std::string modeStr;
|
||||||
@ -679,8 +585,6 @@ Ftp::Response Ftp::DataChannel::Open(Ftp::TransferMode mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Receive data on the data channel until it is closed
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Ftp::DataChannel::Receive(std::vector<char>& data)
|
void Ftp::DataChannel::Receive(std::vector<char>& data)
|
||||||
{
|
{
|
||||||
@ -694,12 +598,10 @@ void Ftp::DataChannel::Receive(std::vector<char>& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close the data socket
|
// Close the data socket
|
||||||
myDataSocket.Close();
|
myDataSocket.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Send data on the data channel
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Ftp::DataChannel::Send(const std::vector<char>& data)
|
void Ftp::DataChannel::Send(const std::vector<char>& data)
|
||||||
{
|
{
|
||||||
@ -708,7 +610,7 @@ void Ftp::DataChannel::Send(const std::vector<char>& data)
|
|||||||
myDataSocket.Send(&data[0], data.size());
|
myDataSocket.Send(&data[0], data.size());
|
||||||
|
|
||||||
// Close the data socket
|
// Close the data socket
|
||||||
myDataSocket.Close();
|
myDataSocket.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -32,16 +32,16 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// Private data
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
// Convert a string to lower case
|
||||||
// Convenience function to convert a string to lower case
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::string ToLower(std::string str)
|
std::string ToLower(std::string str)
|
||||||
{
|
{
|
||||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||||
*i = static_cast<char>(tolower(*i));
|
*i = static_cast<char>(tolower(*i));
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,19 +50,15 @@ namespace
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Http::Request::Request(Method method, const std::string& URI, const std::string& body)
|
|
||||||
{
|
{
|
||||||
SetMethod(method);
|
SetMethod(method);
|
||||||
SetURI(URI);
|
SetUri(uri);
|
||||||
SetHttpVersion(1, 0);
|
SetHttpVersion(1, 0);
|
||||||
SetBody(body);
|
SetBody(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)
|
void Http::Request::SetField(const std::string& field, const std::string& value)
|
||||||
{
|
{
|
||||||
@ -70,9 +66,6 @@ void Http::Request::SetField(const std::string& field, const std::string& value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Set the request method.
|
|
||||||
/// This parameter is Get by default
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Http::Request::SetMethod(Http::Request::Method method)
|
void Http::Request::SetMethod(Http::Request::Method method)
|
||||||
{
|
{
|
||||||
@ -81,12 +74,9 @@ void Http::Request::SetMethod(Http::Request::Method method)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set the target URI of the request.
|
void Http::Request::SetUri(const std::string& uri)
|
||||||
/// This parameter is "/" by default
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void Http::Request::SetURI(const std::string& URI)
|
|
||||||
{
|
{
|
||||||
myURI = URI;
|
myURI = uri;
|
||||||
|
|
||||||
// Make sure it starts with a '/'
|
// Make sure it starts with a '/'
|
||||||
if (myURI.empty() || (myURI[0] != '/'))
|
if (myURI.empty() || (myURI[0] != '/'))
|
||||||
@ -94,9 +84,6 @@ void Http::Request::SetURI(const std::string& URI)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Set the HTTP version of the request.
|
|
||||||
/// This parameter is 1.0 by default
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Http::Request::SetHttpVersion(unsigned int major, unsigned int minor)
|
void Http::Request::SetHttpVersion(unsigned int major, unsigned int minor)
|
||||||
{
|
{
|
||||||
@ -105,10 +92,6 @@ void Http::Request::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
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Http::Request::SetBody(const std::string& body)
|
void Http::Request::SetBody(const std::string& body)
|
||||||
{
|
{
|
||||||
@ -117,9 +100,7 @@ void Http::Request::SetBody(const std::string& body)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the string representation of a request header
|
std::string Http::Request::Prepare() const
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
std::string Http::Request::ToString() const
|
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
|
|
||||||
@ -153,8 +134,6 @@ std::string Http::Request::ToString() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Check if the given field has been defined
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Http::Request::HasField(const std::string& field) const
|
bool Http::Request::HasField(const std::string& field) const
|
||||||
{
|
{
|
||||||
@ -162,8 +141,6 @@ bool Http::Request::HasField(const std::string& field) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Default constructor
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Http::Response::Response() :
|
Http::Response::Response() :
|
||||||
myStatus (ConnectionFailed),
|
myStatus (ConnectionFailed),
|
||||||
@ -174,8 +151,6 @@ myMinorVersion(0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the value of a field
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const std::string& Http::Response::GetField(const std::string& field) const
|
const std::string& Http::Response::GetField(const std::string& field) const
|
||||||
{
|
{
|
||||||
@ -192,8 +167,6 @@ const std::string& Http::Response::GetField(const std::string& field) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the header's status code
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Http::Response::Status Http::Response::GetStatus() const
|
Http::Response::Status Http::Response::GetStatus() const
|
||||||
{
|
{
|
||||||
@ -201,8 +174,6 @@ Http::Response::Status Http::Response::GetStatus() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the major HTTP version number of the response
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int Http::Response::GetMajorHttpVersion() const
|
unsigned int Http::Response::GetMajorHttpVersion() const
|
||||||
{
|
{
|
||||||
@ -210,8 +181,6 @@ unsigned int Http::Response::GetMajorHttpVersion() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the major HTTP version number of the response
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int Http::Response::GetMinorHttpVersion() const
|
unsigned int Http::Response::GetMinorHttpVersion() const
|
||||||
{
|
{
|
||||||
@ -219,12 +188,6 @@ unsigned int Http::Response::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)
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const std::string& Http::Response::GetBody() const
|
const std::string& Http::Response::GetBody() const
|
||||||
{
|
{
|
||||||
@ -233,9 +196,7 @@ const std::string& Http::Response::GetBody() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Construct the header from a response string
|
void Http::Response::Parse(const std::string& data)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void Http::Response::FromString(const std::string& data)
|
|
||||||
{
|
{
|
||||||
std::istringstream in(data);
|
std::istringstream in(data);
|
||||||
|
|
||||||
@ -300,8 +261,6 @@ void Http::Response::FromString(const std::string& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Default constructor
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Http::Http() :
|
Http::Http() :
|
||||||
myHost(),
|
myHost(),
|
||||||
@ -311,8 +270,6 @@ myPort(0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Construct the Http instance with the target host
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Http::Http(const std::string& host, unsigned short port)
|
Http::Http(const std::string& host, unsigned short port)
|
||||||
{
|
{
|
||||||
@ -320,8 +277,6 @@ Http::Http(const std::string& host, unsigned short port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Set the target host
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Http::SetHost(const std::string& host, unsigned short port)
|
void Http::SetHost(const std::string& host, unsigned short port)
|
||||||
{
|
{
|
||||||
@ -354,17 +309,10 @@ void Http::SetHost(const std::string& host, unsigned short port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// 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& request, float timeout)
|
Http::Response Http::SendRequest(const Http::Request& request, float timeout)
|
||||||
{
|
{
|
||||||
// First make sure the request is valid -- add missing mandatory fields
|
// First make sure that the request is valid -- add missing mandatory fields
|
||||||
Request toSend(request);
|
Request toSend(request);
|
||||||
if (!toSend.HasField("From"))
|
if (!toSend.HasField("From"))
|
||||||
{
|
{
|
||||||
@ -397,10 +345,10 @@ Http::Response Http::SendRequest(const Http::Request& request, float timeout)
|
|||||||
Response received;
|
Response received;
|
||||||
|
|
||||||
// Connect the socket to the host
|
// Connect the socket to the host
|
||||||
if (myConnection.Connect(myPort, myHost, timeout) == Socket::Done)
|
if (myConnection.Connect(myHost, myPort, timeout) == Socket::Done)
|
||||||
{
|
{
|
||||||
// Convert the request to string and send it through the connected socket
|
// Convert the request to string and send it through the connected socket
|
||||||
std::string requestStr = toSend.ToString();
|
std::string requestStr = toSend.Prepare();
|
||||||
|
|
||||||
if (!requestStr.empty())
|
if (!requestStr.empty())
|
||||||
{
|
{
|
||||||
@ -417,12 +365,12 @@ Http::Response Http::SendRequest(const Http::Request& request, float timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build the Response object from the received data
|
// Build the Response object from the received data
|
||||||
received.FromString(receivedStr);
|
received.Parse(receivedStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the connection
|
// Close the connection
|
||||||
myConnection.Close();
|
myConnection.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
return received;
|
return received;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/IpAddress.hpp>
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
#include <SFML/Network/Http.hpp>
|
#include <SFML/Network/Http.hpp>
|
||||||
#include <SFML/Network/SocketHelper.hpp>
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
@ -135,37 +135,31 @@ IpAddress IpAddress::GetLocalAddress()
|
|||||||
IpAddress localAddress;
|
IpAddress localAddress;
|
||||||
|
|
||||||
// Create the socket
|
// Create the socket
|
||||||
SocketHelper::SocketType sock = socket(PF_INET, SOCK_DGRAM, 0);
|
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
if (sock == SocketHelper::InvalidSocket())
|
if (sock == priv::SocketImpl::InvalidSocket())
|
||||||
return localAddress;
|
return localAddress;
|
||||||
|
|
||||||
// Build the host address (use a random port)
|
// Connect the socket to localhost on any port
|
||||||
sockaddr_in sockAddr;
|
sockaddr_in address = priv::SocketImpl::CreateAddress(INADDR_LOOPBACK, 0);
|
||||||
memset(sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
|
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||||
sockAddr.sin_addr.s_addr = INADDR_LOOPBACK;
|
|
||||||
sockAddr.sin_family = AF_INET;
|
|
||||||
sockAddr.sin_port = htons(4567);
|
|
||||||
|
|
||||||
// Connect the socket
|
|
||||||
if (connect(sock, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) == -1)
|
|
||||||
{
|
{
|
||||||
SocketHelper::Close(sock);
|
priv::SocketImpl::Close(sock);
|
||||||
return localAddress;
|
return localAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the local address of the socket connection
|
// Get the local address of the socket connection
|
||||||
SocketHelper::LengthType size = sizeof(sockAddr);
|
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||||
if (getsockname(sock, reinterpret_cast<sockaddr*>(&sockAddr), &size) == -1)
|
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
|
||||||
{
|
{
|
||||||
SocketHelper::Close(sock);
|
priv::SocketImpl::Close(sock);
|
||||||
return localAddress;
|
return localAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the socket
|
// Close the socket
|
||||||
SocketHelper::Close(sock);
|
priv::SocketImpl::Close(sock);
|
||||||
|
|
||||||
// Finally build the IP address
|
// Finally build the IP address
|
||||||
localAddress.myAddress = sockAddr.sin_addr.s_addr;
|
localAddress.myAddress = address.sin_addr.s_addr;
|
||||||
|
|
||||||
return localAddress;
|
return localAddress;
|
||||||
}
|
}
|
||||||
@ -181,7 +175,7 @@ IpAddress IpAddress::GetPublicAddress(float timeout)
|
|||||||
// (not very hard: the web page contains only our IP address).
|
// (not very hard: the web page contains only our IP address).
|
||||||
|
|
||||||
Http server("www.sfml-dev.org");
|
Http server("www.sfml-dev.org");
|
||||||
Http::Request request(Http::Request::Get, "/ip-provider.php");
|
Http::Request request("/ip-provider.php", Http::Request::Get);
|
||||||
Http::Response page = server.SendRequest(request, timeout);
|
Http::Response page = server.SendRequest(request, timeout);
|
||||||
if (page.GetStatus() == Http::Response::Ok)
|
if (page.GetStatus() == Http::Response::Ok)
|
||||||
return IpAddress(page.GetBody());
|
return IpAddress(page.GetBody());
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/Packet.hpp>
|
#include <SFML/Network/Packet.hpp>
|
||||||
#include <SFML/Network/SocketHelper.hpp>
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
#include <SFML/System/String.hpp>
|
#include <SFML/System/String.hpp>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -34,8 +34,6 @@
|
|||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Packet::Packet() :
|
Packet::Packet() :
|
||||||
myReadPos(0),
|
myReadPos(0),
|
||||||
myIsValid(true)
|
myIsValid(true)
|
||||||
@ -44,8 +42,6 @@ myIsValid(true)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Virtual destructor
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet::~Packet()
|
Packet::~Packet()
|
||||||
{
|
{
|
||||||
@ -53,8 +49,6 @@ Packet::~Packet()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Append data to the end of the packet
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Packet::Append(const void* data, std::size_t sizeInBytes)
|
void Packet::Append(const void* data, std::size_t sizeInBytes)
|
||||||
{
|
{
|
||||||
@ -67,8 +61,6 @@ void Packet::Append(const void* data, std::size_t sizeInBytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Clear the packet data
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Packet::Clear()
|
void Packet::Clear()
|
||||||
{
|
{
|
||||||
@ -78,10 +70,6 @@ void Packet::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
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const char* Packet::GetData() const
|
const char* Packet::GetData() const
|
||||||
{
|
{
|
||||||
@ -89,8 +77,6 @@ const char* Packet::GetData() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Get the size of the data contained in the packet
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::size_t Packet::GetDataSize() const
|
std::size_t Packet::GetDataSize() const
|
||||||
{
|
{
|
||||||
@ -98,8 +84,6 @@ std::size_t Packet::GetDataSize() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Tell if the reading position has reached the end of the packet
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Packet::EndOfPacket() const
|
bool Packet::EndOfPacket() const
|
||||||
{
|
{
|
||||||
@ -107,8 +91,6 @@ bool Packet::EndOfPacket() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Tell if the packet is valid for reading
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet::operator bool() const
|
Packet::operator bool() const
|
||||||
{
|
{
|
||||||
@ -116,8 +98,6 @@ Packet::operator bool() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Operator >> overloads to extract data from the packet
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(bool& data)
|
Packet& Packet::operator >>(bool& data)
|
||||||
{
|
{
|
||||||
@ -127,6 +107,9 @@ Packet& Packet::operator >>(bool& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(Int8& data)
|
Packet& Packet::operator >>(Int8& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -137,6 +120,9 @@ Packet& Packet::operator >>(Int8& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(Uint8& data)
|
Packet& Packet::operator >>(Uint8& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -147,6 +133,9 @@ Packet& Packet::operator >>(Uint8& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(Int16& data)
|
Packet& Packet::operator >>(Int16& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -157,6 +146,9 @@ Packet& Packet::operator >>(Int16& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(Uint16& data)
|
Packet& Packet::operator >>(Uint16& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -167,6 +159,9 @@ Packet& Packet::operator >>(Uint16& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(Int32& data)
|
Packet& Packet::operator >>(Int32& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -177,6 +172,9 @@ Packet& Packet::operator >>(Int32& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(Uint32& data)
|
Packet& Packet::operator >>(Uint32& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -187,6 +185,9 @@ Packet& Packet::operator >>(Uint32& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(float& data)
|
Packet& Packet::operator >>(float& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -197,6 +198,9 @@ Packet& Packet::operator >>(float& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(double& data)
|
Packet& Packet::operator >>(double& data)
|
||||||
{
|
{
|
||||||
if (CheckSize(sizeof(data)))
|
if (CheckSize(sizeof(data)))
|
||||||
@ -207,6 +211,9 @@ Packet& Packet::operator >>(double& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(char* data)
|
Packet& Packet::operator >>(char* data)
|
||||||
{
|
{
|
||||||
// First extract string length
|
// First extract string length
|
||||||
@ -225,6 +232,9 @@ Packet& Packet::operator >>(char* data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(std::string& data)
|
Packet& Packet::operator >>(std::string& data)
|
||||||
{
|
{
|
||||||
// First extract string length
|
// First extract string length
|
||||||
@ -243,6 +253,9 @@ Packet& Packet::operator >>(std::string& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(wchar_t* data)
|
Packet& Packet::operator >>(wchar_t* data)
|
||||||
{
|
{
|
||||||
// First extract string length
|
// First extract string length
|
||||||
@ -263,6 +276,9 @@ Packet& Packet::operator >>(wchar_t* data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(std::wstring& data)
|
Packet& Packet::operator >>(std::wstring& data)
|
||||||
{
|
{
|
||||||
// First extract string length
|
// First extract string length
|
||||||
@ -283,6 +299,9 @@ Packet& Packet::operator >>(std::wstring& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator >>(String& data)
|
Packet& Packet::operator >>(String& data)
|
||||||
{
|
{
|
||||||
// First extract the string length
|
// First extract the string length
|
||||||
@ -305,58 +324,83 @@ Packet& Packet::operator >>(String& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Operator << overloads to put data into the packet
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(bool data)
|
Packet& Packet::operator <<(bool data)
|
||||||
{
|
{
|
||||||
*this << static_cast<Uint8>(data);
|
*this << static_cast<Uint8>(data);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(Int8 data)
|
Packet& Packet::operator <<(Int8 data)
|
||||||
{
|
{
|
||||||
Append(&data, sizeof(data));
|
Append(&data, sizeof(data));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(Uint8 data)
|
Packet& Packet::operator <<(Uint8 data)
|
||||||
{
|
{
|
||||||
Append(&data, sizeof(data));
|
Append(&data, sizeof(data));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(Int16 data)
|
Packet& Packet::operator <<(Int16 data)
|
||||||
{
|
{
|
||||||
Int16 toWrite = htons(data);
|
Int16 toWrite = htons(data);
|
||||||
Append(&toWrite, sizeof(toWrite));
|
Append(&toWrite, sizeof(toWrite));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(Uint16 data)
|
Packet& Packet::operator <<(Uint16 data)
|
||||||
{
|
{
|
||||||
Uint16 toWrite = htons(data);
|
Uint16 toWrite = htons(data);
|
||||||
Append(&toWrite, sizeof(toWrite));
|
Append(&toWrite, sizeof(toWrite));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(Int32 data)
|
Packet& Packet::operator <<(Int32 data)
|
||||||
{
|
{
|
||||||
Int32 toWrite = htonl(data);
|
Int32 toWrite = htonl(data);
|
||||||
Append(&toWrite, sizeof(toWrite));
|
Append(&toWrite, sizeof(toWrite));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(Uint32 data)
|
Packet& Packet::operator <<(Uint32 data)
|
||||||
{
|
{
|
||||||
Uint32 toWrite = htonl(data);
|
Uint32 toWrite = htonl(data);
|
||||||
Append(&toWrite, sizeof(toWrite));
|
Append(&toWrite, sizeof(toWrite));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(float data)
|
Packet& Packet::operator <<(float data)
|
||||||
{
|
{
|
||||||
Append(&data, sizeof(data));
|
Append(&data, sizeof(data));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(double data)
|
Packet& Packet::operator <<(double data)
|
||||||
{
|
{
|
||||||
Append(&data, sizeof(data));
|
Append(&data, sizeof(data));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(const char* data)
|
Packet& Packet::operator <<(const char* data)
|
||||||
{
|
{
|
||||||
// First insert string length
|
// First insert string length
|
||||||
@ -370,6 +414,9 @@ Packet& Packet::operator <<(const char* data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(const std::string& data)
|
Packet& Packet::operator <<(const std::string& data)
|
||||||
{
|
{
|
||||||
// First insert string length
|
// First insert string length
|
||||||
@ -384,6 +431,9 @@ Packet& Packet::operator <<(const std::string& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(const wchar_t* data)
|
Packet& Packet::operator <<(const wchar_t* data)
|
||||||
{
|
{
|
||||||
// First insert string length
|
// First insert string length
|
||||||
@ -398,6 +448,9 @@ Packet& Packet::operator <<(const wchar_t* data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(const std::wstring& data)
|
Packet& Packet::operator <<(const std::wstring& data)
|
||||||
{
|
{
|
||||||
// First insert string length
|
// First insert string length
|
||||||
@ -413,6 +466,9 @@ Packet& Packet::operator <<(const std::wstring& data)
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
Packet& Packet::operator <<(const String& data)
|
Packet& Packet::operator <<(const String& data)
|
||||||
{
|
{
|
||||||
// First insert the string length
|
// First insert the string length
|
||||||
@ -430,8 +486,6 @@ Packet& Packet::operator <<(const String& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Check if the packet can extract a given size of bytes
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Packet::CheckSize(std::size_t size)
|
bool Packet::CheckSize(std::size_t size)
|
||||||
{
|
{
|
||||||
@ -442,21 +496,17 @@ bool Packet::CheckSize(std::size_t size)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Called before the packet is sent to the network
|
const char* Packet::OnSend(std::size_t& size)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
const char* Packet::OnSend(std::size_t& dataSize)
|
|
||||||
{
|
{
|
||||||
dataSize = GetDataSize();
|
size = GetDataSize();
|
||||||
return GetData();
|
return GetData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Called after the packet has been received from the network
|
void Packet::OnReceive(const char* data, std::size_t size)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void Packet::OnReceive(const char* data, std::size_t dataSize)
|
|
||||||
{
|
{
|
||||||
Append(data, dataSize);
|
Append(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
155
src/SFML/Network/Socket.cpp
Normal file
155
src/SFML/Network/Socket.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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/Socket.hpp>
|
||||||
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Socket(Type type) :
|
||||||
|
myType (type),
|
||||||
|
mySocket (priv::SocketImpl::InvalidSocket()),
|
||||||
|
myIsBlocking(true)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::~Socket()
|
||||||
|
{
|
||||||
|
// Close the socket before it gets destructed
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Socket::SetBlocking(bool blocking)
|
||||||
|
{
|
||||||
|
// Apply if the socket is already created
|
||||||
|
if (mySocket != priv::SocketImpl::InvalidSocket())
|
||||||
|
priv::SocketImpl::SetBlocking(mySocket, blocking);
|
||||||
|
|
||||||
|
myIsBlocking = blocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool Socket::IsBlocking() const
|
||||||
|
{
|
||||||
|
return myIsBlocking;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
SocketHandle Socket::GetHandle() const
|
||||||
|
{
|
||||||
|
return mySocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Socket::Create()
|
||||||
|
{
|
||||||
|
// Don't create the socket if it already exists
|
||||||
|
if (mySocket == priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
SocketHandle handle = socket(PF_INET, myType == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||||
|
Create(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Socket::Create(SocketHandle handle)
|
||||||
|
{
|
||||||
|
// Don't create the socket if it already exists
|
||||||
|
if (mySocket == priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
// Assign the new handle
|
||||||
|
mySocket = handle;
|
||||||
|
|
||||||
|
// Set the current blocking state
|
||||||
|
SetBlocking(myIsBlocking);
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
Err() << "Failed to set socket option \"SO_REUSEADDR\" ; "
|
||||||
|
<< "binding to a same port may fail if too fast" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myType == Tcp)
|
||||||
|
{
|
||||||
|
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
|
||||||
|
if (setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||||
|
{
|
||||||
|
Err() << "Failed to set socket option \"TCP_NODELAY\" ; "
|
||||||
|
<< "all your TCP packets will be buffered" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Enable broadcast by default for UDP sockets
|
||||||
|
if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||||
|
{
|
||||||
|
Err() << "Failed to enable broadcast on UDP socket" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Socket::Close()
|
||||||
|
{
|
||||||
|
// Close the socket
|
||||||
|
if (mySocket != priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
priv::SocketImpl::Close(mySocket);
|
||||||
|
mySocket = priv::SocketImpl::InvalidSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the pending packet data
|
||||||
|
myPendingPacket = PendingPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::PendingPacket::PendingPacket() :
|
||||||
|
Size (0),
|
||||||
|
SizeReceived(0),
|
||||||
|
Data ()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
39
src/SFML/Network/SocketImpl.hpp
Normal file
39
src/SFML/Network/SocketImpl.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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/Config.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(SFML_SYSTEM_WINDOWS)
|
||||||
|
|
||||||
|
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||||
|
|
||||||
|
#endif
|
@ -22,114 +22,116 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
|
||||||
#endif
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SelectorBase.hpp>
|
#include <SFML/Network/SocketSelector.hpp>
|
||||||
|
#include <SFML/Network/Socket.hpp>
|
||||||
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Default constructor
|
struct SocketSelector::SocketSelectorImpl
|
||||||
|
{
|
||||||
|
fd_set AllSockets; ///< Set containing all the sockets handles
|
||||||
|
fd_set SocketsReady; ///< Set containing handles of the sockets that are ready
|
||||||
|
int MaxSocket; ///< Maximum socket handle
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SelectorBase::SelectorBase() :
|
SocketSelector::SocketSelector() :
|
||||||
myMaxSocket(0)
|
myImpl(new SocketSelectorImpl)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Add a socket to watch
|
SocketSelector::SocketSelector(const SocketSelector& copy) :
|
||||||
////////////////////////////////////////////////////////////
|
myImpl(new SocketSelectorImpl(*copy.myImpl))
|
||||||
void SelectorBase::Add(SocketHelper::SocketType socket)
|
|
||||||
{
|
{
|
||||||
FD_SET(socket, &mySet);
|
|
||||||
|
|
||||||
int size = static_cast<int>(socket);
|
|
||||||
if (size > myMaxSocket)
|
|
||||||
myMaxSocket = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove a socket
|
SocketSelector::~SocketSelector()
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SelectorBase::Remove(SocketHelper::SocketType socket)
|
|
||||||
{
|
{
|
||||||
FD_CLR(socket, &mySet);
|
delete myImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Remove all sockets
|
void SocketSelector::Add(Socket& socket)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SelectorBase::Clear()
|
|
||||||
{
|
{
|
||||||
FD_ZERO(&mySet);
|
FD_SET(socket.GetHandle(), &myImpl->AllSockets);
|
||||||
FD_ZERO(&mySetReady);
|
|
||||||
|
|
||||||
myMaxSocket = 0;
|
int size = static_cast<int>(socket.GetHandle());
|
||||||
|
if (size > myImpl->MaxSocket)
|
||||||
|
myImpl->MaxSocket = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Wait and collect sockets which are ready for reading.
|
void SocketSelector::Remove(Socket& socket)
|
||||||
/// 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
|
FD_CLR(socket.GetHandle(), &myImpl->AllSockets);
|
||||||
|
FD_CLR(socket.GetHandle(), &myImpl->SocketsReady);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void SocketSelector::Clear()
|
||||||
|
{
|
||||||
|
FD_ZERO(&myImpl->AllSockets);
|
||||||
|
FD_ZERO(&myImpl->SocketsReady);
|
||||||
|
|
||||||
|
myImpl->MaxSocket = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool SocketSelector::Wait(float timeout)
|
||||||
|
{
|
||||||
|
// Setup the timeout
|
||||||
timeval time;
|
timeval time;
|
||||||
time.tv_sec = static_cast<long>(timeout);
|
time.tv_sec = static_cast<long>(timeout);
|
||||||
time.tv_usec = (static_cast<long>(timeout * 1000) % 1000) * 1000;
|
time.tv_usec = (static_cast<long>(timeout * 1000) % 1000) * 1000;
|
||||||
|
|
||||||
// Prepare the set of sockets to return
|
// Initialize the set that will contain the sockets that are ready
|
||||||
mySetReady = mySet;
|
myImpl->SocketsReady = myImpl->AllSockets;
|
||||||
|
|
||||||
// Wait until one of the sockets is ready for reading, or timeout is reached
|
// 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);
|
int count = select(myImpl->MaxSocket + 1, &myImpl->SocketsReady, NULL, NULL, timeout > 0 ? &time : NULL);
|
||||||
|
|
||||||
return nbSockets >= 0 ? static_cast<unsigned int>(nbSockets) : 0;
|
return count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// After a call to Wait(), get the Index-th socket which is
|
bool SocketSelector::IsReady(Socket& socket) const
|
||||||
/// 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) const
|
|
||||||
{
|
{
|
||||||
// We have to drop the const for FD_ISSET
|
return FD_ISSET(socket.GetHandle(), &myImpl->SocketsReady) != 0;
|
||||||
fd_set* set = const_cast<fd_set*>(&mySetReady);
|
}
|
||||||
|
|
||||||
// The standard FD_xxx interface doesn't define a direct access,
|
|
||||||
// so we must iterate through the whole set to find the socket that we're looking for
|
|
||||||
for (int i = 0; i < myMaxSocket + 1; ++i)
|
|
||||||
{
|
|
||||||
if (FD_ISSET(i, set))
|
|
||||||
{
|
|
||||||
// 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();
|
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
|
||||||
|
{
|
||||||
|
SocketSelector temp(right);
|
||||||
|
|
||||||
|
std::swap(myImpl, temp.myImpl);
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
@ -1,511 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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 <SFML/System/Err.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#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& host, 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(host.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 blocking = myIsBlocking;
|
|
||||||
|
|
||||||
// Switch to non-blocking to enable our connection timeout
|
|
||||||
if (blocking)
|
|
||||||
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 (!blocking)
|
|
||||||
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 (which means that the connection request has returned)
|
|
||||||
if (select(static_cast<int>(mySocket + 1), NULL, &selector, NULL, &time) > 0)
|
|
||||||
{
|
|
||||||
// At this point the connection may have been either accepted or refused.
|
|
||||||
// To know whether it's a success or a failure, we try to retrieve the name of the connected peer
|
|
||||||
SocketHelper::LengthType size = sizeof(sockAddr);
|
|
||||||
if (getpeername(mySocket, reinterpret_cast<sockaddr*>(&sockAddr), &size) != -1)
|
|
||||||
{
|
|
||||||
// Connection accepted
|
|
||||||
status = Socket::Done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Connection failed
|
|
||||||
status = SocketHelper::GetErrorStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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...
|
|
||||||
Err() << "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
|
|
||||||
Err() << "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 sizeInBytes)
|
|
||||||
{
|
|
||||||
// First check that socket is valid
|
|
||||||
if (!IsValid())
|
|
||||||
return Socket::Error;
|
|
||||||
|
|
||||||
// Check parameters
|
|
||||||
if (data && sizeInBytes)
|
|
||||||
{
|
|
||||||
// Loop until every byte has been sent
|
|
||||||
int sent = 0;
|
|
||||||
int sizeToSend = static_cast<int>(sizeInBytes);
|
|
||||||
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...
|
|
||||||
Err() << "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...
|
|
||||||
Err() << "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& packet)
|
|
||||||
{
|
|
||||||
// Get the data to send from the packet
|
|
||||||
std::size_t dataSize = 0;
|
|
||||||
const char* data = packet.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& packet)
|
|
||||||
{
|
|
||||||
// We start by getting the size of the incoming packet
|
|
||||||
Uint32 packetSize = 0;
|
|
||||||
std::size_t received = 0;
|
|
||||||
if (myPendingPacketSize < 0)
|
|
||||||
{
|
|
||||||
// Loop until we've received the entire size of the packet
|
|
||||||
// (even a 4 bytes variable may be received in more than one call)
|
|
||||||
while (myPendingHeaderSize < sizeof(myPendingHeader))
|
|
||||||
{
|
|
||||||
char* data = reinterpret_cast<char*>(&myPendingHeader) + myPendingHeaderSize;
|
|
||||||
Socket::Status status = Receive(data, sizeof(myPendingHeader) - myPendingHeaderSize, received);
|
|
||||||
myPendingHeaderSize += received;
|
|
||||||
|
|
||||||
if (status != Socket::Done)
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
packetSize = ntohl(myPendingHeader);
|
|
||||||
myPendingHeaderSize = 0;
|
|
||||||
}
|
|
||||||
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
|
|
||||||
packet.Clear();
|
|
||||||
if (!myPendingPacket.empty())
|
|
||||||
packet.OnReceive(&myPendingPacket[0], myPendingPacket.size());
|
|
||||||
myPendingPacket.clear();
|
|
||||||
myPendingPacketSize = -1;
|
|
||||||
|
|
||||||
return Socket::Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the socket
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
bool SocketTCP::Close()
|
|
||||||
{
|
|
||||||
if (IsValid())
|
|
||||||
{
|
|
||||||
if (!SocketHelper::Close(mySocket))
|
|
||||||
{
|
|
||||||
Err() << "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
|
|
||||||
myPendingHeaderSize = 0;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Err() << "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)
|
|
||||||
{
|
|
||||||
Err() << "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
|
|
@ -1,433 +0,0 @@
|
|||||||
////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// SFML - Simple and Fast Multimedia Library
|
|
||||||
// Copyright (C) 2007-2009 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 <SFML/System/Err.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
#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 unbind it first
|
|
||||||
Unbind();
|
|
||||||
|
|
||||||
if (port != 0)
|
|
||||||
{
|
|
||||||
// Build an address with the specified port
|
|
||||||
sockaddr_in sockAddr;
|
|
||||||
sockAddr.sin_family = AF_INET;
|
|
||||||
sockAddr.sin_port = htons(port);
|
|
||||||
sockAddr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
memset(sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
|
|
||||||
|
|
||||||
// Bind the socket to the port
|
|
||||||
if (bind(mySocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) == -1)
|
|
||||||
{
|
|
||||||
Err() << "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 sizeInBytes, const IpAddress& address, unsigned short port)
|
|
||||||
{
|
|
||||||
// Make sure the socket is valid
|
|
||||||
if (!IsValid())
|
|
||||||
Create();
|
|
||||||
|
|
||||||
// Check parameters
|
|
||||||
if (data && sizeInBytes)
|
|
||||||
{
|
|
||||||
// Build the target address
|
|
||||||
sockaddr_in sockAddr;
|
|
||||||
sockAddr.sin_family = AF_INET;
|
|
||||||
sockAddr.sin_port = htons(port);
|
|
||||||
sockAddr.sin_addr.s_addr = inet_addr(address.ToString().c_str());
|
|
||||||
memset(sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
|
|
||||||
|
|
||||||
// Loop until every byte has been sent
|
|
||||||
int sent = 0;
|
|
||||||
int sizeToSend = static_cast<int>(sizeInBytes);
|
|
||||||
for (int length = 0; length < sizeToSend; length += sent)
|
|
||||||
{
|
|
||||||
// Send a chunk of data
|
|
||||||
sent = sendto(mySocket, data + length, sizeToSend - length, 0, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr));
|
|
||||||
|
|
||||||
// Check errors
|
|
||||||
if (sent <= 0)
|
|
||||||
return SocketHelper::GetErrorStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Socket::Done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Error...
|
|
||||||
Err() << "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, unsigned short& port)
|
|
||||||
{
|
|
||||||
// First clear the size received
|
|
||||||
sizeReceived = 0;
|
|
||||||
|
|
||||||
// Make sure the socket is bound to a port
|
|
||||||
if (myPort == 0)
|
|
||||||
{
|
|
||||||
Err() << "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 sockAddr;
|
|
||||||
sockAddr.sin_family = AF_INET;
|
|
||||||
sockAddr.sin_port = 0;
|
|
||||||
sockAddr.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
memset(sockAddr.sin_zero, 0, sizeof(sockAddr.sin_zero));
|
|
||||||
SocketHelper::LengthType sockAddrSize = sizeof(sockAddr);
|
|
||||||
|
|
||||||
// Receive a chunk of bytes
|
|
||||||
int received = recvfrom(mySocket, data, static_cast<int>(maxSize), 0, reinterpret_cast<sockaddr*>(&sockAddr), &sockAddrSize);
|
|
||||||
|
|
||||||
// Check the number of bytes received
|
|
||||||
if (received > 0)
|
|
||||||
{
|
|
||||||
address = IpAddress(inet_ntoa(sockAddr.sin_addr));
|
|
||||||
port = ntohs(sockAddr.sin_port);
|
|
||||||
sizeReceived = static_cast<std::size_t>(received);
|
|
||||||
return Socket::Done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
address = IpAddress();
|
|
||||||
port = 0;
|
|
||||||
return received == 0 ? Socket::Disconnected : SocketHelper::GetErrorStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Error...
|
|
||||||
Err() << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
|
||||||
return Socket::Error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Send a packet of data
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status SocketUDP::Send(Packet& packet, const IpAddress& address, unsigned short port)
|
|
||||||
{
|
|
||||||
// Get the data to send from the packet
|
|
||||||
std::size_t dataSize = 0;
|
|
||||||
const char* data = packet.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& packet, IpAddress& address, unsigned short& port)
|
|
||||||
{
|
|
||||||
// We start by getting the size of the incoming packet
|
|
||||||
Uint32 packetSize = 0;
|
|
||||||
std::size_t received = 0;
|
|
||||||
if (myPendingPacketSize < 0)
|
|
||||||
{
|
|
||||||
// Loop until we've received the entire size of the packet
|
|
||||||
// (even a 4 bytes variable may be received in more than one call)
|
|
||||||
while (myPendingHeaderSize < sizeof(myPendingHeader))
|
|
||||||
{
|
|
||||||
char* data = reinterpret_cast<char*>(&myPendingHeader) + myPendingHeaderSize;
|
|
||||||
Socket::Status status = Receive(data, sizeof(myPendingHeader) - myPendingHeaderSize, received, address, port);
|
|
||||||
myPendingHeaderSize += received;
|
|
||||||
|
|
||||||
if (status != Socket::Done)
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
packetSize = ntohl(myPendingHeader);
|
|
||||||
myPendingHeaderSize = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// There is a pending packet : we already know its size
|
|
||||||
packetSize = myPendingPacketSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use another address instance for receiving the packet data ;
|
|
||||||
// chunks of data coming from a different sender will be discarded (and lost...)
|
|
||||||
IpAddress sender;
|
|
||||||
unsigned short senderPort;
|
|
||||||
|
|
||||||
// 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, senderPort);
|
|
||||||
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) && (senderPort == port) && (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
|
|
||||||
packet.Clear();
|
|
||||||
if (!myPendingPacket.empty())
|
|
||||||
packet.OnReceive(&myPendingPacket[0], myPendingPacket.size());
|
|
||||||
myPendingPacket.clear();
|
|
||||||
myPendingPacketSize = -1;
|
|
||||||
|
|
||||||
return Socket::Done;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// Close the socket
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
bool SocketUDP::Close()
|
|
||||||
{
|
|
||||||
if (IsValid())
|
|
||||||
{
|
|
||||||
if (!SocketHelper::Close(mySocket))
|
|
||||||
{
|
|
||||||
Err() << "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
|
|
||||||
myPendingHeaderSize = 0;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Err() << "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)
|
|
||||||
{
|
|
||||||
Err() << "Failed to enable broadcast on UDP socket" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set blocking by default (should always be the case anyway)
|
|
||||||
SetBlocking(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sf
|
|
97
src/SFML/Network/TcpListener.cpp
Normal file
97
src/SFML/Network/TcpListener.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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/TcpListener.hpp>
|
||||||
|
#include <SFML/Network/TcpSocket.hpp>
|
||||||
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
TcpListener::TcpListener() :
|
||||||
|
Socket(Tcp)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpListener::Listen(unsigned short port)
|
||||||
|
{
|
||||||
|
// Create the internal socket if it doesn't exist
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Bind the socket to the specified port
|
||||||
|
sockaddr_in address = priv::SocketImpl::CreateAddress(INADDR_ANY, port);
|
||||||
|
if (bind(GetHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||||
|
{
|
||||||
|
// Not likely to happen, but...
|
||||||
|
Err() << "Failed to bind listener socket to port " << port << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen to the bound port
|
||||||
|
if (listen(GetHandle(), 0) == -1)
|
||||||
|
{
|
||||||
|
// Oops, socket is deaf
|
||||||
|
Err() << "Failed to listen to port " << port << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpListener::Accept(TcpSocket& socket)
|
||||||
|
{
|
||||||
|
// Make sure that we're listening
|
||||||
|
if (GetHandle() == priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
Err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept a new connection
|
||||||
|
sockaddr_in address;
|
||||||
|
priv::SocketImpl::AddrLength length = sizeof(address);
|
||||||
|
SocketHandle remote = accept(GetHandle(), reinterpret_cast<sockaddr*>(&address), &length);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (remote == priv::SocketImpl::InvalidSocket())
|
||||||
|
return priv::SocketImpl::GetErrorStatus();
|
||||||
|
|
||||||
|
// Initialize the new connected socket
|
||||||
|
socket.Close();
|
||||||
|
socket.Create(remote);
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
352
src/SFML/Network/TcpSocket.cpp
Normal file
352
src/SFML/Network/TcpSocket.cpp
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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/TcpSocket.hpp>
|
||||||
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
|
#include <SFML/Network/Packet.hpp>
|
||||||
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
TcpSocket::TcpSocket() :
|
||||||
|
Socket(Tcp)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short TcpSocket::GetLocalPort() const
|
||||||
|
{
|
||||||
|
if (GetHandle() != priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
// Retrieve informations about the local end of the socket
|
||||||
|
sockaddr_in address;
|
||||||
|
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||||
|
if (getsockname(GetHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||||
|
{
|
||||||
|
return ntohs(address.sin_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We failed to retrieve the port
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
IpAddress TcpSocket::GetRemoteAddress() const
|
||||||
|
{
|
||||||
|
if (GetHandle() != priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
// Retrieve informations about the remote end of the socket
|
||||||
|
sockaddr_in address;
|
||||||
|
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||||
|
if (getpeername(GetHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||||
|
{
|
||||||
|
return IpAddress(ntohl(address.sin_addr.s_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We failed to retrieve the address
|
||||||
|
return IpAddress::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short TcpSocket::GetRemotePort() const
|
||||||
|
{
|
||||||
|
if (GetHandle() != priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
// Retrieve informations about the remote end of the socket
|
||||||
|
sockaddr_in address;
|
||||||
|
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||||
|
if (getpeername(GetHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||||
|
{
|
||||||
|
return ntohs(address.sin_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We failed to retrieve the port
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpSocket::Connect(const IpAddress& remoteAddress, unsigned short remotePort, float timeout)
|
||||||
|
{
|
||||||
|
// Create the internal socket if it doesn't exist
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Create the remote address
|
||||||
|
sockaddr_in address = priv::SocketImpl::CreateAddress(remoteAddress.ToInteger(), remotePort);
|
||||||
|
|
||||||
|
if (timeout <= 0)
|
||||||
|
{
|
||||||
|
// ----- We're not using a timeout: just try to connect -----
|
||||||
|
|
||||||
|
// Connect the socket
|
||||||
|
if (connect(GetHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||||
|
return priv::SocketImpl::GetErrorStatus();
|
||||||
|
|
||||||
|
// Connection succeeded
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ----- We're using a timeout: we'll need a few tricks to make it work -----
|
||||||
|
|
||||||
|
// Save the previous blocking state
|
||||||
|
bool blocking = IsBlocking();
|
||||||
|
|
||||||
|
// Switch to non-blocking to enable our connection timeout
|
||||||
|
if (blocking)
|
||||||
|
SetBlocking(false);
|
||||||
|
|
||||||
|
// Try to connect to the remote address
|
||||||
|
if (connect(GetHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
|
||||||
|
{
|
||||||
|
// We got instantly connected! (it may no happen a lot...)
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the error status
|
||||||
|
Status status = priv::SocketImpl::GetErrorStatus();
|
||||||
|
|
||||||
|
// If we were in non-blocking mode, return immediatly
|
||||||
|
if (!blocking)
|
||||||
|
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(GetHandle(), &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 (which means that the connection request has returned)
|
||||||
|
if (select(static_cast<int>(GetHandle() + 1), NULL, &selector, NULL, &time) > 0)
|
||||||
|
{
|
||||||
|
// At this point the connection may have been either accepted or refused.
|
||||||
|
// To know whether it's a success or a failure, we must check the address of the connected peer
|
||||||
|
if (GetRemoteAddress() != sf::IpAddress::None)
|
||||||
|
{
|
||||||
|
// Connection accepted
|
||||||
|
status = Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Connection refused
|
||||||
|
status = priv::SocketImpl::GetErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Failed to connect before timeout is over
|
||||||
|
status = priv::SocketImpl::GetErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch back to blocking mode
|
||||||
|
SetBlocking(true);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void TcpSocket::Disconnect()
|
||||||
|
{
|
||||||
|
// Simply close the socket
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpSocket::Send(const char* data, std::size_t size)
|
||||||
|
{
|
||||||
|
// Check the parameters
|
||||||
|
if (!data || (size == 0))
|
||||||
|
{
|
||||||
|
Err() << "Cannot send data over the network (invalid parameters)" << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(GetHandle(), data + length, sizeToSend - length, 0);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (sent <= 0)
|
||||||
|
return priv::SocketImpl::GetErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpSocket::Receive(char* data, std::size_t size, std::size_t& received)
|
||||||
|
{
|
||||||
|
// First clear the variables to fill
|
||||||
|
received = 0;
|
||||||
|
|
||||||
|
// Check the parameters
|
||||||
|
if (!data || (size == 0))
|
||||||
|
{
|
||||||
|
Err() << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Receive a chunk of bytes
|
||||||
|
int sizeReceived = recv(GetHandle(), data, static_cast<int>(size), 0);
|
||||||
|
|
||||||
|
// Check the number of bytes received
|
||||||
|
if (sizeReceived > 0)
|
||||||
|
{
|
||||||
|
received = static_cast<std::size_t>(sizeReceived);
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
else if (sizeReceived == 0)
|
||||||
|
{
|
||||||
|
return Socket::Disconnected;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return priv::SocketImpl::GetErrorStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpSocket::Send(Packet& packet)
|
||||||
|
{
|
||||||
|
// Get the data to send from the packet
|
||||||
|
std::size_t size = 0;
|
||||||
|
const char* data = packet.OnSend(size);
|
||||||
|
|
||||||
|
// First send the packet size
|
||||||
|
Uint32 packetSize = htonl(static_cast<unsigned long>(size));
|
||||||
|
Status status = Send(reinterpret_cast<const char*>(&packetSize), sizeof(packetSize));
|
||||||
|
|
||||||
|
// Make sure that the size was properly sent
|
||||||
|
if (status != Done)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// Send the packet data
|
||||||
|
if (packetSize > 0)
|
||||||
|
{
|
||||||
|
return Send(data, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status TcpSocket::Receive(Packet& packet)
|
||||||
|
{
|
||||||
|
// First clear the variables to fill
|
||||||
|
packet.Clear();
|
||||||
|
|
||||||
|
// We start by getting the size of the incoming packet
|
||||||
|
Uint32 packetSize = 0;
|
||||||
|
std::size_t received = 0;
|
||||||
|
if (myPendingPacket.SizeReceived < sizeof(myPendingPacket.Size))
|
||||||
|
{
|
||||||
|
// Loop until we've received the entire size of the packet
|
||||||
|
// (even a 4 bytes variable may be received in more than one call)
|
||||||
|
while (myPendingPacket.SizeReceived < sizeof(myPendingPacket.Size))
|
||||||
|
{
|
||||||
|
char* data = reinterpret_cast<char*>(&myPendingPacket.Size) + myPendingPacket.SizeReceived;
|
||||||
|
Status status = Receive(data, sizeof(myPendingPacket.Size) - myPendingPacket.SizeReceived, received);
|
||||||
|
myPendingPacket.SizeReceived += received;
|
||||||
|
|
||||||
|
if (status != Done)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The packet size has been fully received
|
||||||
|
packetSize = ntohl(myPendingPacket.Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The packet size has already been received in a previous call
|
||||||
|
packetSize = ntohl(myPendingPacket.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop until we receive all the packet data
|
||||||
|
char buffer[1024];
|
||||||
|
while (myPendingPacket.Data.size() < packetSize)
|
||||||
|
{
|
||||||
|
// Receive a chunk of data
|
||||||
|
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - myPendingPacket.Data.size()), sizeof(buffer));
|
||||||
|
Status status = Receive(buffer, sizeToGet, received);
|
||||||
|
if (status != Done)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// Append it into the packet
|
||||||
|
if (received > 0)
|
||||||
|
{
|
||||||
|
myPendingPacket.Data.resize(myPendingPacket.Data.size() + received);
|
||||||
|
char* begin = &myPendingPacket.Data[0] + myPendingPacket.Data.size() - received;
|
||||||
|
memcpy(begin, buffer, received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have received all the packet data: we can copy it to the user packet
|
||||||
|
if (!myPendingPacket.Data.empty())
|
||||||
|
packet.OnReceive(&myPendingPacket.Data[0], myPendingPacket.Data.size());
|
||||||
|
|
||||||
|
// Clear the pending packet data
|
||||||
|
myPendingPacket = PendingPacket();
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sf
|
256
src/SFML/Network/UdpSocket.cpp
Normal file
256
src/SFML/Network/UdpSocket.cpp
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// SFML - Simple and Fast Multimedia Library
|
||||||
|
// Copyright (C) 2007-2009 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/UdpSocket.hpp>
|
||||||
|
#include <SFML/Network/IpAddress.hpp>
|
||||||
|
#include <SFML/Network/Packet.hpp>
|
||||||
|
#include <SFML/Network/SocketImpl.hpp>
|
||||||
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
namespace sf
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
UdpSocket::UdpSocket() :
|
||||||
|
Socket(Udp)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
unsigned short UdpSocket::GetLocalPort() const
|
||||||
|
{
|
||||||
|
if (GetHandle() != priv::SocketImpl::InvalidSocket())
|
||||||
|
{
|
||||||
|
// Retrieve informations about the local end of the socket
|
||||||
|
sockaddr_in address;
|
||||||
|
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||||
|
if (getsockname(GetHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
|
||||||
|
{
|
||||||
|
return ntohs(address.sin_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We failed to retrieve the port
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status UdpSocket::Bind(unsigned short port)
|
||||||
|
{
|
||||||
|
// Create the internal socket if it doesn't exist
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Bind the socket
|
||||||
|
sockaddr_in address = priv::SocketImpl::CreateAddress(INADDR_ANY, port);
|
||||||
|
if (bind(GetHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||||
|
{
|
||||||
|
Err() << "Failed to bind socket to port " << port << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void UdpSocket::Unbind()
|
||||||
|
{
|
||||||
|
// Simply close the socket
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status UdpSocket::Send(const char* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||||
|
{
|
||||||
|
// Create the internal socket if it doesn't exist
|
||||||
|
Create();
|
||||||
|
|
||||||
|
// Check the parameters
|
||||||
|
if (!data || (size == 0))
|
||||||
|
{
|
||||||
|
Err() << "Cannot send data over the network (invalid parameters)" << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the target address
|
||||||
|
sockaddr_in address = priv::SocketImpl::CreateAddress(remoteAddress.ToInteger(), remotePort);
|
||||||
|
|
||||||
|
// 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(GetHandle(), data + length, sizeToSend - length, 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (sent <= 0)
|
||||||
|
return priv::SocketImpl::GetErrorStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status UdpSocket::Receive(char* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||||
|
{
|
||||||
|
// First clear the variables to fill
|
||||||
|
received = 0;
|
||||||
|
remoteAddress = IpAddress();
|
||||||
|
remotePort = 0;
|
||||||
|
|
||||||
|
// Check the parameters
|
||||||
|
if (!data || (size == 0))
|
||||||
|
{
|
||||||
|
Err() << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data that will be filled with the other computer's address
|
||||||
|
sockaddr_in address = priv::SocketImpl::CreateAddress(INADDR_ANY, 0);
|
||||||
|
|
||||||
|
// Receive a chunk of bytes
|
||||||
|
priv::SocketImpl::AddrLength addressSize = sizeof(address);
|
||||||
|
int sizeReceived = recvfrom(GetHandle(), data, static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (sizeReceived <= 0)
|
||||||
|
return priv::SocketImpl::GetErrorStatus();
|
||||||
|
|
||||||
|
// Fill the sender informations
|
||||||
|
received = static_cast<std::size_t>(sizeReceived);
|
||||||
|
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||||
|
remotePort = ntohs(address.sin_port);
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status UdpSocket::Send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||||
|
{
|
||||||
|
// Get the data to send from the packet
|
||||||
|
std::size_t size = 0;
|
||||||
|
const char* data = packet.OnSend(size);
|
||||||
|
|
||||||
|
// First send the packet size
|
||||||
|
Uint32 packetSize = htonl(static_cast<unsigned long>(size));
|
||||||
|
Status status = Send(reinterpret_cast<const char*>(&packetSize), sizeof(packetSize), remoteAddress, remotePort);
|
||||||
|
|
||||||
|
// Make sure that the size was properly sent
|
||||||
|
if (status != Done)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// Finally send the packet data
|
||||||
|
if (packetSize > 0)
|
||||||
|
{
|
||||||
|
return Send(data, size, remoteAddress, remotePort);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
Socket::Status UdpSocket::Receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||||
|
{
|
||||||
|
// First clear the variables to fill
|
||||||
|
packet.Clear();
|
||||||
|
remoteAddress = IpAddress();
|
||||||
|
remotePort = 0;
|
||||||
|
|
||||||
|
// We start by getting the size of the incoming packet
|
||||||
|
Uint32 packetSize = 0;
|
||||||
|
std::size_t received = 0;
|
||||||
|
if (myPendingPacket.SizeReceived < sizeof(myPendingPacket.Size))
|
||||||
|
{
|
||||||
|
// Loop until we've received the entire size of the packet
|
||||||
|
// (even a 4 bytes variable may be received in more than one call)
|
||||||
|
while (myPendingPacket.SizeReceived < sizeof(myPendingPacket.Size))
|
||||||
|
{
|
||||||
|
char* data = reinterpret_cast<char*>(&myPendingPacket.Size) + myPendingPacket.SizeReceived;
|
||||||
|
std::size_t size = sizeof(myPendingPacket.Size) - myPendingPacket.SizeReceived;
|
||||||
|
Status status = Receive(data, size, received, remoteAddress, remotePort);
|
||||||
|
myPendingPacket.SizeReceived += received;
|
||||||
|
|
||||||
|
if (status != Done)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The packet size has been fully received
|
||||||
|
packetSize = ntohl(myPendingPacket.Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The packet size has already been received in a previous call
|
||||||
|
packetSize = ntohl(myPendingPacket.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use another address instance for receiving the packet data,
|
||||||
|
// chunks of data coming from a different sender will be discarded (and lost...)
|
||||||
|
IpAddress currentSender;
|
||||||
|
unsigned short currentPort;
|
||||||
|
|
||||||
|
// Loop until we receive all the packet data
|
||||||
|
char buffer[1024];
|
||||||
|
while (myPendingPacket.Data.size() < packetSize)
|
||||||
|
{
|
||||||
|
// Receive a chunk of data
|
||||||
|
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - myPendingPacket.Data.size()), sizeof(buffer));
|
||||||
|
Status status = Receive(buffer, sizeToGet, received, currentSender, currentPort);
|
||||||
|
if (status != Done)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// Append it into the packet
|
||||||
|
if ((currentSender == remoteAddress) && (currentPort == remotePort) && (received > 0))
|
||||||
|
{
|
||||||
|
myPendingPacket.Data.resize(myPendingPacket.Data.size() + received);
|
||||||
|
char* begin = &myPendingPacket.Data[0] + myPendingPacket.Data.size() - received;
|
||||||
|
memcpy(begin, buffer, received);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have received all the packet data: we can copy it to the user packet
|
||||||
|
if (!myPendingPacket.Data.empty())
|
||||||
|
packet.OnReceive(&myPendingPacket.Data[0], myPendingPacket.Data.size());
|
||||||
|
|
||||||
|
// Clear the pending packet data
|
||||||
|
myPendingPacket = PendingPacket();
|
||||||
|
|
||||||
|
return Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace sf
|
@ -25,35 +25,45 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SocketHelper.hpp>
|
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Return the value of the invalid socket
|
sockaddr_in SocketImpl::CreateAddress(unsigned long address, unsigned short port)
|
||||||
|
{
|
||||||
|
sockaddr_in addr;
|
||||||
|
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
|
||||||
|
addr.sin_addr.s_addr = htonl(address);
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SocketHelper::SocketType SocketHelper::InvalidSocket()
|
SocketHandle SocketImpl::InvalidSocket()
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Close / destroy a socket
|
void SocketImpl::Close(SocketHandle sock)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
bool SocketHelper::Close(SocketHelper::SocketType socket)
|
|
||||||
{
|
{
|
||||||
return close(socket) != -1;
|
close(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set a socket as blocking or non-blocking
|
void SocketImpl::SetBlocking(SocketHandle sock, bool block)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SocketHelper::SetBlocking(SocketHelper::SocketType sock, bool block)
|
|
||||||
{
|
{
|
||||||
int status = fcntl(sock, F_GETFL);
|
int status = fcntl(sock, F_GETFL);
|
||||||
if (block)
|
if (block)
|
||||||
@ -64,9 +74,7 @@ void SocketHelper::SetBlocking(SocketHelper::SocketType sock, bool block)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the last socket error status
|
Socket::Status SocketImpl::GetErrorStatus()
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status SocketHelper::GetErrorStatus()
|
|
||||||
{
|
{
|
||||||
// The followings are sometimes equal to EWOULDBLOCK,
|
// The followings are sometimes equal to EWOULDBLOCK,
|
||||||
// so we have to make a special case for them in order
|
// so we have to make a special case for them in order
|
||||||
@ -86,4 +94,6 @@ Socket::Status SocketHelper::GetErrorStatus()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
@ -1,7 +1,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// SFML - Simple and Fast Multimedia Library
|
// SFML - Simple and Fast Multimedia Library
|
||||||
// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
|
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied warranty.
|
// 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.
|
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||||
@ -22,12 +22,13 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETHELPERUNIX_HPP
|
#ifndef SFML_SOCKETIMPL_HPP
|
||||||
#define SFML_SOCKETHELPERUNIX_HPP
|
#define SFML_SOCKETIMPL_HPP
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Socket.hpp>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -39,47 +40,57 @@
|
|||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class defines helper functions to do all the
|
/// \brief Helper class implementing all the non-portable
|
||||||
/// non-portable socket stuff. This class is meant for internal
|
/// socket stuff; this is the Unix version
|
||||||
/// use only
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API SocketHelper
|
class SocketImpl
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Define some socket types
|
// Types
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
typedef int SocketType;
|
typedef socklen_t AddrLength;
|
||||||
typedef socklen_t LengthType;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Return the value of the invalid socket
|
/// \brief Create an internal sockaddr_in address
|
||||||
///
|
///
|
||||||
/// \return Unique value of the invalid socket
|
/// \param address Target address
|
||||||
|
/// \param port Target port
|
||||||
|
///
|
||||||
|
/// \return sockaddr_in ready to be used by socket functions
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static SocketType InvalidSocket();
|
static sockaddr_in CreateAddress(unsigned long address, unsigned short port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Close / destroy a socket
|
/// \brief Return the value of the invalid socket
|
||||||
///
|
///
|
||||||
/// \param Socket : Socket to close
|
/// \return Special value of the invalid socket
|
||||||
///
|
|
||||||
/// \return True on success
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static bool Close(SocketType Socket);
|
static SocketHandle InvalidSocket();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set a socket as blocking or non-blocking
|
/// \brief Close and destroy a socket
|
||||||
///
|
///
|
||||||
/// \param Socket : Socket to modify
|
/// \param sock Handle of the socket to close
|
||||||
/// \param Block : New blocking state of the socket
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static void SetBlocking(SocketType Socket, bool Block);
|
static void Close(SocketHandle sock);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set a socket as blocking or non-blocking
|
||||||
|
///
|
||||||
|
/// \param sock Handle of the socket
|
||||||
|
/// \param block New blocking state of the socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void SetBlocking(SocketHandle sock, bool block);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the last socket error status
|
/// Get the last socket error status
|
||||||
@ -90,7 +101,9 @@ public :
|
|||||||
static Socket::Status GetErrorStatus();
|
static Socket::Status GetErrorStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETHELPERUNIX_HPP
|
#endif // SFML_SOCKETIMPL_HPP
|
@ -25,43 +25,51 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Network/SocketHelper.hpp>
|
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Return the value of the invalid socket
|
sockaddr_in SocketImpl::CreateAddress(unsigned long address, unsigned short port)
|
||||||
|
{
|
||||||
|
sockaddr_in addr;
|
||||||
|
memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
|
||||||
|
addr.sin_addr.s_addr = htonl(address);
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SocketHelper::SocketType SocketHelper::InvalidSocket()
|
SocketHandle SocketImpl::InvalidSocket()
|
||||||
{
|
{
|
||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Close / destroy a socket
|
void SocketImpl::Close(SocketHandle sock)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
bool SocketHelper::Close(SocketHelper::SocketType socket)
|
|
||||||
{
|
{
|
||||||
return closesocket(socket) != -1;
|
closesocket(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set a socket as blocking or non-blocking
|
void SocketImpl::SetBlocking(SocketHandle sock, bool block)
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void SocketHelper::SetBlocking(SocketHelper::SocketType socket, bool block)
|
|
||||||
{
|
{
|
||||||
unsigned long blocking = block ? 0 : 1;
|
unsigned long blocking = block ? 0 : 1;
|
||||||
ioctlsocket(socket, FIONBIO, &blocking);
|
ioctlsocket(sock, FIONBIO, &blocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the last socket error status
|
Socket::Status SocketImpl::GetErrorStatus()
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
Socket::Status SocketHelper::GetErrorStatus()
|
|
||||||
{
|
{
|
||||||
switch (WSAGetLastError())
|
switch (WSAGetLastError())
|
||||||
{
|
{
|
||||||
@ -86,7 +94,7 @@ struct SocketInitializer
|
|||||||
SocketInitializer()
|
SocketInitializer()
|
||||||
{
|
{
|
||||||
WSADATA init;
|
WSADATA init;
|
||||||
WSAStartup(MAKEWORD(2,2), &init);
|
WSAStartup(MAKEWORD(2, 2), &init);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SocketInitializer()
|
~SocketInitializer()
|
||||||
@ -97,4 +105,6 @@ struct SocketInitializer
|
|||||||
|
|
||||||
SocketInitializer globalInitializer;
|
SocketInitializer globalInitializer;
|
||||||
|
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
@ -22,58 +22,69 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SFML_SOCKETHELPERWIN32_HPP
|
#ifndef SFML_SOCKETIMPL_HPP
|
||||||
#define SFML_SOCKETHELPERWIN32_HPP
|
#define SFML_SOCKETIMPL_HPP
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Network/Socket.hpp>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// This class defines helper functions to do all the
|
/// \brief Helper class implementing all the non-portable
|
||||||
/// non-portable socket stuff. This class is meant for internal
|
/// socket stuff; this is the Windows version
|
||||||
/// use only
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_API SocketHelper
|
class SocketImpl
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Define some socket types
|
// Types
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
typedef SOCKET SocketType;
|
typedef int AddrLength;
|
||||||
typedef int LengthType;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Return the value of the invalid socket
|
/// \brief Create an internal sockaddr_in address
|
||||||
///
|
///
|
||||||
/// \return Unique value of the invalid socket
|
/// \param address Target address
|
||||||
|
/// \param port Target port
|
||||||
|
///
|
||||||
|
/// \return sockaddr_in ready to be used by socket functions
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static SocketType InvalidSocket();
|
static sockaddr_in CreateAddress(unsigned long address, unsigned short port);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Close / destroy a socket
|
/// \brief Return the value of the invalid socket
|
||||||
///
|
///
|
||||||
/// \param socket : Socket to close
|
/// \return Special value of the invalid socket
|
||||||
///
|
|
||||||
/// \return True on success
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static bool Close(SocketType socket);
|
static SocketHandle InvalidSocket();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Set a socket as blocking or non-blocking
|
/// \brief Close and destroy a socket
|
||||||
///
|
///
|
||||||
/// \param socket : Socket to modify
|
/// \param sock Handle of the socket to close
|
||||||
/// \param block : New blocking state of the socket
|
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static void SetBlocking(SocketType socket, bool block);
|
static void Close(SocketHandle sock);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set a socket as blocking or non-blocking
|
||||||
|
///
|
||||||
|
/// \param sock Handle of the socket
|
||||||
|
/// \param block New blocking state of the socket
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
static void SetBlocking(SocketHandle sock, bool block);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the last socket error status
|
/// Get the last socket error status
|
||||||
@ -84,7 +95,9 @@ public :
|
|||||||
static Socket::Status GetErrorStatus();
|
static Socket::Status GetErrorStatus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
|
||||||
|
|
||||||
#endif // SFML_SOCKETHELPERWIN32_HPP
|
#endif // SFML_SOCKETIMPL_HPP
|
Loading…
x
Reference in New Issue
Block a user