mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-09-28 05:06:57 -05:00
Update Externals/SFML to 2.1
- all files converted to unix line endings - files from other subsystems and most of system have been removed - include/SFML/System.hpp and include/SFML/Network.hpp modified to not include removed stuff - IpAddress.*pp renamed to IPAddress.*pp to workaround git apply bug with case-only renames
This commit is contained in:
712
Externals/SFML/src/SFML/Network/Ftp.cpp
vendored
712
Externals/SFML/src/SFML/Network/Ftp.cpp
vendored
@@ -1,712 +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/Ftp.hpp>
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Utility class for exchanging stuff with the server
|
||||
// on the data channel
|
||||
////////////////////////////////////////////////////////////
|
||||
class Ftp::DataChannel : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
DataChannel(Ftp& Owner);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
~DataChannel();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Open the data channel using the specified mode and port
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Open(Ftp::TransferMode Mode);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Send data on the data channel
|
||||
////////////////////////////////////////////////////////////
|
||||
void Send(const std::vector<char>& Data);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Receive data on the data channel until it is closed
|
||||
////////////////////////////////////////////////////////////
|
||||
void Receive(std::vector<char>& Data);
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp& myFtp; ///< Reference to the owner Ftp instance
|
||||
SocketTCP myDataSocket; ///< Socket used for data transfers
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response::Response(Status Code, const std::string& Message) :
|
||||
myStatus (Code),
|
||||
myMessage(Message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Convenience function to check if the response status code
|
||||
/// means a success
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Ftp::Response::IsOk() const
|
||||
{
|
||||
return myStatus < 400;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the response status code
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response::Status Ftp::Response::GetStatus() const
|
||||
{
|
||||
return myStatus;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the full message contained in the response
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Ftp::Response::GetMessage() const
|
||||
{
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DirectoryResponse::DirectoryResponse(Ftp::Response Resp) :
|
||||
Ftp::Response(Resp)
|
||||
{
|
||||
if (IsOk())
|
||||
{
|
||||
// Extract the directory from the server response
|
||||
std::string::size_type Begin = Resp.GetMessage().find('"', 0);
|
||||
std::string::size_type End = Resp.GetMessage().find('"', Begin + 1);
|
||||
myDirectory = Resp.GetMessage().substr(Begin + 1, End - Begin - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the directory returned in the response
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Ftp::DirectoryResponse::GetDirectory() const
|
||||
{
|
||||
return myDirectory;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::ListingResponse::ListingResponse(Ftp::Response Resp, const std::vector<char>& Data) :
|
||||
Ftp::Response(Resp)
|
||||
{
|
||||
if (IsOk())
|
||||
{
|
||||
// Fill the array of strings
|
||||
std::string Paths(Data.begin(), Data.end());
|
||||
std::string::size_type LastPos = 0;
|
||||
for (std::string::size_type Pos = Paths.find("\r\n"); Pos != std::string::npos; Pos = Paths.find("\r\n", LastPos))
|
||||
{
|
||||
myFilenames.push_back(Paths.substr(LastPos, Pos - LastPos));
|
||||
LastPos = Pos + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the number of filenames in the listing
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t Ftp::ListingResponse::GetCount() const
|
||||
{
|
||||
return myFilenames.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the Index-th filename in the directory
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::string& Ftp::ListingResponse::GetFilename(std::size_t Index) const
|
||||
{
|
||||
return myFilenames[Index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Destructor -- close the connection with the server
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::~Ftp()
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Connect to the specified FTP server
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::Connect(const IPAddress& Server, unsigned short Port, float Timeout)
|
||||
{
|
||||
// Connect to the server
|
||||
if (myCommandSocket.Connect(Port, Server, Timeout) != Socket::Done)
|
||||
return Response(Response::ConnectionFailed);
|
||||
|
||||
// Get the response to the connection
|
||||
return GetResponse();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Log in using anonymous account
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::Login()
|
||||
{
|
||||
return Login("anonymous", "user@sfml-dev.org");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Log in using a username and a password
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::Login(const std::string& UserName, const std::string& Password)
|
||||
{
|
||||
Response Resp = SendCommand("USER", UserName);
|
||||
if (Resp.IsOk())
|
||||
Resp = SendCommand("PASS", Password);
|
||||
|
||||
return Resp;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Close the connection with FTP server
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::Disconnect()
|
||||
{
|
||||
// Send the exit command
|
||||
Response Resp = SendCommand("QUIT");
|
||||
if (Resp.IsOk())
|
||||
myCommandSocket.Close();
|
||||
|
||||
return Resp;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send a null command just to prevent from being disconnected
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::KeepAlive()
|
||||
{
|
||||
return SendCommand("NOOP");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the current working directory
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DirectoryResponse Ftp::GetWorkingDirectory()
|
||||
{
|
||||
return DirectoryResponse(SendCommand("PWD"));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the contents of the given directory
|
||||
/// (subdirectories and files)
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::ListingResponse Ftp::GetDirectoryListing(const std::string& Directory)
|
||||
{
|
||||
// Open a data channel on default port (20) using ASCII transfer mode
|
||||
std::vector<char> DirData;
|
||||
DataChannel Data(*this);
|
||||
Response Resp = Data.Open(Ascii);
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Tell the server to send us the listing
|
||||
Resp = SendCommand("NLST", Directory);
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Receive the listing
|
||||
Data.Receive(DirData);
|
||||
|
||||
// Get the response from the server
|
||||
Resp = GetResponse();
|
||||
}
|
||||
}
|
||||
|
||||
return ListingResponse(Resp, DirData);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Change the current working directory
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::ChangeDirectory(const std::string& Directory)
|
||||
{
|
||||
return SendCommand("CWD", Directory);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Go to the parent directory of the current one
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::ParentDirectory()
|
||||
{
|
||||
return SendCommand("CDUP");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a new directory
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::MakeDirectory(const std::string& Name)
|
||||
{
|
||||
return SendCommand("MKD", Name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Remove an existing directory
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::DeleteDirectory(const std::string& Name)
|
||||
{
|
||||
return SendCommand("RMD", Name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Rename a file
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::RenameFile(const std::string& File, const std::string& NewName)
|
||||
{
|
||||
Response Resp = SendCommand("RNFR", File);
|
||||
if (Resp.IsOk())
|
||||
Resp = SendCommand("RNTO", NewName);
|
||||
|
||||
return Resp;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Remove an existing file
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::DeleteFile(const std::string& Name)
|
||||
{
|
||||
return SendCommand("DELE", Name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Download a file from the server
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::Download(const std::string& DistantFile, const std::string& DestPath, TransferMode Mode)
|
||||
{
|
||||
// Open a data channel using the given transfer mode
|
||||
DataChannel Data(*this);
|
||||
Response Resp = Data.Open(Mode);
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Tell the server to start the transfer
|
||||
Resp = SendCommand("RETR", DistantFile);
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Receive the file data
|
||||
std::vector<char> FileData;
|
||||
Data.Receive(FileData);
|
||||
|
||||
// Get the response from the server
|
||||
Resp = GetResponse();
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Extract the filename from the file path
|
||||
std::string Filename = DistantFile;
|
||||
std::string::size_type Pos = Filename.find_last_of("/\\");
|
||||
if (Pos != std::string::npos)
|
||||
Filename = Filename.substr(Pos + 1);
|
||||
|
||||
// Make sure the destination path ends with a slash
|
||||
std::string Path = DestPath;
|
||||
if (!Path.empty() && (Path[Path.size() - 1] != '\\') && (Path[Path.size() - 1] != '/'))
|
||||
Path += "/";
|
||||
|
||||
// Create the file and copy the received data into it
|
||||
std::ofstream File((Path + Filename).c_str(), std::ios_base::binary);
|
||||
if (!File)
|
||||
return Response(Response::InvalidFile);
|
||||
if (!FileData.empty())
|
||||
File.write(&FileData[0], static_cast<std::streamsize>(FileData.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Resp;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Upload a file to the server
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::Upload(const std::string& LocalFile, const std::string& DestPath, TransferMode Mode)
|
||||
{
|
||||
// Get the contents of the file to send
|
||||
std::ifstream File(LocalFile.c_str(), std::ios_base::binary);
|
||||
if (!File)
|
||||
return Response(Response::InvalidFile);
|
||||
File.seekg(0, std::ios::end);
|
||||
std::size_t Length = File.tellg();
|
||||
File.seekg(0, std::ios::beg);
|
||||
std::vector<char> FileData(Length);
|
||||
if (Length > 0)
|
||||
File.read(&FileData[0], static_cast<std::streamsize>(Length));
|
||||
|
||||
// Extract the filename from the file path
|
||||
std::string Filename = LocalFile;
|
||||
std::string::size_type Pos = Filename.find_last_of("/\\");
|
||||
if (Pos != std::string::npos)
|
||||
Filename = Filename.substr(Pos + 1);
|
||||
|
||||
// Make sure the destination path ends with a slash
|
||||
std::string Path = DestPath;
|
||||
if (!Path.empty() && (Path[Path.size() - 1] != '\\') && (Path[Path.size() - 1] != '/'))
|
||||
Path += "/";
|
||||
|
||||
// Open a data channel using the given transfer mode
|
||||
DataChannel Data(*this);
|
||||
Response Resp = Data.Open(Mode);
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Tell the server to start the transfer
|
||||
Resp = SendCommand("STOR", Path + Filename);
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Send the file data
|
||||
Data.Send(FileData);
|
||||
|
||||
// Get the response from the server
|
||||
Resp = GetResponse();
|
||||
}
|
||||
}
|
||||
|
||||
return Resp;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send a command to the FTP server
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::SendCommand(const std::string& Command, const std::string& Parameter)
|
||||
{
|
||||
// Build the command string
|
||||
std::string CommandStr;
|
||||
if (Parameter != "")
|
||||
CommandStr = Command + " " + Parameter + "\r\n";
|
||||
else
|
||||
CommandStr = Command + "\r\n";
|
||||
|
||||
// Send it to the server
|
||||
if (myCommandSocket.Send(CommandStr.c_str(), CommandStr.length()) != sf::Socket::Done)
|
||||
return Response(Response::ConnectionClosed);
|
||||
|
||||
// Get the response
|
||||
return GetResponse();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive a response from the server
|
||||
/// (usually after a command has been sent)
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::GetResponse()
|
||||
{
|
||||
// We'll use a variable to keep track of the last valid code.
|
||||
// It is useful in case of multi-lines responses, because the end of such a response
|
||||
// will start by the same code
|
||||
unsigned int LastCode = 0;
|
||||
bool IsInsideMultiline = false;
|
||||
std::string Message;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Receive the response from the server
|
||||
char Buffer[1024];
|
||||
std::size_t Length;
|
||||
if (myCommandSocket.Receive(Buffer, sizeof(Buffer), Length) != sf::Socket::Done)
|
||||
return Response(Response::ConnectionClosed);
|
||||
|
||||
// There can be several lines inside the received buffer, extract them all
|
||||
std::istringstream In(std::string(Buffer, Length), std::ios_base::binary);
|
||||
while (In)
|
||||
{
|
||||
// Try to extract the code
|
||||
unsigned int Code;
|
||||
if (In >> Code)
|
||||
{
|
||||
// Extract the separator
|
||||
char Sep = 0;
|
||||
In.get(Sep);
|
||||
|
||||
// The '-' character means a multiline response
|
||||
if ((Sep == '-') && !IsInsideMultiline)
|
||||
{
|
||||
// Set the multiline flag
|
||||
IsInsideMultiline = true;
|
||||
|
||||
// Keep track of the code
|
||||
if (LastCode == 0)
|
||||
LastCode = Code;
|
||||
|
||||
// Extract the line
|
||||
std::getline(In, Message);
|
||||
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
Message.erase(Message.length() - 1);
|
||||
Message = Sep + Message + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// We must make sure that the code is the same, otherwise it means
|
||||
// we haven't reached the end of the multiline response
|
||||
if ((Sep != '-') && ((Code == LastCode) || (LastCode == 0)))
|
||||
{
|
||||
// Clear the multiline flag
|
||||
IsInsideMultiline = false;
|
||||
|
||||
// Extract the line
|
||||
std::string Line;
|
||||
std::getline(In, Line);
|
||||
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
Line.erase(Line.length() - 1);
|
||||
|
||||
// Append it to the message
|
||||
if (Code == LastCode)
|
||||
{
|
||||
std::ostringstream Out;
|
||||
Out << Code << Sep << Line;
|
||||
Message += Out.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = Sep + Line;
|
||||
}
|
||||
|
||||
// Return the response code and message
|
||||
return Response(static_cast<Response::Status>(Code), Message);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The line we just read was actually not a response,
|
||||
// only a new part of the current multiline response
|
||||
|
||||
// Extract the line
|
||||
std::string Line;
|
||||
std::getline(In, Line);
|
||||
|
||||
if (!Line.empty())
|
||||
{
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
Line.erase(Line.length() - 1);
|
||||
|
||||
// Append it to the current message
|
||||
std::ostringstream Out;
|
||||
Out << Code << Sep << Line << "\n";
|
||||
Message += Out.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (LastCode != 0)
|
||||
{
|
||||
// It seems we are in the middle of a multiline response
|
||||
|
||||
// Clear the error bits of the stream
|
||||
In.clear();
|
||||
|
||||
// Extract the line
|
||||
std::string Line;
|
||||
std::getline(In, Line);
|
||||
|
||||
if (!Line.empty())
|
||||
{
|
||||
// Remove the ending '\r' (all lines are terminated by "\r\n")
|
||||
Line.erase(Line.length() - 1);
|
||||
|
||||
// Append it to the current message
|
||||
Message += Line + "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error : cannot extract the code, and we are not in a multiline response
|
||||
return Response(Response::InvalidResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We never reach there
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DataChannel::DataChannel(Ftp& Owner) :
|
||||
myFtp(Owner)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::DataChannel::~DataChannel()
|
||||
{
|
||||
// Close the data socket
|
||||
myDataSocket.Close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Open the data channel using the specified mode and port
|
||||
////////////////////////////////////////////////////////////
|
||||
Ftp::Response Ftp::DataChannel::Open(Ftp::TransferMode Mode)
|
||||
{
|
||||
// Open a data connection in active mode (we connect to the server)
|
||||
Ftp::Response Resp = myFtp.SendCommand("PASV");
|
||||
if (Resp.IsOk())
|
||||
{
|
||||
// Extract the connection address and port from the response
|
||||
std::string::size_type begin = Resp.GetMessage().find_first_of("0123456789");
|
||||
if (begin != std::string::npos)
|
||||
{
|
||||
sf::Uint8 Data[6] = {0, 0, 0, 0, 0, 0};
|
||||
std::string Str = Resp.GetMessage().substr(begin);
|
||||
std::size_t Index = 0;
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
// Extract the current number
|
||||
while (isdigit(Str[Index]))
|
||||
{
|
||||
Data[i] = Data[i] * 10 + (Str[Index] - '0');
|
||||
Index++;
|
||||
}
|
||||
|
||||
// Skip separator
|
||||
Index++;
|
||||
}
|
||||
|
||||
// Reconstruct connection port and address
|
||||
unsigned short Port = Data[4] * 256 + Data[5];
|
||||
sf::IPAddress Address(static_cast<sf::Uint8>(Data[0]),
|
||||
static_cast<sf::Uint8>(Data[1]),
|
||||
static_cast<sf::Uint8>(Data[2]),
|
||||
static_cast<sf::Uint8>(Data[3]));
|
||||
|
||||
// Connect the data channel to the server
|
||||
if (myDataSocket.Connect(Port, Address) == Socket::Done)
|
||||
{
|
||||
// Translate the transfer mode to the corresponding FTP parameter
|
||||
std::string ModeStr;
|
||||
switch (Mode)
|
||||
{
|
||||
case Ftp::Binary : ModeStr = "I"; break;
|
||||
case Ftp::Ascii : ModeStr = "A"; break;
|
||||
case Ftp::Ebcdic : ModeStr = "E"; break;
|
||||
}
|
||||
|
||||
// Set the transfer mode
|
||||
Resp = myFtp.SendCommand("TYPE", ModeStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to connect to the server
|
||||
Resp = Ftp::Response(Ftp::Response::ConnectionFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Resp;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive data on the data channel until it is closed
|
||||
////////////////////////////////////////////////////////////
|
||||
void Ftp::DataChannel::Receive(std::vector<char>& Data)
|
||||
{
|
||||
// Receive data
|
||||
Data.clear();
|
||||
char Buffer[1024];
|
||||
std::size_t Received;
|
||||
while (myDataSocket.Receive(Buffer, sizeof(Buffer), Received) == sf::Socket::Done)
|
||||
{
|
||||
std::copy(Buffer, Buffer + Received, std::back_inserter(Data));
|
||||
}
|
||||
|
||||
// Close the data socket
|
||||
myDataSocket.Close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send data on the data channel
|
||||
////////////////////////////////////////////////////////////
|
||||
void Ftp::DataChannel::Send(const std::vector<char>& Data)
|
||||
{
|
||||
// Send data
|
||||
if (!Data.empty())
|
||||
myDataSocket.Send(&Data[0], Data.size());
|
||||
|
||||
// Close the data socket
|
||||
myDataSocket.Close();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
318
Externals/SFML/src/SFML/Network/Http.cpp
vendored
318
Externals/SFML/src/SFML/Network/Http.cpp
vendored
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2007-2013 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.
|
||||
@@ -26,7 +26,7 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <ctype.h>
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
@@ -34,16 +34,12 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Convenience function to convert a string to lower case
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string ToLower(const std::string& Str)
|
||||
// Convert a string to lower case
|
||||
std::string toLower(std::string str)
|
||||
{
|
||||
std::string Ret = Str;
|
||||
for (std::string::iterator i = Ret.begin(); i != Ret.end(); ++i)
|
||||
*i = static_cast<char>(tolower(*i));
|
||||
|
||||
return Ret;
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
|
||||
*i = static_cast<char>(std::tolower(*i));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,382 +47,330 @@ namespace
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Request::Request(Method RequestMethod, const std::string& URI, const std::string& Body)
|
||||
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
|
||||
{
|
||||
SetMethod(RequestMethod);
|
||||
SetURI(URI);
|
||||
SetHttpVersion(1, 0);
|
||||
SetBody(Body);
|
||||
setMethod(method);
|
||||
setUri(uri);
|
||||
setHttpVersion(1, 0);
|
||||
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)
|
||||
{
|
||||
myFields[ToLower(Field)] = Value;
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the request method.
|
||||
/// This parameter is Get by default
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::SetMethod(Http::Request::Method RequestMethod)
|
||||
void Http::Request::setMethod(Http::Request::Method method)
|
||||
{
|
||||
myMethod = RequestMethod;
|
||||
m_method = method;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the target URI of the request.
|
||||
/// This parameter is "/" by default
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::SetURI(const std::string& URI)
|
||||
void Http::Request::setUri(const std::string& uri)
|
||||
{
|
||||
myURI = URI;
|
||||
m_uri = uri;
|
||||
|
||||
// Make sure it starts with a '/'
|
||||
if (myURI.empty() || (myURI[0] != '/'))
|
||||
myURI.insert(0, "/");
|
||||
if (m_uri.empty() || (m_uri[0] != '/'))
|
||||
m_uri.insert(0, "/");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the HTTP version of the request.
|
||||
/// This parameter is 1.0 by default
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Request::SetHttpVersion(unsigned int Major, unsigned int Minor)
|
||||
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
|
||||
{
|
||||
myMajorVersion = Major;
|
||||
myMinorVersion = Minor;
|
||||
m_majorVersion = major;
|
||||
m_minorVersion = 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)
|
||||
{
|
||||
myBody = Body;
|
||||
m_body = body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the string representation of a request header
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string Http::Request::ToString() const
|
||||
std::string Http::Request::prepare() const
|
||||
{
|
||||
std::ostringstream Out;
|
||||
std::ostringstream out;
|
||||
|
||||
// Convert the method to its string representation
|
||||
std::string RequestMethod;
|
||||
switch (myMethod)
|
||||
std::string method;
|
||||
switch (m_method)
|
||||
{
|
||||
default :
|
||||
case Get : RequestMethod = "GET"; break;
|
||||
case Post : RequestMethod = "POST"; break;
|
||||
case Head : RequestMethod = "HEAD"; break;
|
||||
case Get : method = "GET"; break;
|
||||
case Post : method = "POST"; break;
|
||||
case Head : method = "HEAD"; break;
|
||||
}
|
||||
|
||||
// Write the first line containing the request type
|
||||
Out << RequestMethod << " " << myURI << " ";
|
||||
Out << "HTTP/" << myMajorVersion << "." << myMinorVersion << "\r\n";
|
||||
out << method << " " << m_uri << " ";
|
||||
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
|
||||
|
||||
// Write fields
|
||||
for (FieldTable::const_iterator i = myFields.begin(); i != myFields.end(); ++i)
|
||||
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
|
||||
{
|
||||
Out << i->first << ": " << i->second << "\r\n";
|
||||
out << i->first << ": " << i->second << "\r\n";
|
||||
}
|
||||
|
||||
// Use an extra \r\n to separate the header from the body
|
||||
Out << "\r\n";
|
||||
out << "\r\n";
|
||||
|
||||
// Add the body
|
||||
Out << myBody;
|
||||
out << m_body;
|
||||
|
||||
return Out.str();
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// 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
|
||||
{
|
||||
return myFields.find(Field) != myFields.end();
|
||||
return m_fields.find(toLower(field)) != m_fields.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Response() :
|
||||
myStatus (ConnectionFailed),
|
||||
myMajorVersion(0),
|
||||
myMinorVersion(0)
|
||||
m_status (ConnectionFailed),
|
||||
m_majorVersion(0),
|
||||
m_minorVersion(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
|
||||
{
|
||||
FieldTable::const_iterator It = myFields.find(ToLower(Field));
|
||||
if (It != myFields.end())
|
||||
FieldTable::const_iterator it = m_fields.find(toLower(field));
|
||||
if (it != m_fields.end())
|
||||
{
|
||||
return It->second;
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const std::string Empty = "";
|
||||
return Empty;
|
||||
static const std::string empty = "";
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the header's status code
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response::Status Http::Response::GetStatus() const
|
||||
Http::Response::Status Http::Response::getStatus() const
|
||||
{
|
||||
return myStatus;
|
||||
return m_status;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the major HTTP version number of the response
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::GetMajorHttpVersion() const
|
||||
unsigned int Http::Response::getMajorHttpVersion() const
|
||||
{
|
||||
return myMajorVersion;
|
||||
return m_majorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the major HTTP version number of the response
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Http::Response::GetMinorHttpVersion() const
|
||||
unsigned int Http::Response::getMinorHttpVersion() const
|
||||
{
|
||||
return myMinorVersion;
|
||||
return m_minorVersion;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// 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
|
||||
{
|
||||
return myBody;
|
||||
return m_body;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the header from a response string
|
||||
////////////////////////////////////////////////////////////
|
||||
void Http::Response::FromString(const std::string& Data)
|
||||
void Http::Response::parse(const std::string& data)
|
||||
{
|
||||
std::istringstream In(Data);
|
||||
std::istringstream in(data);
|
||||
|
||||
// Extract the HTTP version from the first line
|
||||
std::string Version;
|
||||
if (In >> Version)
|
||||
std::string version;
|
||||
if (in >> version)
|
||||
{
|
||||
if ((Version.size() >= 8) && (Version[6] == '.') &&
|
||||
(ToLower(Version.substr(0, 5)) == "http/") &&
|
||||
isdigit(Version[5]) && isdigit(Version[7]))
|
||||
if ((version.size() >= 8) && (version[6] == '.') &&
|
||||
(toLower(version.substr(0, 5)) == "http/") &&
|
||||
isdigit(version[5]) && isdigit(version[7]))
|
||||
{
|
||||
myMajorVersion = Version[5] - '0';
|
||||
myMinorVersion = Version[7] - '0';
|
||||
m_majorVersion = version[5] - '0';
|
||||
m_minorVersion = version[7] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid HTTP version
|
||||
myStatus = InvalidResponse;
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the status code from the first line
|
||||
int StatusCode = 0;
|
||||
if (In >> StatusCode)
|
||||
int status;
|
||||
if (in >> status)
|
||||
{
|
||||
myStatus = static_cast<Status>(StatusCode);
|
||||
m_status = static_cast<Status>(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid status code
|
||||
myStatus = InvalidResponse;
|
||||
m_status = InvalidResponse;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore the end of the first line
|
||||
In.ignore(10000, '\n');
|
||||
in.ignore(10000, '\n');
|
||||
|
||||
// Parse the other lines, which contain fields, one by one
|
||||
std::string Line;
|
||||
while (std::getline(In, Line) && (Line.size() > 2))
|
||||
std::string line;
|
||||
while (std::getline(in, line) && (line.size() > 2))
|
||||
{
|
||||
std::string::size_type Pos = Line.find(": ");
|
||||
if (Pos != std::string::npos)
|
||||
std::string::size_type pos = line.find(": ");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
// Extract the field name and its value
|
||||
std::string Field = Line.substr(0, Pos);
|
||||
std::string Value = Line.substr(Pos + 2);
|
||||
std::string field = line.substr(0, pos);
|
||||
std::string value = line.substr(pos + 2);
|
||||
|
||||
// Remove any trailing \r
|
||||
if (!Value.empty() && (*Value.rbegin() == '\r'))
|
||||
Value.erase(Value.size() - 1);
|
||||
if (!value.empty() && (*value.rbegin() == '\r'))
|
||||
value.erase(value.size() - 1);
|
||||
|
||||
// Add the field
|
||||
myFields[ToLower(Field)] = Value;
|
||||
m_fields[toLower(field)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally extract the body
|
||||
myBody.clear();
|
||||
std::copy(std::istreambuf_iterator<char>(In), std::istreambuf_iterator<char>(), std::back_inserter(myBody));
|
||||
m_body.clear();
|
||||
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Http() :
|
||||
myHost(),
|
||||
myPort(0)
|
||||
m_host(),
|
||||
m_port(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)
|
||||
{
|
||||
SetHost(Host, Port);
|
||||
setHost(host, 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)
|
||||
{
|
||||
// Detect the protocol used
|
||||
std::string Protocol = ToLower(Host.substr(0, 8));
|
||||
if (Protocol.substr(0, 7) == "http://")
|
||||
std::string protocol = toLower(host.substr(0, 8));
|
||||
if (protocol.substr(0, 7) == "http://")
|
||||
{
|
||||
// HTTP protocol
|
||||
myHostName = Host.substr(7);
|
||||
myPort = (Port != 0 ? Port : 80);
|
||||
m_hostName = host.substr(7);
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
else if (Protocol == "https://")
|
||||
else if (protocol == "https://")
|
||||
{
|
||||
// HTTPS protocol
|
||||
myHostName = Host.substr(8);
|
||||
myPort = (Port != 0 ? Port : 443);
|
||||
m_hostName = host.substr(8);
|
||||
m_port = (port != 0 ? port : 443);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undefined protocol - use HTTP
|
||||
myHostName = Host;
|
||||
myPort = (Port != 0 ? Port : 80);
|
||||
m_hostName = host;
|
||||
m_port = (port != 0 ? port : 80);
|
||||
}
|
||||
|
||||
// Remove any trailing '/' from the host name
|
||||
if (!myHostName.empty() && (*myHostName.rbegin() == '/'))
|
||||
myHostName.erase(myHostName.size() - 1);
|
||||
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
|
||||
m_hostName.erase(m_hostName.size() - 1);
|
||||
|
||||
myHost = sf::IPAddress(myHostName);
|
||||
m_host = IpAddress(m_hostName);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send a HTTP request and return the server's response.
|
||||
/// You must be connected to a host before sending requests.
|
||||
/// Any missing mandatory header field will be added with an appropriate value.
|
||||
/// Warning : this function waits for the server's response and may
|
||||
/// not return instantly; use a thread if you don't want to block your
|
||||
/// application.
|
||||
////////////////////////////////////////////////////////////
|
||||
Http::Response Http::SendRequest(const Http::Request& Req, float Timeout)
|
||||
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
|
||||
{
|
||||
// First make sure the request is valid -- add missing mandatory fields
|
||||
Request ToSend(Req);
|
||||
if (!ToSend.HasField("From"))
|
||||
// First make sure that the request is valid -- add missing mandatory fields
|
||||
Request toSend(request);
|
||||
if (!toSend.hasField("From"))
|
||||
{
|
||||
ToSend.SetField("From", "user@sfml-dev.org");
|
||||
toSend.setField("From", "user@sfml-dev.org");
|
||||
}
|
||||
if (!ToSend.HasField("User-Agent"))
|
||||
if (!toSend.hasField("User-Agent"))
|
||||
{
|
||||
ToSend.SetField("User-Agent", "libsfml-network/1.x");
|
||||
toSend.setField("User-Agent", "libsfml-network/2.x");
|
||||
}
|
||||
if (!ToSend.HasField("Host"))
|
||||
if (!toSend.hasField("Host"))
|
||||
{
|
||||
ToSend.SetField("Host", myHostName);
|
||||
toSend.setField("Host", m_hostName);
|
||||
}
|
||||
if (!ToSend.HasField("Content-Length"))
|
||||
if (!toSend.hasField("Content-Length"))
|
||||
{
|
||||
std::ostringstream Out;
|
||||
Out << ToSend.myBody.size();
|
||||
ToSend.SetField("Content-Length", Out.str());
|
||||
std::ostringstream out;
|
||||
out << toSend.m_body.size();
|
||||
toSend.setField("Content-Length", out.str());
|
||||
}
|
||||
if ((ToSend.myMethod == Request::Post) && !ToSend.HasField("Content-Type"))
|
||||
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
|
||||
{
|
||||
ToSend.SetField("Content-Type", "application/x-www-form-urlencoded");
|
||||
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
|
||||
}
|
||||
if ((ToSend.myMajorVersion * 10 + ToSend.myMinorVersion >= 11) && !ToSend.HasField("Connection"))
|
||||
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
|
||||
{
|
||||
ToSend.SetField("Connection", "close");
|
||||
toSend.setField("Connection", "close");
|
||||
}
|
||||
|
||||
// Prepare the response
|
||||
Response Received;
|
||||
Response received;
|
||||
|
||||
// Connect the socket to the host
|
||||
if (myConnection.Connect(myPort, myHost, Timeout) == Socket::Done)
|
||||
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
|
||||
{
|
||||
// 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())
|
||||
{
|
||||
// Send it through the socket
|
||||
if (myConnection.Send(RequestStr.c_str(), RequestStr.size()) == sf::Socket::Done)
|
||||
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
|
||||
{
|
||||
// Wait for the server's response
|
||||
std::string ReceivedStr;
|
||||
std::size_t Size = 0;
|
||||
char Buffer[1024];
|
||||
while (myConnection.Receive(Buffer, sizeof(Buffer), Size) == sf::Socket::Done)
|
||||
std::string receivedStr;
|
||||
std::size_t size = 0;
|
||||
char buffer[1024];
|
||||
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
|
||||
{
|
||||
ReceivedStr.append(Buffer, Buffer + Size);
|
||||
receivedStr.append(buffer, buffer + size);
|
||||
}
|
||||
|
||||
// Build the Response object from the received data
|
||||
Received.FromString(ReceivedStr);
|
||||
received.parse(receivedStr);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
myConnection.Close();
|
||||
m_connection.disconnect();
|
||||
}
|
||||
|
||||
return Received;
|
||||
return received;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
||||
263
Externals/SFML/src/SFML/Network/IPAddress.cpp
vendored
263
Externals/SFML/src/SFML/Network/IPAddress.cpp
vendored
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2007-2013 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.
|
||||
@@ -27,272 +27,229 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/IPAddress.hpp>
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <SFML/Network/SocketHelper.hpp>
|
||||
#include <string.h>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
sf::Uint32 resolve(const std::string& address)
|
||||
{
|
||||
if (address == "255.255.255.255")
|
||||
{
|
||||
// The broadcast address needs to be handled explicitely,
|
||||
// because it is also the value returned by inet_addr on error
|
||||
return INADDR_BROADCAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
sf::Uint32 ip = inet_addr(address.c_str());
|
||||
if (ip != INADDR_NONE)
|
||||
return ip;
|
||||
|
||||
// Not a valid address, try to convert it as a host name
|
||||
addrinfo hints;
|
||||
std::memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
addrinfo* result = NULL;
|
||||
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
|
||||
freeaddrinfo(result);
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a valid address nor a host name
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
const IPAddress IPAddress::LocalHost("127.0.0.1");
|
||||
const IpAddress IpAddress::None;
|
||||
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
|
||||
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress::IPAddress() :
|
||||
myAddress(INADDR_NONE)
|
||||
IpAddress::IpAddress() :
|
||||
m_address(0)
|
||||
{
|
||||
|
||||
// We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address,
|
||||
// because the latter is also the broadcast address (255.255.255.255); it's ok because
|
||||
// SFML doesn't publicly use INADDR_ANY (it is always used implicitely)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the address from a string
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress::IPAddress(const std::string& Address)
|
||||
IpAddress::IpAddress(const std::string& address) :
|
||||
m_address(resolve(address))
|
||||
{
|
||||
// First try to convert it as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
myAddress = inet_addr(Address.c_str());
|
||||
|
||||
// If not successful, try to convert it as a host name
|
||||
if (!IsValid())
|
||||
{
|
||||
hostent* Host = gethostbyname(Address.c_str());
|
||||
if (Host)
|
||||
{
|
||||
// Host found, extract its IP address
|
||||
myAddress = reinterpret_cast<in_addr*>(Host->h_addr)->s_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Host name not found on the network
|
||||
myAddress = INADDR_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the address from a C-style string ;
|
||||
/// Needed for implicit conversions from literal strings to IPAddress to work
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress::IPAddress(const char* Address)
|
||||
IpAddress::IpAddress(const char* address) :
|
||||
m_address(resolve(address))
|
||||
{
|
||||
// First try to convert it as a byte representation ("xxx.xxx.xxx.xxx")
|
||||
myAddress = inet_addr(Address);
|
||||
|
||||
// If not successful, try to convert it as a host name
|
||||
if (!IsValid())
|
||||
{
|
||||
hostent* Host = gethostbyname(Address);
|
||||
if (Host)
|
||||
{
|
||||
// Host found, extract its IP address
|
||||
myAddress = reinterpret_cast<in_addr*>(Host->h_addr)->s_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Host name not found on the network
|
||||
myAddress = INADDR_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the address from 4 bytes
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress::IPAddress(Uint8 Byte0, Uint8 Byte1, Uint8 Byte2, Uint8 Byte3)
|
||||
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
|
||||
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
|
||||
{
|
||||
myAddress = htonl((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the address from a 32-bits integer
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress::IPAddress(Uint32 Address)
|
||||
IpAddress::IpAddress(Uint32 address) :
|
||||
m_address(htonl(address))
|
||||
{
|
||||
myAddress = htonl(Address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Tell if the address is a valid one
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::IsValid() const
|
||||
std::string IpAddress::toString() const
|
||||
{
|
||||
return myAddress != INADDR_NONE;
|
||||
in_addr address;
|
||||
address.s_addr = m_address;
|
||||
|
||||
return inet_ntoa(address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get a string representation of the address
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string IPAddress::ToString() const
|
||||
Uint32 IpAddress::toInteger() const
|
||||
{
|
||||
in_addr InAddr;
|
||||
InAddr.s_addr = myAddress;
|
||||
|
||||
return inet_ntoa(InAddr);
|
||||
return ntohl(m_address);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get an integer representation of the address
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 IPAddress::ToInteger() const
|
||||
{
|
||||
return ntohl(myAddress);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the computer's local IP address (from the LAN point of view)
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress IPAddress::GetLocalAddress()
|
||||
IpAddress IpAddress::getLocalAddress()
|
||||
{
|
||||
// The method here is to connect a UDP socket to anyone (here to localhost),
|
||||
// and get the local socket address with the getsockname function.
|
||||
// UDP connection will not send anything to the network, so this function won't cause any overhead.
|
||||
|
||||
IPAddress LocalAddress;
|
||||
IpAddress localAddress;
|
||||
|
||||
// Create the socket
|
||||
SocketHelper::SocketType Socket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (Socket == SocketHelper::InvalidSocket())
|
||||
return LocalAddress;
|
||||
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == priv::SocketImpl::invalidSocket())
|
||||
return localAddress;
|
||||
|
||||
// Build the host address (use a random port)
|
||||
sockaddr_in SockAddr;
|
||||
memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
|
||||
SockAddr.sin_addr.s_addr = INADDR_LOOPBACK;
|
||||
SockAddr.sin_family = AF_INET;
|
||||
SockAddr.sin_port = htons(4567);
|
||||
|
||||
// Connect the socket
|
||||
if (connect(Socket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
|
||||
// Connect the socket to localhost on any port
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 0);
|
||||
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
|
||||
{
|
||||
SocketHelper::Close(Socket);
|
||||
return LocalAddress;
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
|
||||
// Get the local address of the socket connection
|
||||
SocketHelper::LengthType Size = sizeof(SockAddr);
|
||||
if (getsockname(Socket, reinterpret_cast<sockaddr*>(&SockAddr), &Size) == -1)
|
||||
priv::SocketImpl::AddrLength size = sizeof(address);
|
||||
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
|
||||
{
|
||||
SocketHelper::Close(Socket);
|
||||
return LocalAddress;
|
||||
priv::SocketImpl::close(sock);
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
// Close the socket
|
||||
SocketHelper::Close(Socket);
|
||||
priv::SocketImpl::close(sock);
|
||||
|
||||
// Finally build the IP address
|
||||
LocalAddress.myAddress = SockAddr.sin_addr.s_addr;
|
||||
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
|
||||
|
||||
return LocalAddress;
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the computer's public IP address (from the web point of view)
|
||||
////////////////////////////////////////////////////////////
|
||||
IPAddress IPAddress::GetPublicAddress(float Timeout)
|
||||
IpAddress IpAddress::getPublicAddress(Time timeout)
|
||||
{
|
||||
// The trick here is more complicated, because the only way
|
||||
// to get our public IP address is to get it from a distant computer.
|
||||
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
|
||||
// and parse the result to extract our IP address
|
||||
// (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::Request Request(Http::Request::Get, "/ip-provider.php");
|
||||
Http::Response Page = Server.SendRequest(Request, Timeout);
|
||||
if (Page.GetStatus() == Http::Response::Ok)
|
||||
return IPAddress(Page.GetBody());
|
||||
Http server("www.sfml-dev.org");
|
||||
Http::Request request("/ip-provider.php", Http::Request::Get);
|
||||
Http::Response page = server.sendRequest(request, timeout);
|
||||
if (page.getStatus() == Http::Response::Ok)
|
||||
return IpAddress(page.getBody());
|
||||
|
||||
// Something failed: return an invalid address
|
||||
return IPAddress();
|
||||
return IpAddress();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator ==
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::operator ==(const IPAddress& Other) const
|
||||
bool operator ==(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return myAddress == Other.myAddress;
|
||||
return left.toInteger() == right.toInteger();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator !=
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::operator !=(const IPAddress& Other) const
|
||||
bool operator !=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return myAddress != Other.myAddress;
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator <
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::operator <(const IPAddress& Other) const
|
||||
bool operator <(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return myAddress < Other.myAddress;
|
||||
return left.toInteger() < right.toInteger();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator >
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::operator >(const IPAddress& Other) const
|
||||
bool operator >(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return myAddress > Other.myAddress;
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator <=
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::operator <=(const IPAddress& Other) const
|
||||
bool operator <=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return myAddress <= Other.myAddress;
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator >=
|
||||
////////////////////////////////////////////////////////////
|
||||
bool IPAddress::operator >=(const IPAddress& Other) const
|
||||
bool operator >=(const IpAddress& left, const IpAddress& right)
|
||||
{
|
||||
return myAddress >= Other.myAddress;
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Operator >> overload to extract an address from an input stream
|
||||
////////////////////////////////////////////////////////////
|
||||
std::istream& operator >>(std::istream& Stream, IPAddress& Address)
|
||||
std::istream& operator >>(std::istream& stream, IpAddress& address)
|
||||
{
|
||||
std::string Str;
|
||||
Stream >> Str;
|
||||
Address = IPAddress(Str);
|
||||
std::string str;
|
||||
stream >> str;
|
||||
address = IpAddress(str);
|
||||
|
||||
return Stream;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Operator << overload to print an address to an output stream
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& operator <<(std::ostream& Stream, const IPAddress& Address)
|
||||
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
|
||||
{
|
||||
return Stream << Address.ToString();
|
||||
return stream << address.toString();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
||||
531
Externals/SFML/src/SFML/Network/Packet.cpp
vendored
531
Externals/SFML/src/SFML/Network/Packet.cpp
vendored
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2007-2013 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.
|
||||
@@ -26,25 +26,23 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
#include <SFML/Network/SocketHelper.hpp>
|
||||
#include <string.h>
|
||||
#include <SFML/Network/SocketImpl.hpp>
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet::Packet() :
|
||||
myReadPos(0),
|
||||
myIsValid(true)
|
||||
m_readPos(0),
|
||||
m_isValid(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Virtual destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet::~Packet()
|
||||
{
|
||||
@@ -53,230 +51,250 @@ 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)
|
||||
{
|
||||
if (Data && (SizeInBytes > 0))
|
||||
if (data && (sizeInBytes > 0))
|
||||
{
|
||||
std::size_t Start = myData.size();
|
||||
myData.resize(Start + SizeInBytes);
|
||||
memcpy(&myData[Start], Data, SizeInBytes);
|
||||
std::size_t start = m_data.size();
|
||||
m_data.resize(start + sizeInBytes);
|
||||
std::memcpy(&m_data[start], data, sizeInBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Clear the packet data
|
||||
////////////////////////////////////////////////////////////
|
||||
void Packet::Clear()
|
||||
void Packet::clear()
|
||||
{
|
||||
myData.clear();
|
||||
myReadPos = 0;
|
||||
myIsValid = true;
|
||||
m_data.clear();
|
||||
m_readPos = 0;
|
||||
m_isValid = true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get a pointer to the data contained in the packet
|
||||
/// Warning : the returned pointer may be invalid after you
|
||||
/// append data to the packet
|
||||
////////////////////////////////////////////////////////////
|
||||
const char* Packet::GetData() const
|
||||
const void* Packet::getData() const
|
||||
{
|
||||
return !myData.empty() ? &myData[0] : NULL;
|
||||
return !m_data.empty() ? &m_data[0] : NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the size of the data contained in the packet
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t Packet::GetDataSize() const
|
||||
std::size_t Packet::getDataSize() const
|
||||
{
|
||||
return myData.size();
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Tell if the reading position has reached the end of the packet
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Packet::EndOfPacket() const
|
||||
bool Packet::endOfPacket() const
|
||||
{
|
||||
return myReadPos >= myData.size();
|
||||
return m_readPos >= m_data.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Tell if the packet is valid for reading
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet::operator bool() const
|
||||
Packet::operator BoolType() const
|
||||
{
|
||||
return myIsValid;
|
||||
return m_isValid ? &Packet::checkSize : NULL;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Operator >> overloads to extract data from the packet
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(bool& Data)
|
||||
Packet& Packet::operator >>(bool& data)
|
||||
{
|
||||
Uint8 Value;
|
||||
if (*this >> Value)
|
||||
Data = (Value != 0);
|
||||
Uint8 value;
|
||||
if (*this >> value)
|
||||
data = (value != 0);
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(Int8& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int8& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = *reinterpret_cast<const Int8*>(GetData() + myReadPos);
|
||||
myReadPos += sizeof(Data);
|
||||
data = *reinterpret_cast<const Int8*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(Uint8& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint8& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = *reinterpret_cast<const Uint8*>(GetData() + myReadPos);
|
||||
myReadPos += sizeof(Data);
|
||||
data = *reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(Int16& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int16& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = ntohs(*reinterpret_cast<const Int16*>(GetData() + myReadPos));
|
||||
myReadPos += sizeof(Data);
|
||||
data = ntohs(*reinterpret_cast<const Int16*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(Uint16& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint16& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = ntohs(*reinterpret_cast<const Uint16*>(GetData() + myReadPos));
|
||||
myReadPos += sizeof(Data);
|
||||
data = ntohs(*reinterpret_cast<const Uint16*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(Int32& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Int32& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = ntohl(*reinterpret_cast<const Int32*>(GetData() + myReadPos));
|
||||
myReadPos += sizeof(Data);
|
||||
data = ntohl(*reinterpret_cast<const Int32*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(Uint32& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(Uint32& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = ntohl(*reinterpret_cast<const Uint32*>(GetData() + myReadPos));
|
||||
myReadPos += sizeof(Data);
|
||||
data = ntohl(*reinterpret_cast<const Uint32*>(&m_data[m_readPos]));
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(float& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(float& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = *reinterpret_cast<const float*>(GetData() + myReadPos);
|
||||
myReadPos += sizeof(Data);
|
||||
data = *reinterpret_cast<const float*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(double& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(double& data)
|
||||
{
|
||||
if (CheckSize(sizeof(Data)))
|
||||
if (checkSize(sizeof(data)))
|
||||
{
|
||||
Data = *reinterpret_cast<const double*>(GetData() + myReadPos);
|
||||
myReadPos += sizeof(Data);
|
||||
data = *reinterpret_cast<const double*>(&m_data[m_readPos]);
|
||||
m_readPos += sizeof(data);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(char* Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(char* data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 Length = 0;
|
||||
*this >> Length;
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
if ((Length > 0) && CheckSize(Length))
|
||||
if ((length > 0) && checkSize(length))
|
||||
{
|
||||
// Then extract characters
|
||||
memcpy(Data, GetData() + myReadPos, Length);
|
||||
Data[Length] = '\0';
|
||||
std::memcpy(data, &m_data[m_readPos], length);
|
||||
data[length] = '\0';
|
||||
|
||||
// Update reading position
|
||||
myReadPos += Length;
|
||||
m_readPos += length;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(std::string& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(std::string& data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 Length = 0;
|
||||
*this >> Length;
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
Data.clear();
|
||||
if ((Length > 0) && CheckSize(Length))
|
||||
data.clear();
|
||||
if ((length > 0) && checkSize(length))
|
||||
{
|
||||
// Then extract characters
|
||||
Data.assign(GetData() + myReadPos, Length);
|
||||
data.assign(&m_data[m_readPos], length);
|
||||
|
||||
// Update reading position
|
||||
myReadPos += Length;
|
||||
m_readPos += length;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(wchar_t* Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(wchar_t* data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 Length = 0;
|
||||
*this >> Length;
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
if ((Length > 0) && CheckSize(Length * sizeof(Int32)))
|
||||
if ((length > 0) && checkSize(length * sizeof(Uint32)))
|
||||
{
|
||||
// Then extract characters
|
||||
for (Uint32 i = 0; i < Length; ++i)
|
||||
for (Uint32 i = 0; i < length; ++i)
|
||||
{
|
||||
Uint32 c = 0;
|
||||
*this >> c;
|
||||
Data[i] = static_cast<wchar_t>(c);
|
||||
Uint32 character = 0;
|
||||
*this >> character;
|
||||
data[i] = static_cast<wchar_t>(character);
|
||||
}
|
||||
Data[Length] = L'\0';
|
||||
data[length] = L'\0';
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator >>(std::wstring& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator >>(std::wstring& data)
|
||||
{
|
||||
// First extract string length
|
||||
Uint32 Length = 0;
|
||||
*this >> Length;
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
Data.clear();
|
||||
if ((Length > 0) && CheckSize(Length * sizeof(Int32)))
|
||||
data.clear();
|
||||
if ((length > 0) && checkSize(length * sizeof(Uint32)))
|
||||
{
|
||||
// Then extract characters
|
||||
for (Uint32 i = 0; i < Length; ++i)
|
||||
for (Uint32 i = 0; i < length; ++i)
|
||||
{
|
||||
Uint32 c = 0;
|
||||
*this >> c;
|
||||
Data += static_cast<wchar_t>(c);
|
||||
Uint32 character = 0;
|
||||
*this >> character;
|
||||
data += static_cast<wchar_t>(character);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,109 +303,22 @@ Packet& Packet::operator >>(std::wstring& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Operator << overloads to put data into the packet
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(bool Data)
|
||||
Packet& Packet::operator >>(String& data)
|
||||
{
|
||||
*this << static_cast<Uint8>(Data);
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(Int8 Data)
|
||||
{
|
||||
Append(&Data, sizeof(Data));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(Uint8 Data)
|
||||
{
|
||||
Append(&Data, sizeof(Data));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(Int16 Data)
|
||||
{
|
||||
Int16 ToWrite = htons(Data);
|
||||
Append(&ToWrite, sizeof(ToWrite));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(Uint16 Data)
|
||||
{
|
||||
Uint16 ToWrite = htons(Data);
|
||||
Append(&ToWrite, sizeof(ToWrite));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(Int32 Data)
|
||||
{
|
||||
Int32 ToWrite = htonl(Data);
|
||||
Append(&ToWrite, sizeof(ToWrite));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(Uint32 Data)
|
||||
{
|
||||
Uint32 ToWrite = htonl(Data);
|
||||
Append(&ToWrite, sizeof(ToWrite));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(float Data)
|
||||
{
|
||||
Append(&Data, sizeof(Data));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(double Data)
|
||||
{
|
||||
Append(&Data, sizeof(Data));
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(const char* Data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 Length = 0;
|
||||
for (const char* c = Data; *c != '\0'; ++c)
|
||||
++Length;
|
||||
*this << Length;
|
||||
// First extract the string length
|
||||
Uint32 length = 0;
|
||||
*this >> length;
|
||||
|
||||
// Then insert characters
|
||||
Append(Data, Length * sizeof(char));
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(const std::string& Data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 Length = static_cast<Uint32>(Data.size());
|
||||
*this << Length;
|
||||
|
||||
// Then insert characters
|
||||
if (Length > 0)
|
||||
data.clear();
|
||||
if ((length > 0) && checkSize(length * sizeof(Uint32)))
|
||||
{
|
||||
Append(Data.c_str(), Length * sizeof(std::string::value_type));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(const wchar_t* Data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 Length = 0;
|
||||
for (const wchar_t* c = Data; *c != L'\0'; ++c)
|
||||
++Length;
|
||||
*this << Length;
|
||||
|
||||
// Then insert characters
|
||||
for (const wchar_t* c = Data; *c != L'\0'; ++c)
|
||||
*this << static_cast<Int32>(*c);
|
||||
|
||||
return *this;
|
||||
}
|
||||
Packet& Packet::operator <<(const std::wstring& Data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 Length = static_cast<Uint32>(Data.size());
|
||||
*this << Length;
|
||||
|
||||
// Then insert characters
|
||||
if (Length > 0)
|
||||
{
|
||||
for (std::wstring::const_iterator c = Data.begin(); c != Data.end(); ++c)
|
||||
*this << static_cast<Int32>(*c);
|
||||
// Then extract characters
|
||||
for (Uint32 i = 0; i < length; ++i)
|
||||
{
|
||||
Uint32 character = 0;
|
||||
*this >> character;
|
||||
data += character;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -395,32 +326,182 @@ Packet& Packet::operator <<(const std::wstring& Data)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Check if the packet can extract a given size of bytes
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Packet::CheckSize(std::size_t Size)
|
||||
Packet& Packet::operator <<(bool data)
|
||||
{
|
||||
myIsValid = myIsValid && (myReadPos + Size <= myData.size());
|
||||
|
||||
return myIsValid;
|
||||
*this << static_cast<Uint8>(data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Called before the packet is sent to the network
|
||||
////////////////////////////////////////////////////////////
|
||||
const char* Packet::OnSend(std::size_t& DataSize)
|
||||
Packet& Packet::operator <<(Int8 data)
|
||||
{
|
||||
DataSize = GetDataSize();
|
||||
return GetData();
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Called after the packet has been received from the network
|
||||
////////////////////////////////////////////////////////////
|
||||
void Packet::OnReceive(const char* Data, std::size_t DataSize)
|
||||
Packet& Packet::operator <<(Uint8 data)
|
||||
{
|
||||
Append(Data, DataSize);
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Int16 data)
|
||||
{
|
||||
Int16 toWrite = htons(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Uint16 data)
|
||||
{
|
||||
Uint16 toWrite = htons(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Int32 data)
|
||||
{
|
||||
Int32 toWrite = htonl(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(Uint32 data)
|
||||
{
|
||||
Uint32 toWrite = htonl(data);
|
||||
append(&toWrite, sizeof(toWrite));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(float data)
|
||||
{
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(double data)
|
||||
{
|
||||
append(&data, sizeof(data));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const char* data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = std::strlen(data);
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
append(data, length * sizeof(char));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const std::string& data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = static_cast<Uint32>(data.size());
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
if (length > 0)
|
||||
append(data.c_str(), length * sizeof(std::string::value_type));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const wchar_t* data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = std::wcslen(data);
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
for (const wchar_t* c = data; *c != L'\0'; ++c)
|
||||
*this << static_cast<Uint32>(*c);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const std::wstring& data)
|
||||
{
|
||||
// First insert string length
|
||||
Uint32 length = static_cast<Uint32>(data.size());
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
if (length > 0)
|
||||
{
|
||||
for (std::wstring::const_iterator c = data.begin(); c != data.end(); ++c)
|
||||
*this << static_cast<Uint32>(*c);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Packet& Packet::operator <<(const String& data)
|
||||
{
|
||||
// First insert the string length
|
||||
Uint32 length = static_cast<Uint32>(data.getSize());
|
||||
*this << length;
|
||||
|
||||
// Then insert characters
|
||||
if (length > 0)
|
||||
{
|
||||
for (String::ConstIterator c = data.begin(); c != data.end(); ++c)
|
||||
*this << *c;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Packet::checkSize(std::size_t size)
|
||||
{
|
||||
m_isValid = m_isValid && (m_readPos + size <= m_data.size());
|
||||
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const void* Packet::onSend(std::size_t& size)
|
||||
{
|
||||
size = getDataSize();
|
||||
return getData();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Packet::onReceive(const void* data, std::size_t size)
|
||||
{
|
||||
append(data, size);
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
||||
132
Externals/SFML/src/SFML/Network/SelectorBase.cpp
vendored
132
Externals/SFML/src/SFML/Network/SelectorBase.cpp
vendored
@@ -1,132 +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.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/SelectorBase.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
SelectorBase::SelectorBase() :
|
||||
myMaxSocket(0)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Add a socket to watch
|
||||
////////////////////////////////////////////////////////////
|
||||
void SelectorBase::Add(SocketHelper::SocketType Socket)
|
||||
{
|
||||
FD_SET(Socket, &mySet);
|
||||
|
||||
int Size = static_cast<int>(Socket);
|
||||
if (Size > myMaxSocket)
|
||||
myMaxSocket = Size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Remove a socket
|
||||
////////////////////////////////////////////////////////////
|
||||
void SelectorBase::Remove(SocketHelper::SocketType Socket)
|
||||
{
|
||||
FD_CLR(Socket, &mySet);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Remove all sockets
|
||||
////////////////////////////////////////////////////////////
|
||||
void SelectorBase::Clear()
|
||||
{
|
||||
FD_ZERO(&mySet);
|
||||
FD_ZERO(&mySetReady);
|
||||
|
||||
myMaxSocket = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Wait and collect sockets which are ready for reading.
|
||||
/// This functions will return either when at least one socket
|
||||
/// is ready, or when the given time is out
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int SelectorBase::Wait(float Timeout)
|
||||
{
|
||||
// Setup the timeout structure
|
||||
timeval Time;
|
||||
Time.tv_sec = static_cast<long>(Timeout);
|
||||
Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000;
|
||||
|
||||
// Prepare the set of sockets to return
|
||||
mySetReady = mySet;
|
||||
|
||||
// Wait until one of the sockets is ready for reading, or timeout is reached
|
||||
int NbSockets = select(myMaxSocket + 1, &mySetReady, NULL, NULL, Timeout > 0 ? &Time : NULL);
|
||||
|
||||
return NbSockets >= 0 ? static_cast<unsigned int>(NbSockets) : 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// After a call to Wait(), get the Index-th socket which is
|
||||
/// ready for reading. The total number of sockets ready
|
||||
/// is the integer returned by the previous call to Wait()
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHelper::SocketType SelectorBase::GetSocketReady(unsigned int Index)
|
||||
{
|
||||
// The standard FD_xxx interface doesn't define a direct access,
|
||||
// so we must go through the whole set to find the socket we're looking for
|
||||
for (int i = 0; i < myMaxSocket + 1; ++i)
|
||||
{
|
||||
if (FD_ISSET(i, &mySetReady))
|
||||
{
|
||||
// Current socket is ready, but is it the Index-th one ?
|
||||
if (Index > 0)
|
||||
{
|
||||
Index--;
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<SocketHelper::SocketType>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid index : return an invalid socket
|
||||
return SocketHelper::InvalidSocket();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
144
Externals/SFML/src/SFML/Network/Socket.cpp
vendored
Normal file
144
Externals/SFML/src/SFML/Network/Socket.cpp
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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) :
|
||||
m_type (type),
|
||||
m_socket (priv::SocketImpl::invalidSocket()),
|
||||
m_isBlocking(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::~Socket()
|
||||
{
|
||||
// Close the socket before it gets destructed
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::setBlocking(bool blocking)
|
||||
{
|
||||
// Apply if the socket is already created
|
||||
if (m_socket != priv::SocketImpl::invalidSocket())
|
||||
priv::SocketImpl::setBlocking(m_socket, blocking);
|
||||
|
||||
m_isBlocking = blocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Socket::isBlocking() const
|
||||
{
|
||||
return m_isBlocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketHandle Socket::getHandle() const
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create()
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||
create(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Socket::create(SocketHandle handle)
|
||||
{
|
||||
// Don't create the socket if it already exists
|
||||
if (m_socket == priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
// Assign the new handle
|
||||
m_socket = handle;
|
||||
|
||||
// Set the current blocking state
|
||||
setBlocking(m_isBlocking);
|
||||
|
||||
if (m_type == Tcp)
|
||||
{
|
||||
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, 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;
|
||||
}
|
||||
|
||||
// On Mac OS X, disable the SIGPIPE signal on disconnection
|
||||
#ifdef SFML_SYSTEM_MACOS
|
||||
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
|
||||
{
|
||||
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable broadcast by default for UDP sockets
|
||||
int yes = 1;
|
||||
if (setsockopt(m_socket, 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 (m_socket != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
priv::SocketImpl::close(m_socket);
|
||||
m_socket = priv::SocketImpl::invalidSocket();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
39
Externals/SFML/src/SFML/Network/SocketImpl.hpp
vendored
Normal file
39
Externals/SFML/src/SFML/Network/SocketImpl.hpp
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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
|
||||
141
Externals/SFML/src/SFML/Network/SocketSelector.cpp
vendored
Normal file
141
Externals/SFML/src/SFML/Network/SocketSelector.cpp
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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/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
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector() :
|
||||
m_impl(new SocketSelectorImpl)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::SocketSelector(const SocketSelector& copy) :
|
||||
m_impl(new SocketSelectorImpl(*copy.m_impl))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector::~SocketSelector()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::add(Socket& socket)
|
||||
{
|
||||
SocketHandle handle = socket.getHandle();
|
||||
if (handle != priv::SocketImpl::invalidSocket())
|
||||
{
|
||||
FD_SET(handle, &m_impl->AllSockets);
|
||||
|
||||
int size = static_cast<int>(handle);
|
||||
if (size > m_impl->MaxSocket)
|
||||
m_impl->MaxSocket = size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::remove(Socket& socket)
|
||||
{
|
||||
FD_CLR(socket.getHandle(), &m_impl->AllSockets);
|
||||
FD_CLR(socket.getHandle(), &m_impl->SocketsReady);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketSelector::clear()
|
||||
{
|
||||
FD_ZERO(&m_impl->AllSockets);
|
||||
FD_ZERO(&m_impl->SocketsReady);
|
||||
|
||||
m_impl->MaxSocket = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::wait(Time timeout)
|
||||
{
|
||||
// Setup the timeout
|
||||
timeval time;
|
||||
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// Initialize the set that will contain the sockets that are ready
|
||||
m_impl->SocketsReady = m_impl->AllSockets;
|
||||
|
||||
// Wait until one of the sockets is ready for reading, or timeout is reached
|
||||
int count = select(m_impl->MaxSocket + 1, &m_impl->SocketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketSelector::isReady(Socket& socket) const
|
||||
{
|
||||
return FD_ISSET(socket.getHandle(), &m_impl->SocketsReady) != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
|
||||
{
|
||||
SocketSelector temp(right);
|
||||
|
||||
std::swap(m_impl, temp.m_impl);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
519
Externals/SFML/src/SFML/Network/SocketTCP.cpp
vendored
519
Externals/SFML/src/SFML/Network/SocketTCP.cpp
vendored
@@ -1,519 +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 <algorithm>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketTCP::SocketTCP()
|
||||
{
|
||||
Create(SocketHelper::InvalidSocket());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Change the blocking state of the socket
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketTCP::SetBlocking(bool Blocking)
|
||||
{
|
||||
// Make sure our socket is valid
|
||||
if (!IsValid())
|
||||
Create();
|
||||
|
||||
SocketHelper::SetBlocking(mySocket, Blocking);
|
||||
myIsBlocking = Blocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Connect to another computer on a specified port
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout)
|
||||
{
|
||||
// Make sure our socket is valid
|
||||
if (!IsValid())
|
||||
Create();
|
||||
|
||||
// Build the host address
|
||||
sockaddr_in SockAddr;
|
||||
memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero));
|
||||
SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str());
|
||||
SockAddr.sin_family = AF_INET;
|
||||
SockAddr.sin_port = htons(Port);
|
||||
|
||||
if (Timeout <= 0)
|
||||
{
|
||||
// ----- We're not using a timeout : just try to connect -----
|
||||
|
||||
if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1)
|
||||
{
|
||||
// Failed to connect
|
||||
return SocketHelper::GetErrorStatus();
|
||||
}
|
||||
|
||||
// Connection succeeded
|
||||
return Socket::Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ----- We're using a timeout : we'll need a few tricks to make it work -----
|
||||
|
||||
// Save the previous blocking state
|
||||
bool IsBlocking = myIsBlocking;
|
||||
|
||||
// Switch to non-blocking to enable our connection timeout
|
||||
if (IsBlocking)
|
||||
SetBlocking(false);
|
||||
|
||||
// Try to connect to host
|
||||
if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) >= 0)
|
||||
{
|
||||
// We got instantly connected! (it may no happen a lot...)
|
||||
return Socket::Done;
|
||||
}
|
||||
|
||||
// Get the error status
|
||||
Socket::Status Status = SocketHelper::GetErrorStatus();
|
||||
|
||||
// If we were in non-blocking mode, return immediatly
|
||||
if (!IsBlocking)
|
||||
return Status;
|
||||
|
||||
// Otherwise, wait until something happens to our socket (success, timeout or error)
|
||||
if (Status == Socket::NotReady)
|
||||
{
|
||||
// Setup the selector
|
||||
fd_set Selector;
|
||||
FD_ZERO(&Selector);
|
||||
FD_SET(mySocket, &Selector);
|
||||
|
||||
// Setup the timeout
|
||||
timeval Time;
|
||||
Time.tv_sec = static_cast<long>(Timeout);
|
||||
Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000;
|
||||
|
||||
// Wait for something to write on our socket (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...
|
||||
std::cerr << "Failed to bind socket to port " << Port << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Listen to the bound port
|
||||
if (listen(mySocket, 0) == -1)
|
||||
{
|
||||
// Oops, socket is deaf
|
||||
std::cerr << "Failed to listen to port " << Port << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Wait for a connection (must be listening to a port).
|
||||
/// This function will block if the socket is blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketTCP::Accept(SocketTCP& Connected, IPAddress* Address)
|
||||
{
|
||||
// Address that will be filled with client informations
|
||||
sockaddr_in ClientAddress;
|
||||
SocketHelper::LengthType Length = sizeof(ClientAddress);
|
||||
|
||||
// Accept a new connection
|
||||
Connected = accept(mySocket, reinterpret_cast<sockaddr*>(&ClientAddress), &Length);
|
||||
|
||||
// Check errors
|
||||
if (!Connected.IsValid())
|
||||
{
|
||||
if (Address)
|
||||
*Address = IPAddress();
|
||||
|
||||
return SocketHelper::GetErrorStatus();
|
||||
}
|
||||
|
||||
// Fill address if requested
|
||||
if (Address)
|
||||
*Address = IPAddress(inet_ntoa(ClientAddress.sin_addr));
|
||||
|
||||
return Socket::Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send an array of bytes to the host (must be connected first)
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketTCP::Send(const char* Data, std::size_t Size)
|
||||
{
|
||||
// First check that socket is valid
|
||||
if (!IsValid())
|
||||
return Socket::Error;
|
||||
|
||||
// Check parameters
|
||||
if (Data && Size)
|
||||
{
|
||||
// Loop until every byte has been sent
|
||||
int Sent = 0;
|
||||
int SizeToSend = static_cast<int>(Size);
|
||||
for (int Length = 0; Length < SizeToSend; Length += Sent)
|
||||
{
|
||||
// Send a chunk of data
|
||||
Sent = send(mySocket, Data + Length, SizeToSend - Length, 0);
|
||||
|
||||
// Check if an error occured
|
||||
if (Sent <= 0)
|
||||
return SocketHelper::GetErrorStatus();
|
||||
}
|
||||
|
||||
return Socket::Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error...
|
||||
std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl;
|
||||
return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive an array of bytes from the host (must be connected first).
|
||||
/// This function will block if the socket is blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketTCP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived)
|
||||
{
|
||||
// First clear the size received
|
||||
SizeReceived = 0;
|
||||
|
||||
// Check that socket is valid
|
||||
if (!IsValid())
|
||||
return Socket::Error;
|
||||
|
||||
// Check parameters
|
||||
if (Data && MaxSize)
|
||||
{
|
||||
// Receive a chunk of bytes
|
||||
int Received = recv(mySocket, Data, static_cast<int>(MaxSize), 0);
|
||||
|
||||
// Check the number of bytes received
|
||||
if (Received > 0)
|
||||
{
|
||||
SizeReceived = static_cast<std::size_t>(Received);
|
||||
return Socket::Done;
|
||||
}
|
||||
else if (Received == 0)
|
||||
{
|
||||
return Socket::Disconnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SocketHelper::GetErrorStatus();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error...
|
||||
std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
||||
return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send a packet of data to the host (must be connected first)
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketTCP::Send(Packet& PacketToSend)
|
||||
{
|
||||
// Get the data to send from the packet
|
||||
std::size_t DataSize = 0;
|
||||
const char* Data = PacketToSend.OnSend(DataSize);
|
||||
|
||||
// Send the packet size
|
||||
Uint32 PacketSize = htonl(static_cast<unsigned long>(DataSize));
|
||||
Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize));
|
||||
|
||||
// Send the packet data
|
||||
if (PacketSize > 0)
|
||||
{
|
||||
return Send(Data, DataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Socket::Done;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive a packet from the host (must be connected first).
|
||||
/// This function will block if the socket is blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketTCP::Receive(Packet& PacketToReceive)
|
||||
{
|
||||
// We start by getting the size of the incoming packet
|
||||
Uint32 PacketSize = 0;
|
||||
std::size_t Received = 0;
|
||||
if (myPendingPacketSize < 0)
|
||||
{
|
||||
// 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
|
||||
PacketToReceive.Clear();
|
||||
if (!myPendingPacket.empty())
|
||||
PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
|
||||
myPendingPacket.clear();
|
||||
myPendingPacketSize = -1;
|
||||
|
||||
return Socket::Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Close the socket
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketTCP::Close()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
if (!SocketHelper::Close(mySocket))
|
||||
{
|
||||
std::cerr << "Failed to close socket" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mySocket = SocketHelper::InvalidSocket();
|
||||
}
|
||||
|
||||
myIsBlocking = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Check if the socket is in a valid state ; this function
|
||||
/// can be called any time to check if the socket is OK
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketTCP::IsValid() const
|
||||
{
|
||||
return mySocket != SocketHelper::InvalidSocket();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator ==
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketTCP::operator ==(const SocketTCP& Other) const
|
||||
{
|
||||
return mySocket == Other.mySocket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator !=
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketTCP::operator !=(const SocketTCP& Other) const
|
||||
{
|
||||
return mySocket != Other.mySocket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator <.
|
||||
/// Provided for compatibility with standard containers, as
|
||||
/// comparing two sockets doesn't make much sense...
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketTCP::operator <(const SocketTCP& Other) const
|
||||
{
|
||||
return mySocket < Other.mySocket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the socket from a socket descriptor
|
||||
/// (for internal use only)
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketTCP::SocketTCP(SocketHelper::SocketType Descriptor)
|
||||
{
|
||||
Create(Descriptor);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create the socket
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketTCP::Create(SocketHelper::SocketType Descriptor)
|
||||
{
|
||||
// Use the given socket descriptor, or get a new one
|
||||
mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_STREAM, 0);
|
||||
myIsBlocking = true;
|
||||
|
||||
// Reset the pending packet
|
||||
myPendingHeaderSize = 0;
|
||||
myPendingPacket.clear();
|
||||
myPendingPacketSize = -1;
|
||||
|
||||
// Setup default options
|
||||
if (IsValid())
|
||||
{
|
||||
int Yes = 1;
|
||||
#ifndef SFML_SYSTEM_WINDOWS
|
||||
/* We must disable this in order to detect if ports are being used by other apps, or
|
||||
other instances of dolphin. This is also disabled in SFML 2.0, see
|
||||
http://www.sfml-dev.org/forum/viewtopic.php?t=3388
|
||||
...In fact, SO_REUSEADDR is only unsafe on Windows. See:
|
||||
http://stackoverflow.com/questions/14388706
|
||||
*/
|
||||
// To avoid the "Address already in use" error message when trying to bind to the same port
|
||||
if (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||
{
|
||||
std::cerr << "Failed to set socket option \"SO_REUSEADDR\" ; "
|
||||
<< "binding to a same port may fail if too fast" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
|
||||
if (setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||
{
|
||||
std::cerr << "Failed to set socket option \"TCP_NODELAY\" ; "
|
||||
<< "all your TCP packets will be buffered" << std::endl;
|
||||
}
|
||||
|
||||
// Set blocking by default (should always be the case anyway)
|
||||
SetBlocking(true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
433
Externals/SFML/src/SFML/Network/SocketUDP.cpp
vendored
433
Externals/SFML/src/SFML/Network/SocketUDP.cpp
vendored
@@ -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 <algorithm>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketUDP::SocketUDP()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Change the blocking state of the socket
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketUDP::SetBlocking(bool Blocking)
|
||||
{
|
||||
// Make sure our socket is valid
|
||||
if (!IsValid())
|
||||
Create();
|
||||
|
||||
SocketHelper::SetBlocking(mySocket, Blocking);
|
||||
myIsBlocking = Blocking;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Bind the socket to a specific port
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::Bind(unsigned short Port)
|
||||
{
|
||||
// Check if the socket is already bound to the specified port
|
||||
if (myPort != Port)
|
||||
{
|
||||
// If the socket was previously bound to another port, we need to unbind it first
|
||||
Unbind();
|
||||
|
||||
if (Port != 0)
|
||||
{
|
||||
// Build an address with the specified port
|
||||
sockaddr_in Addr;
|
||||
Addr.sin_family = AF_INET;
|
||||
Addr.sin_port = htons(Port);
|
||||
Addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(Addr.sin_zero, 0, sizeof(Addr.sin_zero));
|
||||
|
||||
// Bind the socket to the port
|
||||
if (bind(mySocket, reinterpret_cast<sockaddr*>(&Addr), sizeof(Addr)) == -1)
|
||||
{
|
||||
std::cerr << "Failed to bind the socket to port " << Port << std::endl;
|
||||
myPort = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the new port
|
||||
myPort = Port;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Unbind the socket to its previous port
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::Unbind()
|
||||
{
|
||||
// To unbind the socket, we just recreate it
|
||||
if (myPort != 0)
|
||||
{
|
||||
Close();
|
||||
Create();
|
||||
myPort = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send an array of bytes
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketUDP::Send(const char* Data, std::size_t Size, const IPAddress& Address, unsigned short Port)
|
||||
{
|
||||
// Make sure the socket is valid
|
||||
if (!IsValid())
|
||||
Create();
|
||||
|
||||
// Check parameters
|
||||
if (Data && Size)
|
||||
{
|
||||
// Build the target address
|
||||
sockaddr_in Target;
|
||||
Target.sin_family = AF_INET;
|
||||
Target.sin_port = htons(Port);
|
||||
Target.sin_addr.s_addr = inet_addr(Address.ToString().c_str());
|
||||
memset(Target.sin_zero, 0, sizeof(Target.sin_zero));
|
||||
|
||||
// Loop until every byte has been sent
|
||||
int Sent = 0;
|
||||
int SizeToSend = static_cast<int>(Size);
|
||||
for (int Length = 0; Length < SizeToSend; Length += Sent)
|
||||
{
|
||||
// Send a chunk of data
|
||||
Sent = sendto(mySocket, Data + Length, SizeToSend - Length, 0, reinterpret_cast<sockaddr*>(&Target), sizeof(Target));
|
||||
|
||||
// Check errors
|
||||
if (Sent <= 0)
|
||||
return SocketHelper::GetErrorStatus();
|
||||
}
|
||||
|
||||
return Socket::Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error...
|
||||
std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl;
|
||||
return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive an array of bytes.
|
||||
/// This function will block if the socket is blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketUDP::Receive(char* Data, std::size_t MaxSize, std::size_t& SizeReceived, IPAddress& Address, unsigned short& Port)
|
||||
{
|
||||
// First clear the size received
|
||||
SizeReceived = 0;
|
||||
|
||||
// Make sure the socket is bound to a port
|
||||
if (myPort == 0)
|
||||
{
|
||||
std::cerr << "Failed to receive data ; the UDP socket first needs to be bound to a port" << std::endl;
|
||||
return Socket::Error;
|
||||
}
|
||||
|
||||
// Make sure the socket is valid
|
||||
if (!IsValid())
|
||||
Create();
|
||||
|
||||
// Check parameters
|
||||
if (Data && MaxSize)
|
||||
{
|
||||
// Data that will be filled with the other computer's address
|
||||
sockaddr_in Sender;
|
||||
Sender.sin_family = AF_INET;
|
||||
Sender.sin_port = 0;
|
||||
Sender.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(Sender.sin_zero, 0, sizeof(Sender.sin_zero));
|
||||
SocketHelper::LengthType SenderSize = sizeof(Sender);
|
||||
|
||||
// Receive a chunk of bytes
|
||||
int Received = recvfrom(mySocket, Data, static_cast<int>(MaxSize), 0, reinterpret_cast<sockaddr*>(&Sender), &SenderSize);
|
||||
|
||||
// Check the number of bytes received
|
||||
if (Received > 0)
|
||||
{
|
||||
Address = IPAddress(inet_ntoa(Sender.sin_addr));
|
||||
Port = ntohs(Sender.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...
|
||||
std::cerr << "Cannot receive data from the network (invalid parameters)" << std::endl;
|
||||
return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Send a packet of data
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketUDP::Send(Packet& PacketToSend, const IPAddress& Address, unsigned short Port)
|
||||
{
|
||||
// Get the data to send from the packet
|
||||
std::size_t DataSize = 0;
|
||||
const char* Data = PacketToSend.OnSend(DataSize);
|
||||
|
||||
// Send the packet size
|
||||
Uint32 PacketSize = htonl(static_cast<unsigned long>(DataSize));
|
||||
Send(reinterpret_cast<const char*>(&PacketSize), sizeof(PacketSize), Address, Port);
|
||||
|
||||
// Send the packet data
|
||||
if (PacketSize > 0)
|
||||
{
|
||||
return Send(Data, DataSize, Address, Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Socket::Done;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Receive a packet.
|
||||
/// This function will block if the socket is blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketUDP::Receive(Packet& PacketToReceive, IPAddress& Address, 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
|
||||
PacketToReceive.Clear();
|
||||
if (!myPendingPacket.empty())
|
||||
PacketToReceive.OnReceive(&myPendingPacket[0], myPendingPacket.size());
|
||||
myPendingPacket.clear();
|
||||
myPendingPacketSize = -1;
|
||||
|
||||
return Socket::Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Close the socket
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::Close()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
if (!SocketHelper::Close(mySocket))
|
||||
{
|
||||
std::cerr << "Failed to close socket" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
mySocket = SocketHelper::InvalidSocket();
|
||||
}
|
||||
|
||||
myPort = 0;
|
||||
myIsBlocking = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Check if the socket is in a valid state ; this function
|
||||
/// can be called any time to check if the socket is OK
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::IsValid() const
|
||||
{
|
||||
return mySocket != SocketHelper::InvalidSocket();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the port the socket is currently bound to
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short SocketUDP::GetPort() const
|
||||
{
|
||||
return myPort;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator ==
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::operator ==(const SocketUDP& Other) const
|
||||
{
|
||||
return mySocket == Other.mySocket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator !=
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::operator !=(const SocketUDP& Other) const
|
||||
{
|
||||
return mySocket != Other.mySocket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Comparison operator <.
|
||||
/// Provided for compatibility with standard containers, as
|
||||
/// comparing two sockets doesn't make much sense...
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketUDP::operator <(const SocketUDP& Other) const
|
||||
{
|
||||
return mySocket < Other.mySocket;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the socket from a socket descriptor
|
||||
/// (for internal use only)
|
||||
////////////////////////////////////////////////////////////
|
||||
SocketUDP::SocketUDP(SocketHelper::SocketType Descriptor)
|
||||
{
|
||||
Create(Descriptor);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create the socket
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketUDP::Create(SocketHelper::SocketType Descriptor)
|
||||
{
|
||||
// Use the given socket descriptor, or get a new one
|
||||
mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_DGRAM, 0);
|
||||
myIsBlocking = true;
|
||||
|
||||
// Clear the last port used
|
||||
myPort = 0;
|
||||
|
||||
// Reset the pending packet
|
||||
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)
|
||||
{
|
||||
std::cerr << "Failed to set socket option \"reuse address\" ; "
|
||||
<< "binding to a same port may fail if too fast" << std::endl;
|
||||
}
|
||||
|
||||
// Enable broadcast by default
|
||||
if (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&Yes), sizeof(Yes)) == -1)
|
||||
{
|
||||
std::cerr << "Failed to enable broadcast on UDP socket" << std::endl;
|
||||
}
|
||||
|
||||
// Set blocking by default (should always be the case anyway)
|
||||
SetBlocking(true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
124
Externals/SFML/src/SFML/Network/TcpListener.cpp
vendored
Normal file
124
Externals/SFML/src/SFML/Network/TcpListener.cpp
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned short TcpListener::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 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;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void TcpListener::close()
|
||||
{
|
||||
// Simply close the socket
|
||||
Socket::close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
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
|
||||
381
Externals/SFML/src/SFML/Network/TcpSocket.cpp
vendored
Normal file
381
Externals/SFML/src/SFML/Network/TcpSocket.cpp
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// Define the low-level send/receive flags, which depend on the OS
|
||||
#ifdef SFML_SYSTEM_LINUX
|
||||
const int flags = MSG_NOSIGNAL;
|
||||
#else
|
||||
const int flags = 0;
|
||||
#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, Time 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 <= Time::Zero)
|
||||
{
|
||||
// ----- 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.asMicroseconds() / 1000000);
|
||||
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
|
||||
|
||||
// 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()
|
||||
{
|
||||
// Close the socket
|
||||
close();
|
||||
|
||||
// Reset the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::send(const void* data, std::size_t size)
|
||||
{
|
||||
// Check the parameters
|
||||
if (!data || (size == 0))
|
||||
{
|
||||
err() << "Cannot send data over the network (no data to send)" << 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(), static_cast<const char*>(data) + length, sizeToSend - length, flags);
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
}
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
|
||||
{
|
||||
// First clear the variables to fill
|
||||
received = 0;
|
||||
|
||||
// Check the destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Receive a chunk of bytes
|
||||
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
|
||||
|
||||
// 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)
|
||||
{
|
||||
// TCP is a stream protocol, it doesn't preserve messages boundaries.
|
||||
// This means that we have to send the packet size first, so that the
|
||||
// receiver knows the actual end of the packet in the data stream.
|
||||
|
||||
// We allocate an extra memory block so that the size can be sent
|
||||
// together with the data in a single call. This may seem inefficient,
|
||||
// but it is actually required to avoid partial send, which could cause
|
||||
// data corruption on the receiving end.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// First convert the packet size to network byte order
|
||||
Uint32 packetSize = htonl(static_cast<Uint32>(size));
|
||||
|
||||
// Allocate memory for the data block to send
|
||||
std::vector<char> blockToSend(sizeof(packetSize) + size);
|
||||
|
||||
// Copy the packet size and data into the block to send
|
||||
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
|
||||
if (size > 0)
|
||||
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
|
||||
|
||||
// Send the data block
|
||||
return send(&blockToSend[0], blockToSend.size());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
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 (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
// Loop until we've received the entire size of the packet
|
||||
// (even a 4 byte variable may be received in more than one call)
|
||||
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
|
||||
{
|
||||
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
|
||||
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
|
||||
m_pendingPacket.SizeReceived += received;
|
||||
|
||||
if (status != Done)
|
||||
return status;
|
||||
}
|
||||
|
||||
// The packet size has been fully received
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The packet size has already been received in a previous call
|
||||
packetSize = ntohl(m_pendingPacket.Size);
|
||||
}
|
||||
|
||||
// Loop until we receive all the packet data
|
||||
char buffer[1024];
|
||||
while (m_pendingPacket.Data.size() < packetSize)
|
||||
{
|
||||
// Receive a chunk of data
|
||||
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
|
||||
Status status = receive(buffer, sizeToGet, received);
|
||||
if (status != Done)
|
||||
return status;
|
||||
|
||||
// Append it into the packet
|
||||
if (received > 0)
|
||||
{
|
||||
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
|
||||
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
|
||||
std::memcpy(begin, buffer, received);
|
||||
}
|
||||
}
|
||||
|
||||
// We have received all the packet data: we can copy it to the user packet
|
||||
if (!m_pendingPacket.Data.empty())
|
||||
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
|
||||
|
||||
// Clear the pending packet data
|
||||
m_pendingPacket = PendingPacket();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
TcpSocket::PendingPacket::PendingPacket() :
|
||||
Size (0),
|
||||
SizeReceived(0),
|
||||
Data ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
193
Externals/SFML/src/SFML/Network/UdpSocket.cpp
vendored
Normal file
193
Externals/SFML/src/SFML/Network/UdpSocket.cpp
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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),
|
||||
m_buffer(MaxDatagramSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
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 void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
|
||||
{
|
||||
// Create the internal socket if it doesn't exist
|
||||
create();
|
||||
|
||||
// Make sure that all the data will fit in one datagram
|
||||
if (size > MaxDatagramSize)
|
||||
{
|
||||
err() << "Cannot send data over the network "
|
||||
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Build the target address
|
||||
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
|
||||
|
||||
// Send the data (unlike TCP, all the data is always sent in one call)
|
||||
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
|
||||
|
||||
// Check for errors
|
||||
if (sent < 0)
|
||||
return priv::SocketImpl::getErrorStatus();
|
||||
|
||||
return Done;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(void* 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 destination buffer
|
||||
if (!data)
|
||||
{
|
||||
err() << "Cannot receive data from the network (the destination buffer is invalid)" << 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(), static_cast<char*>(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)
|
||||
{
|
||||
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
|
||||
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
|
||||
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
|
||||
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
|
||||
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
|
||||
// This also removes the overhead associated to packets -- there's no size to send in addition
|
||||
// to the packet's data.
|
||||
|
||||
// Get the data to send from the packet
|
||||
std::size_t size = 0;
|
||||
const void* data = packet.onSend(size);
|
||||
|
||||
// Send it
|
||||
return send(data, size, remoteAddress, remotePort);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
|
||||
{
|
||||
// See the detailed comment in send(Packet) above.
|
||||
|
||||
// Receive the datagram
|
||||
std::size_t received = 0;
|
||||
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
|
||||
|
||||
// If we received valid data, we can copy it to the user packet
|
||||
packet.clear();
|
||||
if ((status == Done) && (received > 0))
|
||||
packet.onReceive(&m_buffer[0], received);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2007-2013 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.
|
||||
@@ -25,48 +25,56 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/SocketHelper.hpp>
|
||||
#include <SFML/Network/Unix/SocketImpl.hpp>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Return the value of the invalid socket
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::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;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Close / destroy a socket
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketHelper::Close(SocketHelper::SocketType Socket)
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
return close(Socket) != -1;
|
||||
::close(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set a socket as blocking or non-blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketHelper::SetBlocking(SocketHelper::SocketType Socket, bool Block)
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
int Status = fcntl(Socket, F_GETFL);
|
||||
if (Block)
|
||||
fcntl(Socket, F_SETFL, Status & ~O_NONBLOCK);
|
||||
int status = fcntl(sock, F_GETFL);
|
||||
if (block)
|
||||
fcntl(sock, F_SETFL, status & ~O_NONBLOCK);
|
||||
else
|
||||
fcntl(Socket, F_SETFL, Status | O_NONBLOCK);
|
||||
fcntl(sock, F_SETFL, status | O_NONBLOCK);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketHelper::GetErrorStatus()
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
// The followings are sometimes equal to EWOULDBLOCK,
|
||||
// so we have to make a special case for them in order
|
||||
@@ -82,8 +90,11 @@ Socket::Status SocketHelper::GetErrorStatus()
|
||||
case ETIMEDOUT : return Socket::Disconnected;
|
||||
case ENETRESET : return Socket::Disconnected;
|
||||
case ENOTCONN : return Socket::Disconnected;
|
||||
case EPIPE : return Socket::Disconnected;
|
||||
default : return Socket::Error;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
109
Externals/SFML/src/SFML/Network/Unix/SocketImpl.hpp
vendored
Normal file
109
Externals/SFML/src/SFML/Network/Unix/SocketImpl.hpp
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Unix version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef socklen_t AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
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
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
||||
@@ -1,7 +1,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
// Copyright (C) 2007-2013 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.
|
||||
@@ -25,52 +25,62 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Network/SocketHelper.hpp>
|
||||
#include <SFML/Network/Win32/SocketImpl.hpp>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Return the value of the invalid socket
|
||||
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
std::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;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Close / destroy a socket
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SocketHelper::Close(SocketHelper::SocketType Socket)
|
||||
void SocketImpl::close(SocketHandle sock)
|
||||
{
|
||||
return closesocket(Socket) != -1;
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set a socket as blocking or non-blocking
|
||||
////////////////////////////////////////////////////////////
|
||||
void SocketHelper::SetBlocking(SocketHelper::SocketType Socket, bool Block)
|
||||
void SocketImpl::setBlocking(SocketHandle sock, bool block)
|
||||
{
|
||||
unsigned long Blocking = Block ? 0 : 1;
|
||||
ioctlsocket(Socket, FIONBIO, &Blocking);
|
||||
u_long blocking = block ? 0 : 1;
|
||||
ioctlsocket(sock, FIONBIO, &blocking);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the last socket error status
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketHelper::GetErrorStatus()
|
||||
Socket::Status SocketImpl::getErrorStatus()
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
case WSAEWOULDBLOCK : return Socket::NotReady;
|
||||
case WSAEALREADY : return Socket::NotReady;
|
||||
case WSAECONNABORTED : return Socket::Disconnected;
|
||||
case WSAECONNRESET : return Socket::Disconnected;
|
||||
case WSAETIMEDOUT : return Socket::Disconnected;
|
||||
case WSAENETRESET : return Socket::Disconnected;
|
||||
case WSAENOTCONN : return Socket::Disconnected;
|
||||
case WSAEISCONN : return Socket::Done; // when connecting a non-blocking socket
|
||||
default : return Socket::Error;
|
||||
}
|
||||
}
|
||||
@@ -85,8 +95,8 @@ struct SocketInitializer
|
||||
{
|
||||
SocketInitializer()
|
||||
{
|
||||
WSADATA InitData;
|
||||
WSAStartup(MAKEWORD(2,2), &InitData);
|
||||
WSADATA init;
|
||||
WSAStartup(MAKEWORD(2, 2), &init);
|
||||
}
|
||||
|
||||
~SocketInitializer()
|
||||
@@ -95,6 +105,8 @@ struct SocketInitializer
|
||||
}
|
||||
};
|
||||
|
||||
SocketInitializer GlobalInitializer;
|
||||
SocketInitializer globalInitializer;
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
112
Externals/SFML/src/SFML/Network/Win32/SocketImpl.hpp
vendored
Normal file
112
Externals/SFML/src/SFML/Network/Win32/SocketImpl.hpp
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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_SOCKETIMPL_HPP
|
||||
#define SFML_SOCKETIMPL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#ifdef _WIN32_WINDOWS
|
||||
#undef _WIN32_WINDOWS
|
||||
#endif
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
#define _WIN32_WINDOWS 0x0501
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#include <SFML/Network/Socket.hpp>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Helper class implementing all the non-portable
|
||||
/// socket stuff; this is the Windows version
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SocketImpl
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef int AddrLength;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create an internal sockaddr_in address
|
||||
///
|
||||
/// \param address Target address
|
||||
/// \param port Target port
|
||||
///
|
||||
/// \return sockaddr_in ready to be used by socket functions
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static sockaddr_in createAddress(Uint32 address, unsigned short port);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the value of the invalid socket
|
||||
///
|
||||
/// \return Special value of the invalid socket
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static SocketHandle invalidSocket();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Close and destroy a socket
|
||||
///
|
||||
/// \param sock Handle of the socket to close
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
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
|
||||
///
|
||||
/// \return Status corresponding to the last socket error
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Socket::Status getErrorStatus();
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_SOCKETIMPL_HPP
|
||||
110
Externals/SFML/src/SFML/System/Err.cpp
vendored
Normal file
110
Externals/SFML/src/SFML/System/Err.cpp
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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/System/Err.hpp>
|
||||
#include <streambuf>
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// This class will be used as the default streambuf of sf::Err,
|
||||
// it outputs to stderr by default (to keep the default behaviour)
|
||||
class DefaultErrStreamBuf : public std::streambuf
|
||||
{
|
||||
public :
|
||||
|
||||
DefaultErrStreamBuf()
|
||||
{
|
||||
// Allocate the write buffer
|
||||
static const int size = 64;
|
||||
char* buffer = new char[size];
|
||||
setp(buffer, buffer + size);
|
||||
}
|
||||
|
||||
~DefaultErrStreamBuf()
|
||||
{
|
||||
// Synchronize
|
||||
sync();
|
||||
|
||||
// Delete the write buffer
|
||||
delete[] pbase();
|
||||
}
|
||||
|
||||
private :
|
||||
|
||||
virtual int overflow(int character)
|
||||
{
|
||||
if ((character != EOF) && (pptr() != epptr()))
|
||||
{
|
||||
// Valid character
|
||||
return sputc(static_cast<char>(character));
|
||||
}
|
||||
else if (character != EOF)
|
||||
{
|
||||
// Not enough space in the buffer: synchronize output and try again
|
||||
sync();
|
||||
return overflow(character);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid character: synchronize output
|
||||
return sync();
|
||||
}
|
||||
}
|
||||
|
||||
virtual int sync()
|
||||
{
|
||||
// Check if there is something into the write buffer
|
||||
if (pbase() != pptr())
|
||||
{
|
||||
// Print the contents of the write buffer into the standard error output
|
||||
std::size_t size = static_cast<int>(pptr() - pbase());
|
||||
fwrite(pbase(), 1, size, stderr);
|
||||
|
||||
// Reset the pointer position to the beginning of the write buffer
|
||||
setp(pbase(), epptr());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
std::ostream& err()
|
||||
{
|
||||
static DefaultErrStreamBuf buffer;
|
||||
static std::ostream stream(&buffer);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sf
|
||||
335
Externals/SFML/src/SFML/System/String.cpp
vendored
Normal file
335
Externals/SFML/src/SFML/System/String.cpp
vendored
Normal file
@@ -0,0 +1,335 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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/System/String.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(char ansiChar, const std::locale& locale)
|
||||
{
|
||||
m_string += Utf32::decodeAnsi(ansiChar, locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(wchar_t wideChar)
|
||||
{
|
||||
m_string += Utf32::decodeWide(wideChar);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(Uint32 utf32Char)
|
||||
{
|
||||
m_string += utf32Char;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const char* ansiString, const std::locale& locale)
|
||||
{
|
||||
if (ansiString)
|
||||
{
|
||||
std::size_t length = strlen(ansiString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::string& ansiString, const std::locale& locale)
|
||||
{
|
||||
m_string.reserve(ansiString.length() + 1);
|
||||
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const wchar_t* wideString)
|
||||
{
|
||||
if (wideString)
|
||||
{
|
||||
std::size_t length = std::wcslen(wideString);
|
||||
if (length > 0)
|
||||
{
|
||||
m_string.reserve(length + 1);
|
||||
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::wstring& wideString)
|
||||
{
|
||||
m_string.reserve(wideString.length() + 1);
|
||||
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const Uint32* utf32String)
|
||||
{
|
||||
if (utf32String)
|
||||
m_string = utf32String;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const std::basic_string<Uint32>& utf32String) :
|
||||
m_string(utf32String)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::String(const String& copy) :
|
||||
m_string(copy.m_string)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::string() const
|
||||
{
|
||||
return toAnsiString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::operator std::wstring() const
|
||||
{
|
||||
return toWideString();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string String::toAnsiString(const std::locale& locale) const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::string output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::wstring String::toWideString() const
|
||||
{
|
||||
// Prepare the output string
|
||||
std::wstring output;
|
||||
output.reserve(m_string.length() + 1);
|
||||
|
||||
// Convert
|
||||
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator =(const String& right)
|
||||
{
|
||||
m_string = right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String& String::operator +=(const String& right)
|
||||
{
|
||||
m_string += right.m_string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 String::operator [](std::size_t index) const
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32& String::operator [](std::size_t index)
|
||||
{
|
||||
return m_string[index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::clear()
|
||||
{
|
||||
m_string.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::getSize() const
|
||||
{
|
||||
return m_string.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool String::isEmpty() const
|
||||
{
|
||||
return m_string.empty();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::erase(std::size_t position, std::size_t count)
|
||||
{
|
||||
m_string.erase(position, count);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void String::insert(std::size_t position, const String& str)
|
||||
{
|
||||
m_string.insert(position, str.m_string);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
std::size_t String::find(const String& str, std::size_t start) const
|
||||
{
|
||||
return m_string.find(str.m_string, start);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Uint32* String::getData() const
|
||||
{
|
||||
return m_string.c_str();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::begin()
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::begin() const
|
||||
{
|
||||
return m_string.begin();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::Iterator String::end()
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String::ConstIterator String::end() const
|
||||
{
|
||||
return m_string.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string == right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(const String& left, const String& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(const String& left, const String& right)
|
||||
{
|
||||
return left.m_string < right.m_string;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(const String& left, const String& right)
|
||||
{
|
||||
return right < left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(const String& left, const String& right)
|
||||
{
|
||||
return !(right < left);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(const String& left, const String& right)
|
||||
{
|
||||
return !(left < right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
String operator +(const String& left, const String& right)
|
||||
{
|
||||
String string = left;
|
||||
string += right;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
239
Externals/SFML/src/SFML/System/Time.cpp
vendored
Normal file
239
Externals/SFML/src/SFML/System/Time.cpp
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2013 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/System/Time.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
const Time Time::Zero;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time::Time() :
|
||||
m_microseconds(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
float Time::asSeconds() const
|
||||
{
|
||||
return m_microseconds / 1000000.f;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int32 Time::asMilliseconds() const
|
||||
{
|
||||
return static_cast<Int32>(m_microseconds / 1000);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Int64 Time::asMicroseconds() const
|
||||
{
|
||||
return m_microseconds;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time::Time(Int64 microseconds) :
|
||||
m_microseconds(microseconds)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time seconds(float amount)
|
||||
{
|
||||
return Time(static_cast<Int64>(amount * 1000000));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time milliseconds(Int32 amount)
|
||||
{
|
||||
return Time(static_cast<Int64>(amount) * 1000);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time microseconds(Int64 amount)
|
||||
{
|
||||
return Time(amount);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator ==(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() == right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator !=(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() != right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() < right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() > right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator <=(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() <= right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool operator >=(Time left, Time right)
|
||||
{
|
||||
return left.asMicroseconds() >= right.asMicroseconds();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator -(Time right)
|
||||
{
|
||||
return microseconds(-right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator +(Time left, Time right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() + right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator +=(Time& left, Time right)
|
||||
{
|
||||
return left = left + right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator -(Time left, Time right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() - right.asMicroseconds());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator -=(Time& left, Time right)
|
||||
{
|
||||
return left = left - right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(Time left, float right)
|
||||
{
|
||||
return seconds(left.asSeconds() * right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(Time left, Int64 right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() * right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(float left, Time right)
|
||||
{
|
||||
return right * left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator *(Int64 left, Time right)
|
||||
{
|
||||
return right * left;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator *=(Time& left, float right)
|
||||
{
|
||||
return left = left * right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator *=(Time& left, Int64 right)
|
||||
{
|
||||
return left = left * right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator /(Time left, float right)
|
||||
{
|
||||
return seconds(left.asSeconds() / right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time operator /(Time left, Int64 right)
|
||||
{
|
||||
return microseconds(left.asMicroseconds() / right);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator /=(Time& left, float right)
|
||||
{
|
||||
return left = left / right;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Time& operator /=(Time& left, Int64 right)
|
||||
{
|
||||
return left = left / right;
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
Reference in New Issue
Block a user